diff --git a/.gitignore b/.gitignore index 61f7b68..8c7863e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,367 +1,43 @@ -.idea/.gitignore -.idea/compiler.xml -.idea/encodings.xml -.idea/jarRepositories.xml -.idea/misc.xml -.idea/vcs.xml -target/formatter-maven-cache.properties -target/impsort-maven-cache.properties -target/jacoco-quarkus.exec -target/classes/application.properties -target/classes/.openapi-generator/announcement-openapi-internal.yaml-internal.sha256 -target/classes/.openapi-generator/announcement-openapi-v1.yaml-v1.sha256 -target/classes/db/migration/V1.0.1__CreateTables.sql -target/classes/gen/io/github/onecx/announcement/rs/internal/AnnouncementInternalApi.class -target/classes/gen/io/github/onecx/announcement/rs/internal/model/AnnouncementDTO.class -target/classes/gen/io/github/onecx/announcement/rs/internal/model/AnnouncementPageResultDTO.class -target/classes/gen/io/github/onecx/announcement/rs/internal/model/AnnouncementPriorityTypeDTO.class -target/classes/gen/io/github/onecx/announcement/rs/internal/model/AnnouncementStatusDTO.class -target/classes/gen/io/github/onecx/announcement/rs/internal/model/AnnouncementTypeDTO.class -target/classes/gen/io/github/onecx/announcement/rs/internal/model/CreateAnnouncementRequestDTO.class -target/classes/gen/io/github/onecx/announcement/rs/internal/model/ProblemDetailInvalidParamDTO.class -target/classes/gen/io/github/onecx/announcement/rs/internal/model/ProblemDetailParamDTO.class -target/classes/gen/io/github/onecx/announcement/rs/internal/model/ProblemDetailResponseDTO.class -target/classes/gen/io/github/onecx/announcement/rs/internal/model/SearchAnnouncementRequestDTO.class -target/classes/gen/io/github/onecx/announcement/rs/internal/model/UpdateAnnouncementRequestDTO.class -target/classes/gen/io/github/onecx/announcement/v1/AnnouncementV1Api.class -target/classes/gen/io/github/onecx/announcement/v1/model/AnnouncementDTOV1.class -target/classes/gen/io/github/onecx/announcement/v1/model/AnnouncementPageResultDTOV1.class -target/classes/gen/io/github/onecx/announcement/v1/model/AnnouncementPriorityTypeDTOV1.class -target/classes/gen/io/github/onecx/announcement/v1/model/AnnouncementStatusDTOV1.class -target/classes/gen/io/github/onecx/announcement/v1/model/AnnouncementTypeDTOV1.class -target/classes/gen/io/github/onecx/announcement/v1/model/DeleteAnnouncementRequestDTOV1.class -target/classes/gen/io/github/onecx/announcement/v1/model/ProblemDetailInvalidParamDTOV1.class -target/classes/gen/io/github/onecx/announcement/v1/model/ProblemDetailParamDTOV1.class -target/classes/gen/io/github/onecx/announcement/v1/model/ProblemDetailResponseDTOV1.class -target/classes/gen/io/github/onecx/announcement/v1/model/SearchAnnouncementRequestDTOV1.class -target/classes/META-INF/panache-archive.marker -target/classes/org/onecx/announcement/domain/dao/AnnouncementDAO.class -target/classes/org/onecx/announcement/domain/dao/AnnouncementDAO$ErrorKeys.class -target/classes/org/onecx/announcement/domain/models/Announcement_.class -target/classes/org/onecx/announcement/domain/models/Announcement.class -target/classes/org/onecx/announcement/rs/internal/controller/ApplicationControllerInternal.class -target/classes/org/onecx/announcement/rs/internal/mapper/AnnouncementMapper.class -target/classes/org/onecx/announcement/rs/internal/mapper/AnnouncementMapperImpl.class -target/classes/org/onecx/announcement/rs/v1/controller/AnnouncementControllerV1.class -target/classes/org/onecx/announcement/rs/v1/controller/ErrorKeys.class -target/classes/org/onecx/announcement/rs/v1/mapper/AnnouncementMapperV1.class -target/classes/org/onecx/announcement/rs/v1/mapper/AnnouncementMapperV1Impl.class -target/generated-sources/annotations/org/onecx/announcement/domain/models/Announcement_.java -target/generated-sources/annotations/org/onecx/announcement/rs/internal/mapper/AnnouncementMapperImpl.java -target/generated-sources/annotations/org/onecx/announcement/rs/v1/mapper/AnnouncementMapperV1Impl.java -target/generated-sources/openapi/.openapi-generator/announcement-openapi-internal.yaml-internal.sha256 -target/generated-sources/openapi/.openapi-generator/announcement-openapi-v1.yaml-v1.sha256 -target/generated-sources/openapi/gen/io/github/onecx/announcement/rs/internal/AnnouncementInternalApi.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/rs/internal/model/AnnouncementDTO.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/rs/internal/model/AnnouncementPageResultDTO.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/rs/internal/model/AnnouncementPriorityTypeDTO.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/rs/internal/model/AnnouncementStatusDTO.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/rs/internal/model/AnnouncementTypeDTO.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/rs/internal/model/CreateAnnouncementRequestDTO.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/rs/internal/model/ProblemDetailInvalidParamDTO.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/rs/internal/model/ProblemDetailParamDTO.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/rs/internal/model/ProblemDetailResponseDTO.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/rs/internal/model/SearchAnnouncementRequestDTO.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/rs/internal/model/UpdateAnnouncementRequestDTO.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/v1/AnnouncementV1Api.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/v1/model/AnnouncementDTOV1.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/v1/model/AnnouncementPageResultDTOV1.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/v1/model/AnnouncementPriorityTypeDTOV1.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/v1/model/AnnouncementStatusDTOV1.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/v1/model/AnnouncementTypeDTOV1.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/v1/model/DeleteAnnouncementRequestDTOV1.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/v1/model/ProblemDetailInvalidParamDTOV1.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/v1/model/ProblemDetailParamDTOV1.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/v1/model/ProblemDetailResponseDTOV1.java -target/generated-sources/openapi/gen/io/github/onecx/announcement/v1/model/SearchAnnouncementRequestDTOV1.java -target/jacoco-report/index.html -target/jacoco-report/jacoco-sessions.html -target/jacoco-report/jacoco.csv -target/jacoco-report/jacoco.xml -target/jacoco-report/jacoco-resources/branchfc.gif -target/jacoco-report/jacoco-resources/branchnc.gif -target/jacoco-report/jacoco-resources/branchpc.gif -target/jacoco-report/jacoco-resources/bundle.gif -target/jacoco-report/jacoco-resources/class.gif -target/jacoco-report/jacoco-resources/down.gif -target/jacoco-report/jacoco-resources/greenbar.gif -target/jacoco-report/jacoco-resources/group.gif -target/jacoco-report/jacoco-resources/method.gif -target/jacoco-report/jacoco-resources/package.gif -target/jacoco-report/jacoco-resources/prettify.css -target/jacoco-report/jacoco-resources/prettify.js -target/jacoco-report/jacoco-resources/redbar.gif -target/jacoco-report/jacoco-resources/report.css -target/jacoco-report/jacoco-resources/report.gif -target/jacoco-report/jacoco-resources/session.gif -target/jacoco-report/jacoco-resources/sort.gif -target/jacoco-report/jacoco-resources/sort.js -target/jacoco-report/jacoco-resources/source.gif -target/jacoco-report/jacoco-resources/up.gif -target/jacoco-report/org.onecx.announcement.domain.dao/AnnouncementDAO.html -target/jacoco-report/org.onecx.announcement.domain.dao/AnnouncementDAO.java.html -target/jacoco-report/org.onecx.announcement.domain.dao/AnnouncementDAO$ErrorKeys.html -target/jacoco-report/org.onecx.announcement.domain.dao/index.html -target/jacoco-report/org.onecx.announcement.domain.dao/index.source.html -target/jacoco-report/org.onecx.announcement.rs.internal.controller/ApplicationControllerInternal.html -target/jacoco-report/org.onecx.announcement.rs.internal.controller/ApplicationControllerInternal.java.html -target/jacoco-report/org.onecx.announcement.rs.internal.controller/index.html -target/jacoco-report/org.onecx.announcement.rs.internal.controller/index.source.html -target/jacoco-report/org.onecx.announcement.rs.v1.controller/AnnouncementControllerV1.html -target/jacoco-report/org.onecx.announcement.rs.v1.controller/AnnouncementControllerV1.java.html -target/jacoco-report/org.onecx.announcement.rs.v1.controller/ErrorKeys.html -target/jacoco-report/org.onecx.announcement.rs.v1.controller/ErrorKeys.java.html -target/jacoco-report/org.onecx.announcement.rs.v1.controller/index.html -target/jacoco-report/org.onecx.announcement.rs.v1.controller/index.source.html -target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst -target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst -target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst -target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst -target/quarkus/bootstrap/test-app-model.dat -target/surefire-reports/org.onecx.announcement.rs.external.v1.AnnouncementExternalControllerTest.txt -target/surefire-reports/org.onecx.announcement.rs.internal.AnnouncementAPITest.txt -target/surefire-reports/TEST-org.onecx.announcement.rs.external.v1.AnnouncementExternalControllerTest.xml -target/surefire-reports/TEST-org.onecx.announcement.rs.internal.AnnouncementAPITest.xml -target/test-classes/ahm-testdata.xml -target/test-classes/META-INF/panache-archive.marker -target/test-classes/META-INF/resources/test_privateKey.pem -target/test-classes/META-INF/resources/test_publicKey.pem -target/test-classes/META-INF/resources/test_tokens/admin_token.json -target/test-classes/META-INF/resources/test_tokens/non_admin_token.json -target/test-classes/org/onecx/announcement/rs/external/v1/AnnouncementExternalControllerTest.class -target/test-classes/org/onecx/announcement/rs/external/v1/AnnouncementExternalControllerTestIT.class -target/test-classes/org/onecx/announcement/rs/internal/AnnouncementAPITest.class -target/test-classes/org/onecx/announcement/rs/internal/AnnouncementItemAPITestIT.class -target/test-classes/org/onecx/announcement/rs/test/AbstractTest.class -.idea/sonarlint/issuestore/index.pb -.idea/sonarlint/issuestore/0/2/02b0356ea4751bc0b87007849bf76e3e1879fa92 -.idea/sonarlint/issuestore/0/e/0ec43cacf30b15c12fadd38167bf03c824f9409a -.idea/sonarlint/issuestore/2/d/2d1ba447f7d64cd13f9b3f90edc4193dc656e410 -.idea/sonarlint/issuestore/4/1/4143058a2a87c98bc41c49c23b3265696c2315d3 -.idea/sonarlint/issuestore/4/4/442292b8a7efeabbe4cc176709b833b1792140ec -.idea/sonarlint/issuestore/8/e/8ea91b85564d1bba5673a8e45f43f94b8be6edae -.idea/sonarlint/issuestore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d -.idea/sonarlint/issuestore/9/3/93274201e44a81754526f7033380fffb1581e547 -.idea/sonarlint/issuestore/9/4/949eab112e3e5bd22120ac0e1f06401ff4500c2c -.idea/sonarlint/issuestore/9/8/9815df64f8f563326bd3133bf3962ff49fb3a9e7 -.idea/sonarlint/issuestore/b/8/b8e28853d4a0fa4fcf35ffceb8d93ddd7cd62ac3 -.idea/sonarlint/issuestore/d/2/d27f8af4262dc89f85141bd5d57b8dcf5fa4a225 -.idea/sonarlint/securityhotspotstore/index.pb -.idea/sonarlint/securityhotspotstore/0/2/02b0356ea4751bc0b87007849bf76e3e1879fa92 -.idea/sonarlint/securityhotspotstore/0/e/0ec43cacf30b15c12fadd38167bf03c824f9409a -.idea/sonarlint/securityhotspotstore/2/d/2d1ba447f7d64cd13f9b3f90edc4193dc656e410 -.idea/sonarlint/securityhotspotstore/4/1/4143058a2a87c98bc41c49c23b3265696c2315d3 -.idea/sonarlint/securityhotspotstore/4/4/442292b8a7efeabbe4cc176709b833b1792140ec -.idea/sonarlint/securityhotspotstore/8/e/8ea91b85564d1bba5673a8e45f43f94b8be6edae -.idea/sonarlint/securityhotspotstore/8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d -.idea/sonarlint/securityhotspotstore/9/3/93274201e44a81754526f7033380fffb1581e547 -.idea/sonarlint/securityhotspotstore/9/4/949eab112e3e5bd22120ac0e1f06401ff4500c2c -.idea/sonarlint/securityhotspotstore/9/8/9815df64f8f563326bd3133bf3962ff49fb3a9e7 -.idea/sonarlint/securityhotspotstore/b/8/b8e28853d4a0fa4fcf35ffceb8d93ddd7cd62ac3 -.idea/sonarlint/securityhotspotstore/d/2/d27f8af4262dc89f85141bd5d57b8dcf5fa4a225 -target/onecx-announcement-svc-999-SNAPSHOT.jar -target/quarkus-artifact.properties -target/maven-archiver/pom.properties -target/quarkus-app/quarkus-app-dependencies.txt -target/quarkus-app/quarkus-run.jar -target/quarkus-app/app/onecx-announcement-svc-999-SNAPSHOT.jar -target/quarkus-app/lib/boot/io.github.crac.org-crac-0.1.3.jar -target/quarkus-app/lib/boot/io.quarkus.quarkus-bootstrap-runner-3.5.1.jar -target/quarkus-app/lib/boot/io.quarkus.quarkus-development-mode-spi-3.5.1.jar -target/quarkus-app/lib/boot/io.quarkus.quarkus-vertx-latebound-mdc-provider-3.5.1.jar -target/quarkus-app/lib/boot/io.smallrye.common.smallrye-common-constraint-2.1.2.jar -target/quarkus-app/lib/boot/io.smallrye.common.smallrye-common-cpu-2.1.2.jar -target/quarkus-app/lib/boot/io.smallrye.common.smallrye-common-expression-2.1.2.jar -target/quarkus-app/lib/boot/io.smallrye.common.smallrye-common-function-2.1.2.jar -target/quarkus-app/lib/boot/io.smallrye.common.smallrye-common-io-2.1.2.jar -target/quarkus-app/lib/boot/io.smallrye.common.smallrye-common-net-2.1.2.jar -target/quarkus-app/lib/boot/io.smallrye.common.smallrye-common-os-2.1.2.jar -target/quarkus-app/lib/boot/io.smallrye.common.smallrye-common-ref-2.1.2.jar -target/quarkus-app/lib/boot/org.jboss.logging.jboss-logging-3.5.3.Final.jar -target/quarkus-app/lib/boot/org.jboss.logmanager.jboss-logmanager-3.0.2.Final.jar -target/quarkus-app/lib/main/com.aayushatharva.brotli4j.brotli4j-1.12.0.jar -target/quarkus-app/lib/main/com.aayushatharva.brotli4j.native-linux-x86_64-1.12.0.jar -target/quarkus-app/lib/main/com.aayushatharva.brotli4j.service-1.12.0.jar -target/quarkus-app/lib/main/com.fasterxml.classmate-1.5.1.jar -target/quarkus-app/lib/main/com.fasterxml.jackson.core.jackson-annotations-2.15.2.jar -target/quarkus-app/lib/main/com.fasterxml.jackson.core.jackson-core-2.15.2.jar -target/quarkus-app/lib/main/com.fasterxml.jackson.core.jackson-databind-2.15.2.jar -target/quarkus-app/lib/main/com.fasterxml.jackson.dataformat.jackson-dataformat-toml-2.15.2.jar -target/quarkus-app/lib/main/com.fasterxml.jackson.dataformat.jackson-dataformat-yaml-2.15.2.jar -target/quarkus-app/lib/main/com.fasterxml.jackson.datatype.jackson-datatype-jdk8-2.15.2.jar -target/quarkus-app/lib/main/com.fasterxml.jackson.datatype.jackson-datatype-jsr310-2.15.2.jar -target/quarkus-app/lib/main/com.fasterxml.jackson.module.jackson-module-parameter-names-2.15.2.jar -target/quarkus-app/lib/main/com.github.ben-manes.caffeine.caffeine-3.1.5.jar -target/quarkus-app/lib/main/com.google.code.gson.gson-2.10.1.jar -target/quarkus-app/lib/main/com.google.errorprone.error_prone_annotations-2.22.0.jar -target/quarkus-app/lib/main/com.sun.istack.istack-commons-runtime-4.1.2.jar -target/quarkus-app/lib/main/io.agroal.agroal-api-2.1.jar -target/quarkus-app/lib/main/io.agroal.agroal-narayana-2.1.jar -target/quarkus-app/lib/main/io.agroal.agroal-pool-2.1.jar -target/quarkus-app/lib/main/io.netty.netty-buffer-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-codec-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-codec-dns-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-codec-haproxy-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-codec-http-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-codec-http2-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-codec-socks-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-common-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-handler-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-handler-proxy-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-resolver-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-resolver-dns-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-transport-4.1.100.Final.jar -target/quarkus-app/lib/main/io.netty.netty-transport-native-unix-common-4.1.100.Final.jar -target/quarkus-app/lib/main/io.quarkus.arc.arc-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-agroal-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-arc-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-caffeine-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-container-image-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-container-image-docker-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-core-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-credentials-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-datasource-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-datasource-common-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-flyway-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-fs-util-0.0.9.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-hibernate-orm-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-hibernate-validator-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-jackson-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-jaxrs-client-reactive-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-jdbc-postgresql-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-jsonp-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-mutiny-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-narayana-jta-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-netty-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-rest-client-config-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-rest-client-reactive-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-resteasy-reactive-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-resteasy-reactive-common-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-resteasy-reactive-jackson-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-resteasy-reactive-jackson-common-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-security-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-security-runtime-spi-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-smallrye-context-propagation-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-smallrye-health-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-smallrye-jwt-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-smallrye-jwt-build-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-smallrye-openapi-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-smallrye-stork-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-swagger-ui-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-transaction-annotations-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-vertx-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-vertx-http-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.quarkus-virtual-threads-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.resteasy.reactive.resteasy-reactive-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.resteasy.reactive.resteasy-reactive-client-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.resteasy.reactive.resteasy-reactive-common-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.resteasy.reactive.resteasy-reactive-common-types-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.resteasy.reactive.resteasy-reactive-jackson-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.resteasy.reactive.resteasy-reactive-vertx-3.5.1.jar -target/quarkus-app/lib/main/io.quarkus.security.quarkus-security-2.0.2.Final.jar -target/quarkus-app/lib/main/io.smallrye.common.smallrye-common-annotation-2.1.2.jar -target/quarkus-app/lib/main/io.smallrye.common.smallrye-common-classloader-2.1.2.jar -target/quarkus-app/lib/main/io.smallrye.common.smallrye-common-vertx-context-2.1.2.jar -target/quarkus-app/lib/main/io.smallrye.config.smallrye-config-3.4.1.jar -target/quarkus-app/lib/main/io.smallrye.config.smallrye-config-common-3.4.1.jar -target/quarkus-app/lib/main/io.smallrye.config.smallrye-config-core-3.4.1.jar -target/quarkus-app/lib/main/io.smallrye.config.smallrye-config-validator-3.4.1.jar -target/quarkus-app/lib/main/io.smallrye.jandex-3.1.5.jar -target/quarkus-app/lib/main/io.smallrye.reactive.mutiny-2.5.1.jar -target/quarkus-app/lib/main/io.smallrye.reactive.mutiny-smallrye-context-propagation-2.5.1.jar -target/quarkus-app/lib/main/io.smallrye.reactive.mutiny-zero-flow-adapters-1.0.0.jar -target/quarkus-app/lib/main/io.smallrye.reactive.smallrye-mutiny-vertx-auth-common-3.7.2.jar -target/quarkus-app/lib/main/io.smallrye.reactive.smallrye-mutiny-vertx-bridge-common-3.7.2.jar -target/quarkus-app/lib/main/io.smallrye.reactive.smallrye-mutiny-vertx-core-3.7.2.jar -target/quarkus-app/lib/main/io.smallrye.reactive.smallrye-mutiny-vertx-runtime-3.7.2.jar -target/quarkus-app/lib/main/io.smallrye.reactive.smallrye-mutiny-vertx-uri-template-3.7.2.jar -target/quarkus-app/lib/main/io.smallrye.reactive.smallrye-mutiny-vertx-web-3.7.2.jar -target/quarkus-app/lib/main/io.smallrye.reactive.smallrye-mutiny-vertx-web-common-3.7.2.jar -target/quarkus-app/lib/main/io.smallrye.reactive.smallrye-reactive-converter-api-3.0.1.jar -target/quarkus-app/lib/main/io.smallrye.reactive.smallrye-reactive-converter-mutiny-3.0.1.jar -target/quarkus-app/lib/main/io.smallrye.reactive.vertx-mutiny-generator-3.7.2.jar -target/quarkus-app/lib/main/io.smallrye.smallrye-context-propagation-2.1.0.jar -target/quarkus-app/lib/main/io.smallrye.smallrye-context-propagation-api-2.1.0.jar -target/quarkus-app/lib/main/io.smallrye.smallrye-context-propagation-jta-2.1.0.jar -target/quarkus-app/lib/main/io.smallrye.smallrye-context-propagation-storage-2.1.0.jar -target/quarkus-app/lib/main/io.smallrye.smallrye-fault-tolerance-vertx-6.2.6.jar -target/quarkus-app/lib/main/io.smallrye.smallrye-health-4.0.4.jar -target/quarkus-app/lib/main/io.smallrye.smallrye-health-api-4.0.4.jar -target/quarkus-app/lib/main/io.smallrye.smallrye-health-provided-checks-4.0.4.jar -target/quarkus-app/lib/main/io.smallrye.smallrye-jwt-4.3.1.jar -target/quarkus-app/lib/main/io.smallrye.smallrye-jwt-build-4.3.1.jar -target/quarkus-app/lib/main/io.smallrye.smallrye-jwt-common-4.3.1.jar -target/quarkus-app/lib/main/io.smallrye.smallrye-open-api-core-3.7.0.jar -target/quarkus-app/lib/main/io.smallrye.stork.stork-api-2.3.1.jar -target/quarkus-app/lib/main/io.smallrye.stork.stork-core-2.3.1.jar -target/quarkus-app/lib/main/io.vertx.vertx-auth-common-4.4.6.jar -target/quarkus-app/lib/main/io.vertx.vertx-bridge-common-4.4.6.jar -target/quarkus-app/lib/main/io.vertx.vertx-codegen-4.4.6.jar -target/quarkus-app/lib/main/io.vertx.vertx-core-4.4.6.jar -target/quarkus-app/lib/main/io.vertx.vertx-uri-template-4.4.6.jar -target/quarkus-app/lib/main/io.vertx.vertx-web-4.4.6.jar -target/quarkus-app/lib/main/io.vertx.vertx-web-client-4.4.6.jar -target/quarkus-app/lib/main/io.vertx.vertx-web-common-4.4.6.jar -target/quarkus-app/lib/main/jakarta.activation.jakarta.activation-api-2.1.2.jar -target/quarkus-app/lib/main/jakarta.annotation.jakarta.annotation-api-2.1.1.jar -target/quarkus-app/lib/main/jakarta.ejb.jakarta.ejb-api-4.0.1.jar -target/quarkus-app/lib/main/jakarta.el.jakarta.el-api-5.0.1.jar -target/quarkus-app/lib/main/jakarta.enterprise.jakarta.enterprise.cdi-api-4.0.1.jar -target/quarkus-app/lib/main/jakarta.enterprise.jakarta.enterprise.lang-model-4.0.1.jar -target/quarkus-app/lib/main/jakarta.inject.jakarta.inject-api-2.0.1.jar -target/quarkus-app/lib/main/jakarta.interceptor.jakarta.interceptor-api-2.1.0.jar -target/quarkus-app/lib/main/jakarta.json.jakarta.json-api-2.1.2.jar -target/quarkus-app/lib/main/jakarta.persistence.jakarta.persistence-api-3.1.0.jar -target/quarkus-app/lib/main/jakarta.resource.jakarta.resource-api-2.1.0.jar -target/quarkus-app/lib/main/jakarta.transaction.jakarta.transaction-api-2.0.1.jar -target/quarkus-app/lib/main/jakarta.validation.jakarta.validation-api-3.0.2.jar -target/quarkus-app/lib/main/jakarta.ws.rs.jakarta.ws.rs-api-3.1.0.jar -target/quarkus-app/lib/main/jakarta.xml.bind.jakarta.xml.bind-api-4.0.1.jar -target/quarkus-app/lib/main/javax.activation.javax.activation-api-1.2.0.jar -target/quarkus-app/lib/main/javax.xml.bind.jaxb-api-2.3.1.jar -target/quarkus-app/lib/main/net.bytebuddy.byte-buddy-1.14.7.jar -target/quarkus-app/lib/main/org.antlr.antlr4-runtime-4.10.1.jar -target/quarkus-app/lib/main/org.bitbucket.b_c.jose4j-0.9.3.jar -target/quarkus-app/lib/main/org.eclipse.angus.angus-activation-2.0.1.jar -target/quarkus-app/lib/main/org.eclipse.microprofile.config.microprofile-config-api-3.0.3.jar -target/quarkus-app/lib/main/org.eclipse.microprofile.context-propagation.microprofile-context-propagation-api-1.3.jar -target/quarkus-app/lib/main/org.eclipse.microprofile.health.microprofile-health-api-4.0.1.jar -target/quarkus-app/lib/main/org.eclipse.microprofile.jwt.microprofile-jwt-auth-api-2.1.jar -target/quarkus-app/lib/main/org.eclipse.microprofile.openapi.microprofile-openapi-api-3.1.1.jar -target/quarkus-app/lib/main/org.eclipse.microprofile.reactive-streams-operators.microprofile-reactive-streams-operators-api-3.0.jar -target/quarkus-app/lib/main/org.eclipse.microprofile.rest.client.microprofile-rest-client-api-3.0.1.jar -target/quarkus-app/lib/main/org.eclipse.parsson.parsson-1.1.4.jar -target/quarkus-app/lib/main/org.flywaydb.flyway-core-9.22.2.jar -target/quarkus-app/lib/main/org.glassfish.expressly.expressly-5.0.0.jar -target/quarkus-app/lib/main/org.glassfish.jaxb.jaxb-core-4.0.3.jar -target/quarkus-app/lib/main/org.glassfish.jaxb.jaxb-runtime-4.0.3.jar -target/quarkus-app/lib/main/org.glassfish.jaxb.txw2-4.0.3.jar -target/quarkus-app/lib/main/org.hibernate.common.hibernate-commons-annotations-6.0.6.Final.jar -target/quarkus-app/lib/main/org.hibernate.hibernate-jpamodelgen-5.5.6.jar -target/quarkus-app/lib/main/org.hibernate.orm.hibernate-core-6.2.13.Final.jar -target/quarkus-app/lib/main/org.hibernate.orm.hibernate-graalvm-6.2.13.Final.jar -target/quarkus-app/lib/main/org.hibernate.quarkus-local-cache-0.2.1.jar -target/quarkus-app/lib/main/org.hibernate.validator.hibernate-validator-8.0.1.Final.jar -target/quarkus-app/lib/main/org.jboss.invocation.jboss-invocation-2.0.0.Final.jar -target/quarkus-app/lib/main/org.jboss.jboss-transaction-spi-8.0.0.Final.jar -target/quarkus-app/lib/main/org.jboss.logging.commons-logging-jboss-logging-1.0.0.Final.jar -target/quarkus-app/lib/main/org.jboss.logging.jboss-logging-annotations-2.2.1.Final.jar -target/quarkus-app/lib/main/org.jboss.narayana.jta.narayana-jta-7.0.0.Final.jar -target/quarkus-app/lib/main/org.jboss.narayana.jts.narayana-jts-integration-7.0.0.Final.jar -target/quarkus-app/lib/main/org.jboss.slf4j.slf4j-jboss-logmanager-2.0.0.Final.jar -target/quarkus-app/lib/main/org.jboss.threads.jboss-threads-3.5.0.Final.jar -target/quarkus-app/lib/main/org.mapstruct.mapstruct-1.5.5.Final.jar -target/quarkus-app/lib/main/org.postgresql.postgresql-42.6.0.jar -target/quarkus-app/lib/main/org.reactivestreams.reactive-streams-1.0.4.jar -target/quarkus-app/lib/main/org.slf4j.slf4j-api-2.0.6.jar -target/quarkus-app/lib/main/org.tkit.quarkus.lib.tkit-quarkus-context-2.3.0.jar -target/quarkus-app/lib/main/org.tkit.quarkus.lib.tkit-quarkus-jpa-2.3.0.jar -target/quarkus-app/lib/main/org.tkit.quarkus.lib.tkit-quarkus-jpa-models-2.3.0.jar -target/quarkus-app/lib/main/org.tkit.quarkus.lib.tkit-quarkus-log-cdi-2.3.0.jar -target/quarkus-app/lib/main/org.tkit.quarkus.lib.tkit-quarkus-log-rs-2.3.0.jar -target/quarkus-app/lib/main/org.tkit.quarkus.lib.tkit-quarkus-rest-2.3.0.jar -target/quarkus-app/lib/main/org.wildfly.common.wildfly-common-1.5.4.Final-format-001.jar -target/quarkus-app/lib/main/org.yaml.snakeyaml-2.1.jar -target/quarkus-app/quarkus/generated-bytecode.jar -target/quarkus-app/quarkus/quarkus-application.dat -target/quarkus-app/quarkus/transformed-bytecode.jar +#Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +release.properties +.flattened-pom.xml + +# Eclipse +.project +.classpath +.settings/ +bin/ + +# IntelliJ +.idea +*.ipr +*.iml +*.iws + +# NetBeans +nb-configuration.xml + +# Visual Studio Code +.vscode +.factorypath + +# OSX +.DS_Store + +# Vim +*.swp +*.swo + +# patch +*.orig +*.rej + +# Local environment +.env + +# Plugin directory +/.quarkus/cli/plugins/ diff --git a/onecx-announcement-svc.iml b/onecx-announcement-svc.iml deleted file mode 100644 index a1585fa..0000000 --- a/onecx-announcement-svc.iml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index c8f5ef1..0b54f38 100644 --- a/pom.xml +++ b/pom.xml @@ -1,141 +1,140 @@ - - + + + 4.0.0 + io.github.onecx onecx-quarkus3-parent - 0.16.0 + 0.23.0 - org.onecx onecx-announcement-svc 999-SNAPSHOT - - 3.11.0 - 17 - UTF-8 - UTF-8 - quarkus-bom - io.quarkus.platform - 3.5.1 - true - 3.1.2 - - - - - ${quarkus.platform.group-id} - ${quarkus.platform.artifact-id} - ${quarkus.platform.version} - pom - import - - - + - - io.quarkus - quarkus-jdbc-postgresql + io.github.onecx.quarkus + onecx-tenant + - io.quarkus - quarkus-resteasy-reactive + org.tkit.quarkus.lib + tkit-quarkus-rest-context - io.quarkus - quarkus-resteasy-reactive-jackson + org.tkit.quarkus.lib + tkit-quarkus-jpa - io.quarkus - quarkus-hibernate-orm + org.tkit.quarkus.lib + tkit-quarkus-jpa-tenant - io.quarkus - quarkus-smallrye-jwt + org.tkit.quarkus.lib + tkit-quarkus-log-cdi - io.quarkus - quarkus-smallrye-openapi + org.tkit.quarkus.lib + tkit-quarkus-log-rs + + org.tkit.quarkus.lib + tkit-quarkus-log-json + + + org.tkit.quarkus.lib + tkit-quarkus-rest + + + io.quarkus - quarkus-flyway + quarkus-arc io.quarkus - quarkus-rest-client-reactive + quarkus-liquibase - - org.tkit.quarkus.lib - tkit-quarkus-rest + com.github.blagerweij + liquibase-sessionlock - org.tkit.quarkus.lib - tkit-quarkus-log-cdi + io.quarkus + quarkus-smallrye-health - org.tkit.quarkus.lib - tkit-quarkus-jpa + io.quarkus + quarkus-micrometer-registry-prometheus - org.tkit.quarkus.lib - tkit-quarkus-log-rs + io.quarkus + quarkus-hibernate-orm - - org.hibernate - hibernate-jpamodelgen - 5.5.6 + io.quarkus + quarkus-resteasy-reactive - org.mapstruct - mapstruct + io.quarkus + quarkus-resteasy-reactive-jackson - org.mapstruct - mapstruct-processor - 1.5.0.Final - provided + io.quarkus + quarkus-jdbc-postgresql - org.projectlombok - lombok + io.quarkus + quarkus-smallrye-context-propagation io.quarkus - quarkus-smallrye-health + quarkus-smallrye-openapi io.quarkus quarkus-hibernate-validator - - org.tkit.quarkus.lib - tkit-quarkus-test-db-import - - test + io.quarkus + quarkus-opentelemetry + + + + org.projectlombok + lombok + + + org.mapstruct + mapstruct + + + io.quarkus quarkus-junit5 test - org.assertj - assertj-core + io.quarkus + quarkus-junit5-mockito test - io.rest-assured rest-assured test + + org.tkit.quarkus.lib + tkit-quarkus-test-db-import + test + + @@ -188,26 +187,13 @@ gen.io.github.onecx.announcement.v1 gen.io.github.onecx.announcement.v1.model DTOV1 + V1Api true - - ${quarkus.platform.group-id} - quarkus-maven-plugin - ${quarkus.platform.version} - true - - - - build - generate-code - generate-code-tests - - - - + diff --git a/src/main/helm/Chart.yaml b/src/main/helm/Chart.yaml index 199e6f2..c166e8d 100644 --- a/src/main/helm/Chart.yaml +++ b/src/main/helm/Chart.yaml @@ -1,4 +1,4 @@ -apiVersion: v1 +apiVersion: v2 name: onecx-announcement-svc version: 0.0.0 appVersion: 0.0.0 diff --git a/src/main/helm/values.yaml b/src/main/helm/values.yaml index 2b35993..1bc3fee 100644 --- a/src/main/helm/values.yaml +++ b/src/main/helm/values.yaml @@ -1,6 +1,5 @@ app: image: repository: "onecx/onecx-announcement-svc" - tag: 999-SNAPSHOT db: enabled: true \ No newline at end of file diff --git a/src/main/java/io/github/onecx/announcement/domain/criteria/AnnouncementSearchCriteria.java b/src/main/java/io/github/onecx/announcement/domain/criteria/AnnouncementSearchCriteria.java new file mode 100644 index 0000000..9527d84 --- /dev/null +++ b/src/main/java/io/github/onecx/announcement/domain/criteria/AnnouncementSearchCriteria.java @@ -0,0 +1,36 @@ +package io.github.onecx.announcement.domain.criteria; + +import java.time.OffsetDateTime; + +import jakarta.validation.Valid; + +import io.github.onecx.announcement.domain.models.Announcement; +import io.quarkus.runtime.annotations.RegisterForReflection; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@RegisterForReflection +public class AnnouncementSearchCriteria { + + private Announcement.Type type; + + private Announcement.Priority priority; + + private Announcement.Status status; + + private @Valid OffsetDateTime startDateFrom; + + private @Valid OffsetDateTime startDateTo; + + private @Valid OffsetDateTime endDateFrom; + + private @Valid OffsetDateTime endDateTo; + + private @Valid String appId; + + private @Valid Integer pageNumber = 0; + + private @Valid Integer pageSize = 100; +} diff --git a/src/main/java/io/github/onecx/announcement/domain/daos/AnnouncementDAO.java b/src/main/java/io/github/onecx/announcement/domain/daos/AnnouncementDAO.java new file mode 100644 index 0000000..aa35b9f --- /dev/null +++ b/src/main/java/io/github/onecx/announcement/domain/daos/AnnouncementDAO.java @@ -0,0 +1,115 @@ +package io.github.onecx.announcement.domain.daos; + +import java.util.ArrayList; +import java.util.List; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.persistence.NoResultException; +import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.*; + +import org.tkit.quarkus.jpa.daos.AbstractDAO; +import org.tkit.quarkus.jpa.daos.Page; +import org.tkit.quarkus.jpa.daos.PageResult; +import org.tkit.quarkus.jpa.exceptions.DAOException; +import org.tkit.quarkus.jpa.models.AbstractTraceableEntity_; +import org.tkit.quarkus.jpa.models.TraceableEntity_; + +import io.github.onecx.announcement.domain.criteria.AnnouncementSearchCriteria; +import io.github.onecx.announcement.domain.models.Announcement; +import io.github.onecx.announcement.domain.models.Announcement_; +import lombok.extern.slf4j.Slf4j; + +@ApplicationScoped +@Slf4j +public class AnnouncementDAO extends AbstractDAO { + + // https://hibernate.atlassian.net/browse/HHH-16830#icft=HHH-16830 + @Override + public Announcement findById(Object id) throws DAOException { + try { + var cb = this.getEntityManager().getCriteriaBuilder(); + var cq = cb.createQuery(Announcement.class); + var root = cq.from(Announcement.class); + cq.where(cb.equal(root.get(TraceableEntity_.ID), id)); + return this.getEntityManager().createQuery(cq).getSingleResult(); + } catch (NoResultException nre) { + return null; + } catch (Exception e) { + throw new DAOException(ErrorKeys.FIND_ENTITY_BY_ID_FAILED, e, entityName, id); + } + } + + public PageResult loadAnnouncementByCriteria(AnnouncementSearchCriteria criteria) { + try { + CriteriaBuilder cb = getEntityManager().getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(Announcement.class); + Root root = cq.from(Announcement.class); + cq.select(root).distinct(true); + + List predicates = new ArrayList<>(); + if (criteria.getStatus() != null) { + predicates.add(root.get(Announcement_.STATUS).in(criteria.getStatus())); + } + if (criteria.getAppId() != null) { + predicates.add(cb.equal(root.get(Announcement_.APP_ID), criteria.getAppId())); + } + if (criteria.getStartDateFrom() != null) { + predicates.add(cb.greaterThanOrEqualTo(root.get(Announcement_.START_DATE), + criteria.getStartDateFrom().toLocalDateTime())); + } + if (criteria.getStartDateTo() != null) { + predicates.add(cb.lessThanOrEqualTo(root.get(Announcement_.START_DATE), + criteria.getStartDateTo().toLocalDateTime())); + } + if (criteria.getEndDateFrom() != null) { + predicates.add(cb.greaterThanOrEqualTo(root.get(Announcement_.END_DATE), + criteria.getEndDateFrom().toLocalDateTime())); + } + if (criteria.getEndDateTo() != null) { + predicates.add( + cb.lessThanOrEqualTo(root.get(Announcement_.END_DATE), criteria.getEndDateTo().toLocalDateTime())); + } + if (criteria.getPriority() != null) { + predicates.add(root.get(Announcement_.PRIORITY).in(criteria.getPriority())); + + } + if (criteria.getType() != null) { + predicates.add(root.get(Announcement_.TYPE).in(criteria.getType())); + + } + if (!predicates.isEmpty()) { + cq.where(cb.and(predicates.toArray(new Predicate[0]))); + } + + //do query and sort resultList by Priority and creation-date + cq.orderBy(cb.desc(root.get(AbstractTraceableEntity_.CREATION_DATE))); + return createPageQuery(cq, Page.of(criteria.getPageNumber(), criteria.getPageSize())).getPageResult(); + } catch (Exception ex) { + throw new DAOException(ErrorKeys.ERROR_LOAD_ANNOUNCEMENT_BY_CRITERIA, ex); + } + + } + + public List findApplicationsWithAnnouncements() { + try { + CriteriaBuilder cb = getEntityManager().getCriteriaBuilder(); + CriteriaQuery cq = cb.createTupleQuery(); + Root root = cq.from(Announcement.class); + cq.multiselect(root.get(Announcement_.APP_ID)); + cq.distinct(true); + List tupleResult = getEntityManager().createQuery(cq).getResultList(); + return tupleResult.stream().map(t -> (String) t.get(0)).toList(); + } catch (Exception ex) { + throw new DAOException(ErrorKeys.ERROR_FIND_APPLICATIONS_WITH_ANNOUNCEMENTS, ex); + } + } + + public enum ErrorKeys { + + FIND_ENTITY_BY_ID_FAILED, + ERROR_LOAD_ANNOUNCEMENT_BY_CRITERIA, + ERROR_FIND_APPLICATIONS_WITH_ANNOUNCEMENTS + } + +} diff --git a/src/main/java/org/onecx/announcement/domain/models/Announcement.java b/src/main/java/io/github/onecx/announcement/domain/models/Announcement.java similarity index 54% rename from src/main/java/org/onecx/announcement/domain/models/Announcement.java rename to src/main/java/io/github/onecx/announcement/domain/models/Announcement.java index 6e11a43..b5889e8 100644 --- a/src/main/java/org/onecx/announcement/domain/models/Announcement.java +++ b/src/main/java/io/github/onecx/announcement/domain/models/Announcement.java @@ -1,4 +1,4 @@ -package org.onecx.announcement.domain.models; +package io.github.onecx.announcement.domain.models; import java.time.LocalDateTime; @@ -8,11 +8,9 @@ import jakarta.persistence.Enumerated; import jakarta.persistence.Table; +import org.hibernate.annotations.TenantId; import org.tkit.quarkus.jpa.models.TraceableEntity; -import gen.io.github.onecx.announcement.rs.internal.model.AnnouncementPriorityTypeDTO; -import gen.io.github.onecx.announcement.rs.internal.model.AnnouncementStatusDTO; -import gen.io.github.onecx.announcement.rs.internal.model.AnnouncementTypeDTO; import lombok.*; @Getter @@ -22,18 +20,52 @@ @SuppressWarnings("java:S2160") public class Announcement extends TraceableEntity { + @TenantId + @Column(name = "TENANT_ID") + private String tenantId; + + @Column(name = "title") private String title; + + @Column(name = "content") private String content; + + @Column(name = "type") @Enumerated(EnumType.STRING) - private AnnouncementTypeDTO type; + private Type type; + + @Column(name = "priority") @Enumerated(EnumType.STRING) - private AnnouncementPriorityTypeDTO priority; + private Priority priority; + + @Column(name = "status") @Enumerated(EnumType.STRING) - private AnnouncementStatusDTO status; + private Status status; + @Column(name = "startDate") private LocalDateTime startDate; + @Column(name = "endDate") private LocalDateTime endDate; + @Column(name = "appId") private String appId; + + public enum Type { + EVENT, + INFO, + SYSTEM_MAINTENANCE; + } + + public enum Priority { + IMPORTANT, + NORMAL, + LOW; + } + + public enum Status { + ACTIVE, + INACTIVE; + } + } diff --git a/src/main/java/io/github/onecx/announcement/rs/internal/controller/AnnouncementControllerInternal.java b/src/main/java/io/github/onecx/announcement/rs/internal/controller/AnnouncementControllerInternal.java new file mode 100644 index 0000000..dfb2fcc --- /dev/null +++ b/src/main/java/io/github/onecx/announcement/rs/internal/controller/AnnouncementControllerInternal.java @@ -0,0 +1,92 @@ +package io.github.onecx.announcement.rs.internal.controller; + +import static jakarta.ws.rs.core.Response.Status.NOT_FOUND; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.validation.ConstraintViolationException; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.UriInfo; + +import org.jboss.resteasy.reactive.RestResponse; +import org.jboss.resteasy.reactive.server.ServerExceptionMapper; +import org.tkit.quarkus.log.cdi.LogService; + +import gen.io.github.onecx.announcement.rs.internal.AnnouncementInternalApi; +import gen.io.github.onecx.announcement.rs.internal.model.*; +import io.github.onecx.announcement.domain.daos.AnnouncementDAO; +import io.github.onecx.announcement.rs.internal.mapper.AnnouncementMapper; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@LogService +@ApplicationScoped +public class AnnouncementControllerInternal implements AnnouncementInternalApi { + @Inject + AnnouncementMapper mapper; + @Inject + AnnouncementDAO dao; + + @Context + UriInfo uriInfo; + + @Override + public Response createAnnouncement(CreateAnnouncementRequestDTO createAnnouncementRequestDTO) { + var item = mapper.create(createAnnouncementRequestDTO); + item = dao.create(item); + return Response + .created(uriInfo.getAbsolutePathBuilder().path(item.getId()).build()) + .entity(mapper.map(item)) + .build(); + } + + @Override + public Response deleteAnnouncementById(String id) { + dao.deleteQueryById(id); + return Response.noContent().build(); + } + + @Override + + public Response getAllAppsWithAnnouncements() { + var items = dao.findApplicationsWithAnnouncements(); + var results = mapper.map(items); + return Response.ok(results).build(); + } + + @Override + public Response getAnnouncementById(String id) { + var item = dao.findById(id); + if (item == null) { + return Response.status(NOT_FOUND).build(); + } + return Response.ok(mapper.map(item)).build(); + } + + @Override + public Response getAnnouncements(AnnouncementSearchCriteriaDTO announcementSearchCriteriaDTO) { + var criteria = mapper.map(announcementSearchCriteriaDTO); + var page = dao.loadAnnouncementByCriteria(criteria); + var results = mapper.mapToPageResult(page); + return Response.ok().entity(results).build(); + } + + @Override + public Response updateAnnouncementById(String id, UpdateAnnouncementRequestDTO updateAnnouncementRequestDTO) { + var item = dao.findById(id); + if (item == null) { + return Response.status(NOT_FOUND).build(); + } + + mapper.update(item, updateAnnouncementRequestDTO); + item = dao.update(item); + return Response.ok(item).build(); + } + + @ServerExceptionMapper + public RestResponse constraint(ConstraintViolationException ex) { + return mapper.constraint(ex); + } + +} diff --git a/src/main/java/io/github/onecx/announcement/rs/internal/log/InternalLogParam.java b/src/main/java/io/github/onecx/announcement/rs/internal/log/InternalLogParam.java new file mode 100644 index 0000000..a4b73a2 --- /dev/null +++ b/src/main/java/io/github/onecx/announcement/rs/internal/log/InternalLogParam.java @@ -0,0 +1,34 @@ +package io.github.onecx.announcement.rs.internal.log; + +import java.util.List; + +import jakarta.enterprise.context.ApplicationScoped; + +import org.tkit.quarkus.log.cdi.LogParam; + +import gen.io.github.onecx.announcement.rs.internal.model.AnnouncementSearchCriteriaDTO; +import gen.io.github.onecx.announcement.rs.internal.model.CreateAnnouncementRequestDTO; +import gen.io.github.onecx.announcement.rs.internal.model.UpdateAnnouncementRequestDTO; + +@ApplicationScoped +public class InternalLogParam implements LogParam { + + @Override + public List getClasses() { + return List.of( + item(10, CreateAnnouncementRequestDTO.class, x -> { + CreateAnnouncementRequestDTO d = (CreateAnnouncementRequestDTO) x; + return CreateAnnouncementRequestDTO.class.getSimpleName() + "[ appId:" + d.getAppId() + "]"; + }), + item(10, UpdateAnnouncementRequestDTO.class, x -> { + UpdateAnnouncementRequestDTO d = (UpdateAnnouncementRequestDTO) x; + return UpdateAnnouncementRequestDTO.class.getSimpleName() + "[ appId:" + d.getAppId() + "]"; + }), + item(10, AnnouncementSearchCriteriaDTO.class, x -> { + AnnouncementSearchCriteriaDTO d = (AnnouncementSearchCriteriaDTO) x; + return AnnouncementSearchCriteriaDTO.class.getSimpleName() + "[" + d.getPageNumber() + "," + + d.getPageSize() + + "]"; + })); + } +} diff --git a/src/main/java/org/onecx/announcement/rs/internal/mapper/AnnouncementMapper.java b/src/main/java/io/github/onecx/announcement/rs/internal/mapper/AnnouncementMapper.java similarity index 52% rename from src/main/java/org/onecx/announcement/rs/internal/mapper/AnnouncementMapper.java rename to src/main/java/io/github/onecx/announcement/rs/internal/mapper/AnnouncementMapper.java index c56ed02..4d04a84 100644 --- a/src/main/java/org/onecx/announcement/rs/internal/mapper/AnnouncementMapper.java +++ b/src/main/java/io/github/onecx/announcement/rs/internal/mapper/AnnouncementMapper.java @@ -1,4 +1,4 @@ -package org.onecx.announcement.rs.internal.mapper; +package io.github.onecx.announcement.rs.internal.mapper; import java.util.List; import java.util.Map; @@ -13,17 +13,27 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; -import org.onecx.announcement.domain.models.Announcement; import org.tkit.quarkus.jpa.daos.PageResult; -import org.tkit.quarkus.jpa.exceptions.ConstraintException; import org.tkit.quarkus.rs.mappers.OffsetDateTimeMapper; import gen.io.github.onecx.announcement.rs.internal.model.*; -import gen.io.github.onecx.announcement.v1.model.AnnouncementDTOV1; -import gen.io.github.onecx.announcement.v1.model.SearchAnnouncementRequestDTOV1; +import io.github.onecx.announcement.domain.criteria.AnnouncementSearchCriteria; +import io.github.onecx.announcement.domain.models.Announcement; @Mapper(uses = OffsetDateTimeMapper.class) -public abstract class AnnouncementMapper { +public interface AnnouncementMapper { + + default AnnouncementAppsDTO map(List appIds) { + if (appIds == null) { + return null; + } + + AnnouncementAppsDTO dto = new AnnouncementAppsDTO(); + dto.setAppIds(appIds); + return dto; + } + + AnnouncementSearchCriteria map(AnnouncementSearchCriteriaDTO dto); @Mapping(target = "id", ignore = true) @Mapping(target = "controlTraceabilityManual", ignore = true) @@ -33,22 +43,10 @@ public abstract class AnnouncementMapper { @Mapping(target = "modificationDate", ignore = true) @Mapping(target = "creationUser", ignore = true) @Mapping(target = "modificationUser", ignore = true) - public abstract Announcement create(CreateAnnouncementRequestDTO dto); + @Mapping(target = "tenantId", ignore = true) + Announcement create(CreateAnnouncementRequestDTO dto); - public abstract SearchAnnouncementRequestDTOV1 mapCriteria(SearchAnnouncementRequestDTO searchAnnouncementRequestDTO); - - @Mapping(target = "version", ignore = true) - public abstract AnnouncementDTO map(Announcement announcement); - - @Mapping(target = "id", ignore = true) - @Mapping(target = "creationDate", ignore = true) - @Mapping(target = "modificationDate", ignore = true) - @Mapping(target = "creationUser", ignore = true) - @Mapping(target = "modificationUser", ignore = true) - @Mapping(target = "controlTraceabilityManual", ignore = true) - @Mapping(target = "modificationCount", ignore = true) - @Mapping(target = "persisted", ignore = true) - public abstract Announcement update(@MappingTarget Announcement announcement, UpdateAnnouncementRequestDTO dto); + AnnouncementDTO map(Announcement announcement); @Mapping(target = "id", ignore = true) @Mapping(target = "creationDate", ignore = true) @@ -58,31 +56,25 @@ public abstract class AnnouncementMapper { @Mapping(target = "controlTraceabilityManual", ignore = true) @Mapping(target = "modificationCount", ignore = true) @Mapping(target = "persisted", ignore = true) - public abstract Announcement map(AnnouncementDTOV1 dto); + @Mapping(target = "tenantId", ignore = true) + void update(@MappingTarget Announcement announcement, UpdateAnnouncementRequestDTO dto); @Mapping(target = "removeStreamItem", ignore = true) - // @Mapping(target = "stream.version", ignore = true) - public abstract AnnouncementPageResultDTO mapToPageResult(PageResult announcementItemsPageResults); + AnnouncementPageResultDTO mapToPageResult(PageResult announcementItemsPageResults); @Mapping(target = "params", ignore = true) @Mapping(target = "removeParamsItem", ignore = true) @Mapping(target = "invalidParams", ignore = true) @Mapping(target = "removeInvalidParamsItem", ignore = true) - public abstract ProblemDetailResponseDTO exception(String errorCode, String detail); + ProblemDetailResponseDTO exception(String errorCode, String detail); - public RestResponse constraint(ConstraintViolationException ex) { - var dto = exception("CONSTRAINT_VIOLATIONS", ex.getMessage()); + default RestResponse constraint(ConstraintViolationException ex) { + var dto = exception(ErrorKeys.CONSTRAINT_VIOLATIONS.name(), ex.getMessage()); dto.setInvalidParams(createErrorValidationResponse(ex.getConstraintViolations())); return RestResponse.status(Response.Status.BAD_REQUEST, dto); } - public RestResponse exception(ConstraintException ex) { - var dto = exception(ex.getMessageKey().name(), ex.getConstraints()); - dto.setParams(map(ex.namedParameters)); - return RestResponse.status(Response.Status.BAD_REQUEST, dto); - } - - public List map(Map params) { + default List map(Map params) { if (params == null) { return List.of(); } @@ -96,14 +88,18 @@ public List map(Map params) { }).toList(); } - public abstract List createErrorValidationResponse( + List createErrorValidationResponse( Set> constraintViolation); @Mapping(target = "name", source = "propertyPath") @Mapping(target = "message", source = "message") - public abstract ProblemDetailInvalidParamDTO createError(ConstraintViolation constraintViolation); + ProblemDetailInvalidParamDTO createError(ConstraintViolation constraintViolation); - public String mapPath(Path path) { + default String mapPath(Path path) { return path.toString(); } + + enum ErrorKeys { + CONSTRAINT_VIOLATIONS + } } diff --git a/src/main/java/io/github/onecx/announcement/rs/v1/controller/AnnouncementControllerV1.java b/src/main/java/io/github/onecx/announcement/rs/v1/controller/AnnouncementControllerV1.java new file mode 100644 index 0000000..a3e830d --- /dev/null +++ b/src/main/java/io/github/onecx/announcement/rs/v1/controller/AnnouncementControllerV1.java @@ -0,0 +1,40 @@ +package io.github.onecx.announcement.rs.v1.controller; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.validation.ConstraintViolationException; +import jakarta.ws.rs.core.Response; + +import org.jboss.resteasy.reactive.RestResponse; +import org.jboss.resteasy.reactive.server.ServerExceptionMapper; +import org.tkit.quarkus.log.cdi.LogService; + +import gen.io.github.onecx.announcement.v1.AnnouncementV1Api; +import gen.io.github.onecx.announcement.v1.model.AnnouncementSearchCriteriaDTOV1; +import gen.io.github.onecx.announcement.v1.model.ProblemDetailResponseDTOV1; +import io.github.onecx.announcement.domain.daos.AnnouncementDAO; +import io.github.onecx.announcement.rs.v1.mapper.AnnouncementMapperV1; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@LogService +@ApplicationScoped +public class AnnouncementControllerV1 implements AnnouncementV1Api { + + @Inject + AnnouncementMapperV1 mapper; + @Inject + AnnouncementDAO dao; + + @Override + public Response getAnnouncementsByCriteria(AnnouncementSearchCriteriaDTOV1 announcementSearchCriteriaDTOV1) { + var criteria = mapper.map(announcementSearchCriteriaDTOV1); + var results = dao.loadAnnouncementByCriteria(criteria); + return Response.ok().entity(mapper.mapToPageResult(results)).build(); + } + + @ServerExceptionMapper + public RestResponse constraint(ConstraintViolationException ex) { + return mapper.constraint(ex); + } +} diff --git a/src/main/java/io/github/onecx/announcement/rs/v1/log/ExternalLogParamV1.java b/src/main/java/io/github/onecx/announcement/rs/v1/log/ExternalLogParamV1.java new file mode 100644 index 0000000..5a7fc9c --- /dev/null +++ b/src/main/java/io/github/onecx/announcement/rs/v1/log/ExternalLogParamV1.java @@ -0,0 +1,24 @@ +package io.github.onecx.announcement.rs.v1.log; + +import java.util.List; + +import jakarta.enterprise.context.ApplicationScoped; + +import org.tkit.quarkus.log.cdi.LogParam; + +import gen.io.github.onecx.announcement.v1.model.AnnouncementSearchCriteriaDTOV1; + +@ApplicationScoped +public class ExternalLogParamV1 implements LogParam { + + @Override + public List getClasses() { + return List.of( + item(10, AnnouncementSearchCriteriaDTOV1.class, x -> { + AnnouncementSearchCriteriaDTOV1 d = (AnnouncementSearchCriteriaDTOV1) x; + return AnnouncementSearchCriteriaDTOV1.class.getSimpleName() + "[" + d.getPageNumber() + "," + + d.getPageSize() + + "]"; + })); + } +} diff --git a/src/main/java/io/github/onecx/announcement/rs/v1/mapper/AnnouncementMapperV1.java b/src/main/java/io/github/onecx/announcement/rs/v1/mapper/AnnouncementMapperV1.java new file mode 100644 index 0000000..90aef56 --- /dev/null +++ b/src/main/java/io/github/onecx/announcement/rs/v1/mapper/AnnouncementMapperV1.java @@ -0,0 +1,53 @@ +package io.github.onecx.announcement.rs.v1.mapper; + +import java.util.List; +import java.util.Set; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; +import jakarta.validation.Path; +import jakarta.ws.rs.core.Response; + +import org.jboss.resteasy.reactive.RestResponse; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.tkit.quarkus.jpa.daos.PageResult; +import org.tkit.quarkus.rs.mappers.OffsetDateTimeMapper; + +import gen.io.github.onecx.announcement.v1.model.*; +import io.github.onecx.announcement.domain.criteria.AnnouncementSearchCriteria; +import io.github.onecx.announcement.domain.models.Announcement; + +@Mapper(uses = OffsetDateTimeMapper.class) +public interface AnnouncementMapperV1 { + + AnnouncementSearchCriteria map(AnnouncementSearchCriteriaDTOV1 dto); + + AnnouncementDTOV1 map(Announcement data); + + @Mapping(target = "removeStreamItem", ignore = true) + AnnouncementPageResultDTOV1 mapToPageResult(PageResult announcementItemsPageResults); + + default RestResponse constraint(ConstraintViolationException ex) { + var dto = exception("CONSTRAINT_VIOLATIONS", ex.getMessage()); + dto.setInvalidParams(createErrorValidationResponse(ex.getConstraintViolations())); + return RestResponse.status(Response.Status.BAD_REQUEST, dto); + } + + List createErrorValidationResponse( + Set> constraintViolation); + + @Mapping(target = "name", source = "propertyPath") + @Mapping(target = "message", source = "message") + public abstract ProblemDetailInvalidParamDTOV1 createError(ConstraintViolation constraintViolation); + + @Mapping(target = "invalidParams", ignore = true) + @Mapping(target = "removeInvalidParamsItem", ignore = true) + @Mapping(target = "removeParamsItem", ignore = true) + @Mapping(target = "params", ignore = true) + ProblemDetailResponseDTOV1 exception(String errorCode, String detail); + + default String mapPath(Path path) { + return path.toString(); + } +} diff --git a/src/main/java/org/onecx/announcement/domain/dao/AnnouncementDAO.java b/src/main/java/org/onecx/announcement/domain/dao/AnnouncementDAO.java deleted file mode 100644 index a922065..0000000 --- a/src/main/java/org/onecx/announcement/domain/dao/AnnouncementDAO.java +++ /dev/null @@ -1,119 +0,0 @@ -package org.onecx.announcement.domain.dao; - -import java.util.ArrayList; -import java.util.List; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.persistence.Tuple; -import jakarta.persistence.criteria.*; - -import org.onecx.announcement.domain.models.Announcement; -import org.onecx.announcement.domain.models.Announcement_; -import org.tkit.quarkus.jpa.daos.AbstractDAO; -import org.tkit.quarkus.jpa.daos.Page; -import org.tkit.quarkus.jpa.daos.PageResult; -import org.tkit.quarkus.jpa.exceptions.DAOException; -import org.tkit.quarkus.jpa.models.AbstractTraceableEntity_; - -import gen.io.github.onecx.announcement.v1.model.SearchAnnouncementRequestDTOV1; -import lombok.extern.slf4j.Slf4j; - -@ApplicationScoped -@Slf4j -public class AnnouncementDAO extends AbstractDAO { - - public PageResult loadAnnouncementByCriteria(SearchAnnouncementRequestDTOV1 criteria) { - try { - CriteriaBuilder cb = getEntityManager().getCriteriaBuilder(); - CriteriaQuery cq = cb.createQuery(Announcement.class); - Root root = cq.from(Announcement.class); - cq.select(root).distinct(true); - - List predicates = new ArrayList<>(); - if (criteria != null) { - if (criteria.getStatus() != null) { - predicates.add(root.get(Announcement_.STATUS).in(criteria.getStatus())); - } - if (criteria.getAppId() != null) { - Predicate predicateEqualAppId = cb.equal(root.get(Announcement_.APP_ID), criteria.getAppId()); - Predicate predicateIsNull = cb.isNull(root.get(Announcement_.APP_ID)); - predicates.add(cb.or(predicateEqualAppId, predicateIsNull)); - } - if (criteria.getStartDateFrom() != null) { - log.info("criteria.getStartDateFrom() : " + criteria.getStartDateFrom().toLocalDateTime()); - predicates.add(cb.greaterThanOrEqualTo(root.get(Announcement_.START_DATE), - criteria.getStartDateFrom().toLocalDateTime())); - } - if (criteria.getStartDateTo() != null) { - log.info("criteria.getStartDateTo() : " + criteria.getStartDateTo().toLocalDateTime()); - predicates.add(cb.lessThanOrEqualTo(root.get(Announcement_.START_DATE), - criteria.getStartDateTo().toLocalDateTime())); - } - if (criteria.getEndDateFrom() != null) { - predicates.add(cb.greaterThanOrEqualTo(root.get(Announcement_.END_DATE), - criteria.getEndDateFrom().toLocalDateTime())); - } - if (criteria.getEndDateTo() != null) { - predicates.add( - cb.lessThanOrEqualTo(root.get(Announcement_.END_DATE), criteria.getEndDateTo().toLocalDateTime())); - } - if (criteria.getPriority() != null) { - predicates.add(root.get(Announcement_.PRIORITY).in(criteria.getPriority())); - - } - if (criteria.getType() != null) { - predicates.add(root.get(Announcement_.TYPE).in(criteria.getType())); - - } - if (criteria.getId() != null) { - predicates.add(root.get(Announcement_.ID).in(criteria.getId())); - } - } - if (!predicates.isEmpty()) { - cq.where(cb.and(predicates.toArray(new Predicate[0]))); - } - - //do query and sort resultList by Priority and creation-date - cq.orderBy(cb.desc(root.get(AbstractTraceableEntity_.CREATION_DATE))); - return createPageQuery(cq, Page.of(criteria.getPageNumber(), criteria.getPageSize())).getPageResult(); - } catch (Exception ex) { - throw new DAOException(ErrorKeys.ERROR_LOAD_ANNOUNCEMENT_BY_CRITERIA, ex); - } - - } - - public List findApplicationsWithAnnouncements() { - try { - CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery cq = cb.createTupleQuery(); - Root root = cq.from(Announcement.class); - cq.multiselect(root.get(Announcement_.APP_ID)); - cq.distinct(true); - List tupleResult = em.createQuery(cq).getResultList(); - return tupleResult.stream().map(t -> (String) t.get(0)).toList(); - } catch (Exception ex) { - throw new DAOException(ErrorKeys.ERROR_FIND_APPLICATIONS_WITH_ANNOUNCEMENTS, ex); - } - } - - public void deleteByAppId(String appId) { - try { - CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); - CriteriaDelete criteriaDelete = criteriaBuilder.createCriteriaDelete(Announcement.class); - Root root = criteriaDelete.from(Announcement.class); - criteriaDelete.where(criteriaBuilder.equal(root.get(Announcement_.APP_ID), appId)); - int rowsDeleted = em.createQuery(criteriaDelete).executeUpdate(); - log.info("Number of Announcements deleted: " + rowsDeleted); - } catch (Exception ex) { - throw new DAOException(ErrorKeys.ERROR_DELETE_BY_CRITERIA, ex); - } - } - - public enum ErrorKeys { - - ERROR_LOAD_ANNOUNCEMENT_BY_CRITERIA, - ERROR_FIND_APPLICATIONS_WITH_ANNOUNCEMENTS, - ERROR_DELETE_BY_CRITERIA - } - -} diff --git a/src/main/java/org/onecx/announcement/rs/internal/controller/ApplicationControllerInternal.java b/src/main/java/org/onecx/announcement/rs/internal/controller/ApplicationControllerInternal.java deleted file mode 100644 index 2b1970b..0000000 --- a/src/main/java/org/onecx/announcement/rs/internal/controller/ApplicationControllerInternal.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.onecx.announcement.rs.internal.controller; - -import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; -import static jakarta.ws.rs.core.Response.Status.NOT_FOUND; - -import java.util.List; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.validation.ConstraintViolationException; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.core.UriInfo; - -import org.jboss.resteasy.reactive.RestResponse; -import org.jboss.resteasy.reactive.server.ServerExceptionMapper; -import org.onecx.announcement.domain.dao.AnnouncementDAO; -import org.onecx.announcement.domain.models.Announcement; -import org.onecx.announcement.rs.internal.mapper.AnnouncementMapper; -import org.onecx.announcement.rs.v1.controller.ErrorKeys; -import org.tkit.quarkus.jpa.exceptions.ConstraintException; -import org.tkit.quarkus.jpa.exceptions.DAOException; - -import gen.io.github.onecx.announcement.rs.internal.AnnouncementInternalApi; -import gen.io.github.onecx.announcement.rs.internal.model.*; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -@ApplicationScoped -@Path("/internal/announcements") -public class ApplicationControllerInternal implements AnnouncementInternalApi { - @Inject - AnnouncementMapper announcementMapper; - @Inject - AnnouncementDAO announcementDAO; - - @Context - UriInfo uriInfo; - - @Override - public Response addAnnouncement(CreateAnnouncementRequestDTO createAnnouncementRequestDTO) { - Announcement announcementItem = announcementMapper.create(createAnnouncementRequestDTO); - Announcement responseAnnouncementItem = announcementDAO.create(announcementItem); - return Response - .created(uriInfo.getAbsolutePathBuilder().path(responseAnnouncementItem.getId()).build()) - .entity(announcementMapper.map(responseAnnouncementItem)) - .build(); - } - - @Override - public Response deleteAnnouncementById(String id) { - try { - Announcement announcement = announcementDAO.findById(id); - if (announcement != null) { - announcementDAO.deleteQueryById(id); - return Response.noContent().build(); - } - } catch (DAOException e) { - e.printStackTrace(); - return Response.status(BAD_REQUEST) - .entity(announcementMapper.exception(ErrorKeys.ERROR_DELETE_ANNOUNCEMENT_BY_CRITERIA.name(), - "Failed to delete announcements. Error: " + e.getMessage())) - .build(); - } - return Response.status(NOT_FOUND).build(); - } - - @Override - - public Response getAllAppsWithAnnouncements() { - List resultList = announcementDAO.findApplicationsWithAnnouncements(); - return Response.ok(resultList).build(); - } - - @Override - public Response getAnnouncementById(String id) { - Announcement fetchedAnnouncement = announcementDAO.findById(id); - if (fetchedAnnouncement == null) { - return Response.status(NOT_FOUND).build(); - } - return Response.ok(announcementMapper.map(fetchedAnnouncement)).build(); - } - - @Override - public Response getAnnouncements(SearchAnnouncementRequestDTO searchAnnouncementRequestDTO) { - log.info("INSIDE SEARCH SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"); - var results = announcementDAO.loadAnnouncementByCriteria(announcementMapper.mapCriteria(searchAnnouncementRequestDTO)); - if (results == null) { - return Response.status(NOT_FOUND).build(); - } - AnnouncementPageResultDTO announcementPageResultDTO = announcementMapper.mapToPageResult(results); - return Response.ok().entity(announcementPageResultDTO).build(); - } - - @Override - public Response updateAnnouncementById(String id, UpdateAnnouncementRequestDTO updateAnnouncementRequestDTO) { - Announcement acItem = announcementDAO.findById(id); - if (acItem != null) { - announcementDAO.update(announcementMapper.update(acItem, updateAnnouncementRequestDTO)); - Announcement updatedAnnouncement = announcementDAO.findById(id); - return Response.ok(updatedAnnouncement).build(); - } - return Response.status(NOT_FOUND).build(); - - } - - @ServerExceptionMapper - public RestResponse exception(ConstraintException ex) { - return announcementMapper.exception(ex); - } - - @ServerExceptionMapper - public RestResponse constraint(ConstraintViolationException ex) { - return announcementMapper.constraint(ex); - } -} diff --git a/src/main/java/org/onecx/announcement/rs/v1/controller/AnnouncementControllerV1.java b/src/main/java/org/onecx/announcement/rs/v1/controller/AnnouncementControllerV1.java deleted file mode 100644 index 51c37d7..0000000 --- a/src/main/java/org/onecx/announcement/rs/v1/controller/AnnouncementControllerV1.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.onecx.announcement.rs.v1.controller; - -import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; -import static jakarta.ws.rs.core.Response.Status.NOT_FOUND; - -import jakarta.inject.Inject; -import jakarta.transaction.Transactional; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - -import org.eclipse.microprofile.openapi.annotations.tags.Tag; -import org.onecx.announcement.domain.dao.AnnouncementDAO; -import org.onecx.announcement.domain.models.Announcement; -import org.onecx.announcement.rs.v1.mapper.AnnouncementMapperV1; -import org.tkit.quarkus.jpa.exceptions.DAOException; - -import gen.io.github.onecx.announcement.v1.AnnouncementV1Api; -import gen.io.github.onecx.announcement.v1.model.AnnouncementDTOV1; -import gen.io.github.onecx.announcement.v1.model.AnnouncementPageResultDTOV1; -import gen.io.github.onecx.announcement.v1.model.DeleteAnnouncementRequestDTOV1; -import gen.io.github.onecx.announcement.v1.model.SearchAnnouncementRequestDTOV1; -import lombok.extern.slf4j.Slf4j; - -@Path("/v1/applications") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -@Slf4j -@Tag(name = "AnnouncementV1") -public class AnnouncementControllerV1 implements AnnouncementV1Api { - - @Inject - AnnouncementMapperV1 announcementMapper; - @Inject - AnnouncementDAO announcementDAO; - - @Override - public Response getAnnouncementByIdV1(String id) { - Announcement announcement = announcementDAO.findById(id); - if (announcement == null) { - return Response.status(NOT_FOUND).build(); - } - AnnouncementDTOV1 announcementDto = announcementMapper.map(announcement); - return Response.ok().entity(announcementDto).build(); - } - - @Override - public Response getAnnouncementsByCriteriaV1(SearchAnnouncementRequestDTOV1 searchAnnouncementRequestDTOV1) { - var results = announcementDAO.loadAnnouncementByCriteria(searchAnnouncementRequestDTOV1); - if (results == null) { - return Response.status(NOT_FOUND).build(); - } - AnnouncementPageResultDTOV1 announcementPageResultDTOV1 = announcementMapper.mapToPageResult(results); - return Response.ok().entity(announcementPageResultDTOV1).build(); - } - - @Override - @Transactional - public Response deleteAnnouncementByCriteriaV1(DeleteAnnouncementRequestDTOV1 deleteAnnouncementRequestDTOV1) { - try { - for (String appId : deleteAnnouncementRequestDTOV1.getAppIds()) { - announcementDAO.deleteByAppId(appId); - } - return Response.noContent().build(); - } catch (DAOException e) { - e.printStackTrace(); - return Response.status(BAD_REQUEST) - .entity(announcementMapper.exception(ErrorKeys.ERROR_DELETE_ANNOUNCEMENT_BY_CRITERIA.name(), - "Failed to delete announcements. Error: " + e.getMessage())) - .build(); - } - } -} diff --git a/src/main/java/org/onecx/announcement/rs/v1/controller/ErrorKeys.java b/src/main/java/org/onecx/announcement/rs/v1/controller/ErrorKeys.java deleted file mode 100644 index f4932f1..0000000 --- a/src/main/java/org/onecx/announcement/rs/v1/controller/ErrorKeys.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.onecx.announcement.rs.v1.controller; - -public enum ErrorKeys { - ERROR_DELETE_ANNOUNCEMENT_BY_CRITERIA -} diff --git a/src/main/java/org/onecx/announcement/rs/v1/mapper/AnnouncementMapperV1.java b/src/main/java/org/onecx/announcement/rs/v1/mapper/AnnouncementMapperV1.java deleted file mode 100644 index d4d18bd..0000000 --- a/src/main/java/org/onecx/announcement/rs/v1/mapper/AnnouncementMapperV1.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.onecx.announcement.rs.v1.mapper; - -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.onecx.announcement.domain.models.Announcement; -import org.tkit.quarkus.jpa.daos.PageResult; -import org.tkit.quarkus.rs.mappers.OffsetDateTimeMapper; - -import gen.io.github.onecx.announcement.v1.model.AnnouncementDTOV1; -import gen.io.github.onecx.announcement.v1.model.AnnouncementPageResultDTOV1; -import gen.io.github.onecx.announcement.v1.model.ProblemDetailResponseDTOV1; - -@Mapper(uses = OffsetDateTimeMapper.class) -public interface AnnouncementMapperV1 { - - @Mapping(target = "id", ignore = true) - @Mapping(target = "creationDate", ignore = true) - @Mapping(target = "modificationDate", ignore = true) - @Mapping(target = "creationUser", ignore = true) - @Mapping(target = "modificationUser", ignore = true) - @Mapping(target = "controlTraceabilityManual", ignore = true) - @Mapping(target = "modificationCount", ignore = true) - @Mapping(target = "persisted", ignore = true) - Announcement map(AnnouncementDTOV1 dto); - - @Mapping(target = "version", ignore = true) - AnnouncementDTOV1 map(Announcement data); - - @Mapping(target = "removeStreamItem", ignore = true) - AnnouncementPageResultDTOV1 mapToPageResult(PageResult announcementItemsPageResults); - - @Mapping(target = "params", ignore = true) - @Mapping(target = "removeParamsItem", ignore = true) - @Mapping(target = "invalidParams", ignore = true) - @Mapping(target = "removeInvalidParamsItem", ignore = true) - ProblemDetailResponseDTOV1 exception(String errorCode, String detail); - -} diff --git a/src/main/openapi/announcement-openapi-internal.yaml b/src/main/openapi/announcement-openapi-internal.yaml index bb20a97..f2f57f3 100644 --- a/src/main/openapi/announcement-openapi-internal.yaml +++ b/src/main/openapi/announcement-openapi-internal.yaml @@ -3,7 +3,7 @@ info: title: onecx-announcement-svc version: "1.0" servers: - - url: https://localhost:8080 + - url: https://onecx-announcement-svc:8080 tags: - name: AnnouncementInternal description: Execute Announcement CRUD operations @@ -19,7 +19,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/SearchAnnouncementRequest' + $ref: '#/components/schemas/AnnouncementSearchCriteria' responses: "200": description: OK @@ -39,8 +39,8 @@ paths: post: tags: - AnnouncementInternal - summary: Add announcement - operationId: addAnnouncement + summary: Create announcement + operationId: createAnnouncement requestBody: required: true content: @@ -78,8 +78,7 @@ paths: content: application/json: schema: - type: array - items: {} + $ref: '#/components/schemas/AnnouncementApps' /internal/announcements/{id}: get: tags: @@ -125,6 +124,7 @@ paths: schema: type: string requestBody: + required: true content: application/json: schema: @@ -144,8 +144,18 @@ paths: $ref: '#/components/schemas/ProblemDetailResponse' components: schemas: + AnnouncementApps: + type: object + properties: + appIds: + type: array + items: + type: string CreateAnnouncementRequest: type: object + required: + - title + - content properties: title: type: string @@ -163,23 +173,9 @@ components: $ref: '#/components/schemas/OffsetDateTime' appId: type: string - SearchAnnouncementRequest: + AnnouncementSearchCriteria: type: object properties: - creationDateFrom: - $ref: '#/components/schemas/OffsetDateTime' - creationDateTo: - $ref: '#/components/schemas/OffsetDateTime' - creationUser: - type: string - modificationDateFrom: - $ref: '#/components/schemas/OffsetDateTime' - modificationDateTo: - $ref: '#/components/schemas/OffsetDateTime' - modificationUser: - type: string - id: - type: string title: type: string content: @@ -212,6 +208,9 @@ components: type: integer UpdateAnnouncementRequest: type: object + required: + - title + - content properties: title: type: string @@ -232,7 +231,7 @@ components: Announcement: type: object properties: - version: + modificationCount: format: int32 type: integer creationDate: diff --git a/src/main/openapi/announcement-openapi-v1.yaml b/src/main/openapi/announcement-openapi-v1.yaml index daaa0f1..14aa91f 100644 --- a/src/main/openapi/announcement-openapi-v1.yaml +++ b/src/main/openapi/announcement-openapi-v1.yaml @@ -1,25 +1,25 @@ openapi: "3.0.3" info: - title: onecx-announcement-svc-v1 + title: onecx-announcement version: "1.0" servers: - - url: https://localhost:8080 + - url: https://onecx-announcement-svc:8080 tags: - - name: AnnouncementV1 + - name: Announcement description: Announcement Management v1 RS API paths: /v1/applications/announcements/search: post: tags: - - AnnouncementV1 + - Announcement summary: Get announcements - operationId: getAnnouncementsByCriteriaV1 + operationId: getAnnouncementsByCriteria requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/SearchAnnouncementRequest' + $ref: '#/components/schemas/AnnouncementSearchCriteria' responses: "200": description: OK @@ -27,46 +27,6 @@ paths: application/json: schema: $ref: '#/components/schemas/AnnouncementPageResult' - /v1/applications/announcements/{id}: - get: - tags: - - AnnouncementV1 - summary: Retrieve announcement by Id - operationId: getAnnouncementByIdV1 - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - "200": - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/Announcement' - "404": - description: Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/ProblemDetailResponse' - /v1/applications: - delete: - tags: - - AnnouncementV1 - summary: Delete announcement - operationId: deleteAnnouncementByCriteriaV1 - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DeleteAnnouncementRequest' - responses: - "204": - description: No content "400": description: Bad request content: @@ -78,43 +38,14 @@ components: Announcement: type: object properties: - version: - format: int32 - type: integer - creationDate: - format: date-time - type: string - example: 2022-03-10T12:15:50-04:00 - creationUser: - type: string - modificationDate: - format: date-time - type: string - example: 2022-03-10T12:15:50-04:00 - modificationUser: - type: string - id: - type: string title: type: string - appId: - type: string content: type: string type: - $ref: '#/components/schemas/AnnouncementType' + $ref: '#/components/schemas/Type' priority: - $ref: '#/components/schemas/AnnouncementPriorityType' - status: - $ref: '#/components/schemas/AnnouncementStatus' - startDate: - format: date-time - type: string - example: 2022-03-10T12:15:50-04:00 - endDate: - format: date-time - type: string - example: 2022-03-10T12:15:50-04:00 + $ref: '#/components/schemas/Priority' AnnouncementPageResult: description: PageResult for Announcements type: object @@ -135,33 +66,15 @@ components: type: array items: $ref: '#/components/schemas/Announcement' - SearchAnnouncementRequest: + AnnouncementSearchCriteria: type: object properties: - creationDateFrom: - $ref: '#/components/schemas/OffsetDateTime' - creationDateTo: - $ref: '#/components/schemas/OffsetDateTime' - creationUser: - type: string - modificationDateFrom: - $ref: '#/components/schemas/OffsetDateTime' - modificationDateTo: - $ref: '#/components/schemas/OffsetDateTime' - modificationUser: - type: string - id: - type: string - title: - type: string - content: - type: string type: - $ref: '#/components/schemas/AnnouncementType' + $ref: '#/components/schemas/Type' priority: - $ref: '#/components/schemas/AnnouncementPriorityType' + $ref: '#/components/schemas/Priority' status: - $ref: '#/components/schemas/AnnouncementStatus' + $ref: '#/components/schemas/Status' startDateFrom: $ref: '#/components/schemas/OffsetDateTime' startDateTo: @@ -182,25 +95,18 @@ components: description: The size of page default: 100 type: integer - DeleteAnnouncementRequest: - type: object - properties: - appIds: - type: array - items: - type: string - AnnouncementPriorityType: + Priority: enum: - IMPORTANT - NORMAL - LOW type: string - AnnouncementStatus: + Status: enum: - ACTIVE - INACTIVE type: string - AnnouncementType: + Type: enum: - EVENT - INFO diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 0d656ce..2a1bede 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,51 +1,47 @@ -# Configuration file +# DEFAULT quarkus.datasource.db-kind=postgresql -quarkus.datasource.jdbc.max-size=8 -quarkus.datasource.jdbc.min-size=2 +quarkus.datasource.jdbc.max-size=30 +quarkus.datasource.jdbc.min-size=10 -quarkus.flyway.migrate-at-start=true -quarkus.flyway.validate-on-migrate=true quarkus.hibernate-orm.database.generation=validate -quarkus.hibernate-orm.jdbc.timezone=UTC -smallrye.jwt.path.groups=realm_access/roles +quarkus.hibernate-orm.multitenant=DISCRIMINATOR +quarkus.liquibase.migrate-at-start=true +quarkus.liquibase.validate-on-migrate=true -mp.jwt.verify.issuer=${RHSSO_HOST:https://secure-keycloak2-test.apps.openshift1.1000kit.net/auth/}admin/realms/${OAUTH_REALM:GigabitHub} -mp.jwt.verify.publickey.location=${RHSSO_HOST:https://secure-keycloak2-test.apps.openshift1.1000kit.net/auth/}admin/realms/${OAUTH_REALM:GigabitHub}/protocol/openid-connect/certs -quarkus.swagger-ui.enable=true -quarkus.swagger-ui.always-include=true -quarkus.smallrye-openapi.auto-add-server=false -quarkus.jackson.write-dates-as-timestamps=true +# enable or disable multi-tenancy support +tkit.rs.context.tenant-id.enabled=true # PROD -%prod.quarkus.datasource.jdbc.url=${DB_URL:jdbc:postgresql://localhost:5432/ahm?sslmode=disable} -%prod.quarkus.datasource.username=${DB_USER:ahm} -%prod.quarkus.datasource.password=${DB_PWD:ahm} +%prod.quarkus.datasource.jdbc.url=${DB_URL:jdbc:postgresql://postgresdb:5432/onecx-announcement?sslmode=disable} +%prod.quarkus.datasource.username=${DB_USER:onecx-announcement} +%prod.quarkus.datasource.password=${DB_PWD:onecx-announcement} + # DEV -%dev.quarkus.http.port=9090 -%dev.mp.jwt.verify.issuer=http://keycloak-app/realms/OneCX -%dev.mp.jwt.verify.publickey.location=http://keycloak-app/realms/OneCX/protocol/openid-connect/certs -%dev.quarkus.tkit.log.console.json=false -%dev.tkit.log.mdc=false -%dev.tkit.log.rs.mdc=false -%dev.tkit.log.rs.client.mdc=false -%dev.quarkus.datasource.metrics.enabled=false -%dev.quarkus.hibernate-orm.metrics.enabled=false -%dev.quarkus.http.host=0.0.0.0 -%dev.quarkus.datasource.jdbc.url=${DB_URL:jdbc:postgresql://localhost:5432/ahm?sslmode=disable} -%dev.quarkus.datasource.username=${DB_USER:ahm} -%dev.quarkus.datasource.password=${DB_PWD:ahm} - - -%test.mp.jwt.verify.publickey.location=META-INF/resources/test_publicKey.pem -%test.mp.jwt.verify.issuer=https://quarkus.io/using-jwt-rbac -%test.quarkus.tkit.log.console.json=false -%test.tkit.log.json=true -%test.tkit.log.mdc=false -%test.tkit.log.rs.mdc=false -%test.tkit.log.rs.client.mdc=false -%test.quarkus.datasource.metrics.enabled=false -%test.quarkus.hibernate-orm.metrics.enabled=false -%test.quarkus.datasource.devservices.image-name=postgres:14.2 -quarkus.test.native-image-profile=test +%dev.tkit.rs.context.tenant-id.enabled=true +%dev.tkit.rs.context.tenant-id.mock.enabled=true +%dev.tkit.rs.context.tenant-id.mock.default-tenant=test +%dev.tkit.rs.context.tenant-id.mock.data.org1=tenant100 + +# TEST +%test.tkit.rs.context.tenant-id.enabled=true +%test.tkit.rs.context.tenant-id.mock.enabled=true +%test.tkit.rs.context.tenant-id.mock.default-tenant=default +%test.tkit.rs.context.tenant-id.mock.claim-org-id=orgId +%test.tkit.rs.context.tenant-id.mock.token-header-param=apm-principal-token +%test.tkit.rs.context.tenant-id.mock.data.org1=tenant-100 +%test.tkit.rs.context.tenant-id.mock.data.org2=tenant-200 + +# TEST-IT +quarkus.test.integration-test-profile=test-it +%test-it.tkit.log.json.enabled=false +%test-it.tkit.rs.context.tenant-id.mock.enabled=true +%test-it.tkit.rs.context.tenant-id.mock.default-tenant=default +%test-it.tkit.rs.context.tenant-id.mock.claim-org-id=orgId +%test-it.tkit.rs.context.tenant-id.mock.token-header-param=apm-principal-token +%test-it.tkit.rs.context.tenant-id.mock.data.org1=tenant-100 +%test-it.tkit.rs.context.tenant-id.mock.data.org2=tenant-200 + +# PIPE CONFIG + diff --git a/src/main/resources/db/changeLog.xml b/src/main/resources/db/changeLog.xml new file mode 100644 index 0000000..235cb9c --- /dev/null +++ b/src/main/resources/db/changeLog.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/db/migration/V1.0.1__CreateTables.sql b/src/main/resources/db/migration/V1.0.1__CreateTables.sql deleted file mode 100644 index 8679502..0000000 --- a/src/main/resources/db/migration/V1.0.1__CreateTables.sql +++ /dev/null @@ -1,19 +0,0 @@ - create table announcement ( - GUID varchar(255) not null, - OPTLOCK int4 not null, - creationDate timestamp, - creationUser varchar(255), - modificationDate timestamp, - modificationUser varchar(255), - appId varchar(255), - content varchar(255), - endDate timestamp, - name varchar(255), - priority varchar(255), - startDate timestamp, - status varchar(255), - title varchar(255), - type varchar(255), - primary key (GUID) - ); - diff --git a/src/main/resources/db/v1/2023-12-11-create-tables.xml b/src/main/resources/db/v1/2023-12-11-create-tables.xml new file mode 100644 index 0000000..e8be8a0 --- /dev/null +++ b/src/main/resources/db/v1/2023-12-11-create-tables.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/io/github/onecx/announcement/domain/daos/AnnouncementDAOTest.java b/src/test/java/io/github/onecx/announcement/domain/daos/AnnouncementDAOTest.java new file mode 100644 index 0000000..72a8f92 --- /dev/null +++ b/src/test/java/io/github/onecx/announcement/domain/daos/AnnouncementDAOTest.java @@ -0,0 +1,46 @@ +package io.github.onecx.announcement.domain.daos; + +import jakarta.inject.Inject; +import jakarta.persistence.EntityManager; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; +import org.mockito.Mockito; +import org.tkit.quarkus.jpa.exceptions.DAOException; + +import io.github.onecx.announcement.test.AbstractTest; +import io.quarkus.test.InjectMock; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +class AnnouncementDAOTest extends AbstractTest { + + @Inject + AnnouncementDAO dao; + + @InjectMock + EntityManager em; + + @BeforeEach + void beforeAll() { + Mockito.when(em.getCriteriaBuilder()).thenThrow(new RuntimeException("Test technical error exception")); + } + + @Test + void methodExceptionTests() { + methodExceptionTests(() -> dao.findById(null), + AnnouncementDAO.ErrorKeys.FIND_ENTITY_BY_ID_FAILED); + methodExceptionTests(() -> dao.findApplicationsWithAnnouncements(), + AnnouncementDAO.ErrorKeys.ERROR_FIND_APPLICATIONS_WITH_ANNOUNCEMENTS); + methodExceptionTests(() -> dao.loadAnnouncementByCriteria(null), + AnnouncementDAO.ErrorKeys.ERROR_LOAD_ANNOUNCEMENT_BY_CRITERIA); + } + + void methodExceptionTests(Executable fn, Enum key) { + var exc = Assertions.assertThrows(DAOException.class, fn); + Assertions.assertEquals(key, exc.key); + } + +} diff --git a/src/test/java/io/github/onecx/announcement/rs/external/v1/AnnouncementControllerV1Test.java b/src/test/java/io/github/onecx/announcement/rs/external/v1/AnnouncementControllerV1Test.java new file mode 100644 index 0000000..f6cb411 --- /dev/null +++ b/src/test/java/io/github/onecx/announcement/rs/external/v1/AnnouncementControllerV1Test.java @@ -0,0 +1,113 @@ +package io.github.onecx.announcement.rs.external.v1; + +import static io.restassured.RestAssured.given; +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; +import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; +import static jakarta.ws.rs.core.Response.Status.OK; +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.OffsetDateTime; + +import org.junit.jupiter.api.Test; +import org.tkit.quarkus.test.WithDBData; + +import gen.io.github.onecx.announcement.v1.model.*; +import io.github.onecx.announcement.rs.v1.controller.AnnouncementControllerV1; +import io.github.onecx.announcement.test.AbstractTest; +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +@TestHTTPEndpoint(AnnouncementControllerV1.class) +@WithDBData(value = "data/test-v1.xml", deleteBeforeInsert = true, deleteAfterTest = true, rinseAndRepeat = true) +class AnnouncementControllerV1Test extends AbstractTest { + + @Test + void getAnnouncementsByCriteriaAllTest() { + AnnouncementSearchCriteriaDTOV1 criteria = new AnnouncementSearchCriteriaDTOV1(); + + var data = given() + .contentType(APPLICATION_JSON) + .body(criteria) + .post() + .then() + .statusCode(OK.getStatusCode()) + .contentType(APPLICATION_JSON) + .extract() + .as(AnnouncementPageResultDTOV1.class); + + assertThat(data).isNotNull(); + assertThat(data.getTotalElements()).isEqualTo(5); + assertThat(data.getStream()).isNotNull().hasSize(5); + } + + @Test + void getAnnouncementsByCriteriaTest() { + AnnouncementSearchCriteriaDTOV1 criteria = new AnnouncementSearchCriteriaDTOV1(); + criteria.setAppId("app2"); + criteria.status(StatusDTOV1.ACTIVE); + criteria.setPriority(PriorityDTOV1.NORMAL); + criteria.setType(TypeDTOV1.EVENT); + criteria.setStartDateFrom(OffsetDateTime.parse("2000-03-10T12:15:50-04:00")); + criteria.setStartDateTo(OffsetDateTime.parse("2023-03-10T12:15:50-04:00")); + criteria.setEndDateFrom(OffsetDateTime.parse("2000-03-10T12:15:50-04:00")); + criteria.setEndDateTo(OffsetDateTime.parse("2023-03-10T12:15:50-04:00")); + + var data = given() + .contentType(APPLICATION_JSON) + .body(criteria) + .post() + .then() + .statusCode(OK.getStatusCode()) + .contentType(APPLICATION_JSON) + .extract() + .as(AnnouncementPageResultDTOV1.class); + + assertThat(data).isNotNull(); + assertThat(data.getTotalElements()).isEqualTo(2); + assertThat(data.getStream()).isNotNull().hasSize(2); + } + + @Test + void getAnnouncementsByCriteriaNoBodyTest() { + var data = given() + .contentType(APPLICATION_JSON) + .post() + .then() + .statusCode(BAD_REQUEST.getStatusCode()) + .contentType(APPLICATION_JSON) + .extract() + .as(ProblemDetailResponseDTOV1.class); + + assertThat(data).isNotNull(); + assertThat(data.getDetail()).isEqualTo("getAnnouncementsByCriteria.announcementSearchCriteriaDTOV1: must not be null"); + } + + @Test + void getAnnouncementsByCriteriaOrg1Test() { + AnnouncementSearchCriteriaDTOV1 criteria = new AnnouncementSearchCriteriaDTOV1(); + criteria.setAppId("app2"); + criteria.status(StatusDTOV1.ACTIVE); + criteria.setPriority(PriorityDTOV1.NORMAL); + criteria.setType(TypeDTOV1.EVENT); + criteria.setStartDateFrom(OffsetDateTime.parse("2000-03-10T12:15:50-04:00")); + criteria.setStartDateTo(OffsetDateTime.parse("2023-03-10T12:15:50-04:00")); + criteria.setEndDateFrom(OffsetDateTime.parse("2000-03-10T12:15:50-04:00")); + criteria.setEndDateTo(OffsetDateTime.parse("2023-03-10T12:15:50-04:00")); + + var data = given() + .header(APM_HEADER_PARAM, createToken("org1")) + .contentType(APPLICATION_JSON) + .body(criteria) + .post() + .then() + .statusCode(OK.getStatusCode()) + .contentType(APPLICATION_JSON) + .extract() + .as(AnnouncementPageResultDTOV1.class); + + assertThat(data).isNotNull(); + assertThat(data.getTotalElements()).isEqualTo(2); + assertThat(data.getStream()).isNotNull().hasSize(2); + } +} diff --git a/src/test/java/io/github/onecx/announcement/rs/external/v1/AnnouncementControllerV1TestIT.java b/src/test/java/io/github/onecx/announcement/rs/external/v1/AnnouncementControllerV1TestIT.java new file mode 100644 index 0000000..696439b --- /dev/null +++ b/src/test/java/io/github/onecx/announcement/rs/external/v1/AnnouncementControllerV1TestIT.java @@ -0,0 +1,7 @@ +package io.github.onecx.announcement.rs.external.v1; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +class AnnouncementControllerV1TestIT extends AnnouncementControllerV1Test { +} diff --git a/src/test/java/io/github/onecx/announcement/rs/internal/AnnouncementControllerInternalExceptionTest.java b/src/test/java/io/github/onecx/announcement/rs/internal/AnnouncementControllerInternalExceptionTest.java new file mode 100644 index 0000000..b1bcbd0 --- /dev/null +++ b/src/test/java/io/github/onecx/announcement/rs/internal/AnnouncementControllerInternalExceptionTest.java @@ -0,0 +1,49 @@ +package io.github.onecx.announcement.rs.internal; + +import static io.restassured.RestAssured.given; +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; +import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.tkit.quarkus.jpa.exceptions.DAOException; + +import io.github.onecx.announcement.domain.daos.AnnouncementDAO; +import io.github.onecx.announcement.rs.internal.controller.AnnouncementControllerInternal; +import io.github.onecx.announcement.test.AbstractTest; +import io.quarkus.test.InjectMock; +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +@TestHTTPEndpoint(AnnouncementControllerInternal.class) +class AnnouncementControllerInternalExceptionTest extends AbstractTest { + + @InjectMock + AnnouncementDAO dao; + + @BeforeEach + void beforeAll() { + Mockito.when(dao.findApplicationsWithAnnouncements()) + .thenThrow(new RuntimeException("Test technical error exception")) + .thenThrow(new DAOException(AnnouncementDAO.ErrorKeys.ERROR_FIND_APPLICATIONS_WITH_ANNOUNCEMENTS, + new RuntimeException("Test"))); + } + + @Test + void exceptionTest() { + given() + .contentType(APPLICATION_JSON) + .get("appIds") + .then() + .statusCode(INTERNAL_SERVER_ERROR.getStatusCode()); + + given() + .contentType(APPLICATION_JSON) + .get("appIds") + .then() + .statusCode(INTERNAL_SERVER_ERROR.getStatusCode()); + + } +} diff --git a/src/test/java/io/github/onecx/announcement/rs/internal/AnnouncementControllerInternalTest.java b/src/test/java/io/github/onecx/announcement/rs/internal/AnnouncementControllerInternalTest.java new file mode 100644 index 0000000..a5dafc3 --- /dev/null +++ b/src/test/java/io/github/onecx/announcement/rs/internal/AnnouncementControllerInternalTest.java @@ -0,0 +1,262 @@ +package io.github.onecx.announcement.rs.internal; + +import static io.restassured.RestAssured.given; +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; +import static jakarta.ws.rs.core.Response.Status.*; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.jboss.resteasy.reactive.RestResponse.Status.CREATED; + +import java.time.OffsetDateTime; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.tkit.quarkus.test.WithDBData; + +import gen.io.github.onecx.announcement.rs.internal.model.*; +import io.github.onecx.announcement.rs.internal.controller.AnnouncementControllerInternal; +import io.github.onecx.announcement.rs.internal.mapper.AnnouncementMapper; +import io.github.onecx.announcement.test.AbstractTest; +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +@TestHTTPEndpoint(AnnouncementControllerInternal.class) +@WithDBData(value = "data/test-internal.xml", deleteBeforeInsert = true, deleteAfterTest = true, rinseAndRepeat = true) +class AnnouncementControllerInternalTest extends AbstractTest { + + @Test + void getAnnouncementsByCriteriaAllTest() { + AnnouncementSearchCriteriaDTO criteria = new AnnouncementSearchCriteriaDTO(); + + var data = given() + .contentType(APPLICATION_JSON) + .body(criteria) + .post("search") + .then() + .statusCode(OK.getStatusCode()) + .contentType(APPLICATION_JSON) + .extract() + .as(AnnouncementPageResultDTO.class); + + Assertions.assertThat(data).isNotNull(); + Assertions.assertThat(data.getTotalElements()).isEqualTo(5); + Assertions.assertThat(data.getStream()).isNotNull().hasSize(5); + } + + @Test + void getAnnouncementsByCriteriaTest() { + AnnouncementSearchCriteriaDTO criteria = new AnnouncementSearchCriteriaDTO(); + criteria.setAppId("app2"); + criteria.status(AnnouncementStatusDTO.ACTIVE); + criteria.setPriority(AnnouncementPriorityTypeDTO.NORMAL); + criteria.setType(AnnouncementTypeDTO.EVENT); + criteria.setStartDateFrom(OffsetDateTime.parse("2000-03-10T12:15:50-04:00")); + criteria.setStartDateTo(OffsetDateTime.parse("2023-03-10T12:15:50-04:00")); + criteria.setEndDateFrom(OffsetDateTime.parse("2000-03-10T12:15:50-04:00")); + criteria.setEndDateTo(OffsetDateTime.parse("2023-03-10T12:15:50-04:00")); + + var data = given() + .contentType(APPLICATION_JSON) + .body(criteria) + .post("search") + .then() + .statusCode(OK.getStatusCode()) + .contentType(APPLICATION_JSON) + .extract() + .as(AnnouncementPageResultDTO.class); + + Assertions.assertThat(data).isNotNull(); + Assertions.assertThat(data.getTotalElements()).isEqualTo(2); + Assertions.assertThat(data.getStream()).isNotNull().hasSize(2); + } + + @Test + void createAnnouncementTest() { + + // create product + var createDto = new CreateAnnouncementRequestDTO(); + + createDto.setAppId("app0"); + createDto.setContent("test01"); + createDto.setTitle("basePath"); + + var dto = given() + .when() + .contentType(APPLICATION_JSON) + .body(createDto) + .post() + .then() + .statusCode(CREATED.getStatusCode()) + .extract() + .body().as(AnnouncementDTO.class); + + assertThat(dto).isNotNull(); + assertThat(dto.getAppId()).isNotNull().isEqualTo(createDto.getAppId()); + assertThat(dto.getTitle()).isNotNull().isEqualTo(createDto.getTitle()); + + // create theme without body + var exception = given() + .when() + .contentType(APPLICATION_JSON) + .post() + .then() + .statusCode(BAD_REQUEST.getStatusCode()) + .extract().as(ProblemDetailResponseDTO.class); + + assertThat(exception.getErrorCode()).isEqualTo(AnnouncementMapper.ErrorKeys.CONSTRAINT_VIOLATIONS.name()); + assertThat(exception.getDetail()).isEqualTo("createAnnouncement.createAnnouncementRequestDTO: must not be null"); + + // create theme with existing name + dto = given().when() + .contentType(APPLICATION_JSON) + .body(createDto) + .post() + .then() + .statusCode(CREATED.getStatusCode()) + .extract().as(AnnouncementDTO.class); + + assertThat(dto).isNotNull(); + assertThat(dto.getAppId()).isNotNull().isEqualTo(createDto.getAppId()); + assertThat(dto.getTitle()).isNotNull().isEqualTo(createDto.getTitle()); + } + + @Test + void deleteAnnouncementTest() { + // delete + given() + .contentType(APPLICATION_JSON) + .delete("a1") + .then().statusCode(NO_CONTENT.getStatusCode()); + + // check if exists + given() + .contentType(APPLICATION_JSON) + .get("a1") + .then().statusCode(NOT_FOUND.getStatusCode()); + + // delete + given() + .contentType(APPLICATION_JSON) + .delete("a1") + .then() + .statusCode(NO_CONTENT.getStatusCode()); + } + + @Test + void getAnnouncementTest() { + var dto = given() + .contentType(APPLICATION_JSON) + .get("a2") + .then() + .statusCode(OK.getStatusCode()) + .contentType(APPLICATION_JSON) + .extract() + .body().as(AnnouncementDTO.class); + + assertThat(dto).isNotNull(); + assertThat(dto.getAppId()).isEqualTo("app2"); + assertThat(dto.getTitle()).isEqualTo("title2"); + + given() + .contentType(APPLICATION_JSON) + .get("does-not-exists") + .then().statusCode(NOT_FOUND.getStatusCode()); + } + + @Test + void updateAnnouncementTest() { + var updateDto = new UpdateAnnouncementRequestDTO(); + updateDto.setTitle("test01"); + updateDto.setContent("0.0.0"); + + given() + .contentType(APPLICATION_JSON) + .body(updateDto) + .when() + .put("does-not-exists") + .then() + .statusCode(NOT_FOUND.getStatusCode()); + + given() + .contentType(APPLICATION_JSON) + .body(updateDto) + .when() + .put("a1") + .then().statusCode(OK.getStatusCode()); + + var dto = given().contentType(APPLICATION_JSON) + .body(updateDto) + .when() + .get("a1") + .then().statusCode(OK.getStatusCode()) + .contentType(APPLICATION_JSON) + .extract() + .body().as(AnnouncementDTO.class); + + assertThat(dto).isNotNull(); + assertThat(dto.getTitle()).isEqualTo(updateDto.getTitle()); + } + + @Test + void updateAnnouncementWithoutBodyTest() { + + var exception = given() + .contentType(APPLICATION_JSON) + .when() + .put("update_create_new") + .then() + .statusCode(BAD_REQUEST.getStatusCode()) + .extract().as(ProblemDetailResponseDTO.class); + + assertThat(exception).isNotNull(); + assertThat(exception.getErrorCode()).isEqualTo(AnnouncementMapper.ErrorKeys.CONSTRAINT_VIOLATIONS.name()); + assertThat(exception.getDetail()).isEqualTo("updateAnnouncementById.updateAnnouncementRequestDTO: must not be null"); + assertThat(exception.getInvalidParams()).isNotNull().asList().hasSize(1); + + } + + @Test + void getAllAnnouncementAppsTest() { + var dto = given() + .contentType(APPLICATION_JSON) + .get("appIds") + .then() + .statusCode(OK.getStatusCode()) + .contentType(APPLICATION_JSON) + .extract() + .body().as(AnnouncementAppsDTO.class); + + assertThat(dto).isNotNull(); + assertThat(dto.getAppIds()).isNotNull().asList().hasSize(2); + } + + @Test + void getAnnouncementsByCriteriaOrg200Test() { + AnnouncementSearchCriteriaDTO criteria = new AnnouncementSearchCriteriaDTO(); + criteria.setAppId("app2"); + criteria.status(AnnouncementStatusDTO.ACTIVE); + criteria.setPriority(AnnouncementPriorityTypeDTO.NORMAL); + criteria.setType(AnnouncementTypeDTO.EVENT); + criteria.setStartDateFrom(OffsetDateTime.parse("2000-03-10T12:15:50-04:00")); + criteria.setStartDateTo(OffsetDateTime.parse("2023-03-10T12:15:50-04:00")); + criteria.setEndDateFrom(OffsetDateTime.parse("2000-03-10T12:15:50-04:00")); + criteria.setEndDateTo(OffsetDateTime.parse("2023-03-10T12:15:50-04:00")); + + var data = given() + .contentType(APPLICATION_JSON) + .header(APM_HEADER_PARAM, createToken("org2")) + .body(criteria) + .post("search") + .then() + .statusCode(OK.getStatusCode()) + .contentType(APPLICATION_JSON) + .extract() + .as(AnnouncementPageResultDTO.class); + + Assertions.assertThat(data).isNotNull(); + Assertions.assertThat(data.getTotalElements()).isEqualTo(1); + Assertions.assertThat(data.getStream()).isNotNull().hasSize(1); + Assertions.assertThat(data.getStream().get(0)).isNotNull(); + Assertions.assertThat(data.getStream().get(0).getId()).isEqualTo("a3-200"); + } +} diff --git a/src/test/java/io/github/onecx/announcement/rs/internal/AnnouncementControllerInternalTestIT.java b/src/test/java/io/github/onecx/announcement/rs/internal/AnnouncementControllerInternalTestIT.java new file mode 100644 index 0000000..08bb9e6 --- /dev/null +++ b/src/test/java/io/github/onecx/announcement/rs/internal/AnnouncementControllerInternalTestIT.java @@ -0,0 +1,8 @@ +package io.github.onecx.announcement.rs.internal; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +class AnnouncementControllerInternalTestIT extends AnnouncementControllerInternalTest { + +} diff --git a/src/test/java/io/github/onecx/announcement/test/AbstractTest.java b/src/test/java/io/github/onecx/announcement/test/AbstractTest.java new file mode 100644 index 0000000..8aec6c2 --- /dev/null +++ b/src/test/java/io/github/onecx/announcement/test/AbstractTest.java @@ -0,0 +1,54 @@ +package io.github.onecx.announcement.test; + +import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS; +import static io.restassured.RestAssured.config; +import static io.restassured.config.ObjectMapperConfig.objectMapperConfig; + +import java.security.PrivateKey; + +import jakarta.json.Json; +import jakarta.json.JsonObjectBuilder; + +import org.eclipse.microprofile.config.ConfigProvider; +import org.eclipse.microprofile.jwt.Claims; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +import io.restassured.config.RestAssuredConfig; +import io.smallrye.jwt.build.Jwt; +import io.smallrye.jwt.util.KeyUtils; + +@SuppressWarnings("java:S2187") +public abstract class AbstractTest { + + protected static final String APM_HEADER_PARAM = ConfigProvider.getConfig() + .getValue("%test.tkit.rs.context.tenant-id.mock.token-header-param", String.class); + protected static final String CLAIMS_ORG_ID = ConfigProvider.getConfig() + .getValue("%test.tkit.rs.context.tenant-id.mock.claim-org-id", String.class);; + + static { + config = RestAssuredConfig.config().objectMapperConfig( + objectMapperConfig().jackson2ObjectMapperFactory( + (cls, charset) -> { + var objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.configure(WRITE_DATES_AS_TIMESTAMPS, false); + return objectMapper; + })); + } + + protected static String createToken(String organizationId) { + try { + String userName = "test-user"; + JsonObjectBuilder claims = Json.createObjectBuilder(); + claims.add(Claims.preferred_username.name(), userName); + claims.add(Claims.sub.name(), userName); + claims.add(CLAIMS_ORG_ID, organizationId); + PrivateKey privateKey = KeyUtils.generateKeyPair(2048).getPrivate(); + return Jwt.claims(claims.build()).sign(privateKey); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/src/test/java/org/onecx/announcement/rs/external/v1/AnnouncementExternalControllerTest.java b/src/test/java/org/onecx/announcement/rs/external/v1/AnnouncementExternalControllerTest.java deleted file mode 100644 index cf0c425..0000000 --- a/src/test/java/org/onecx/announcement/rs/external/v1/AnnouncementExternalControllerTest.java +++ /dev/null @@ -1,199 +0,0 @@ -package org.onecx.announcement.rs.external.v1; - -import static io.restassured.RestAssured.given; -import static org.assertj.core.api.Assertions.assertThat; - -import java.text.ParseException; -import java.time.*; -import java.util.ArrayList; -import java.util.List; - -import jakarta.ws.rs.core.MediaType; - -import org.junit.jupiter.api.Test; -import org.tkit.quarkus.test.WithDBData; - -import gen.io.github.onecx.announcement.v1.model.*; -import io.quarkus.test.junit.QuarkusTest; - -@QuarkusTest -class AnnouncementExternalControllerTest { - String ANNOUNCEMENT_CONTROLLER_V1_ENDPOINT = "/v1/applications"; - - @Test - @WithDBData(value = { "ahm-testdata.xml" }, deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullySearchForOneResultWithId() throws ParseException { - String fetchedId = "123"; - String creationUser = "Test User"; - var response = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .get(ANNOUNCEMENT_CONTROLLER_V1_ENDPOINT + "/announcements/" + fetchedId) - .prettyPeek(); - - AnnouncementDTOV1 announcements = response.as(AnnouncementDTOV1.class); - // then - response.then().statusCode(200); - assertThat(announcements.getId()).isEqualTo(fetchedId); - assertThat(announcements.getCreationUser()).isEqualTo(creationUser); - } - - @Test - @WithDBData(value = { "ahm-testdata.xml" }, deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullySearchForOneResultWithCriteriaV1() throws ParseException { - String announcementId = "123"; - String creationUser = "Test User"; - OffsetDateTime startDateFrom = OffsetDateTime.parse("2009-12-30T14:55:00+00:00"); - OffsetDateTime startDateTo = OffsetDateTime.parse("2010-01-01T14:55:00+00:00"); - - SearchAnnouncementRequestDTOV1 searchAnnouncementRequestDTOV1 = new SearchAnnouncementRequestDTOV1(); - searchAnnouncementRequestDTOV1.setStartDateFrom(startDateFrom); - searchAnnouncementRequestDTOV1.setStartDateTo(startDateTo); - - searchAnnouncementRequestDTOV1.setType(AnnouncementTypeDTOV1.EVENT); - var response = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .body(searchAnnouncementRequestDTOV1) - .post(ANNOUNCEMENT_CONTROLLER_V1_ENDPOINT + "/announcements/search/") - .prettyPeek(); - - AnnouncementPageResultDTOV1 announcements = response.as(AnnouncementPageResultDTOV1.class); - // then - response.then().statusCode(200); - assertThat(announcements.getTotalElements()).isEqualTo(1); - assertThat(announcements.getStream().get(0).getId()).isEqualTo(announcementId); - assertThat(announcements.getStream().get(0).getCreationUser()).isEqualTo(creationUser); - } - - @Test - @WithDBData(value = "ahm-testdata.xml", deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullyFetchAllAnnouncementsV1() throws ParseException { - SearchAnnouncementRequestDTOV1 searchAnnouncementRequestDTOV1 = new SearchAnnouncementRequestDTOV1(); - var response = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .body(searchAnnouncementRequestDTOV1) - .post(ANNOUNCEMENT_CONTROLLER_V1_ENDPOINT + "/announcements/search") - .prettyPeek(); - - AnnouncementPageResultDTOV1 announcements = response.as(AnnouncementPageResultDTOV1.class); - // then - response.then().statusCode(200); - assertThat(announcements.getTotalElements()).isEqualTo(500); - } - - @Test - @WithDBData(value = "ahm-testdata.xml", deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullyFetchAnnouncementsWithPageSize10() throws ParseException { - int pageSize = 10; - int pageNumber = 7; - SearchAnnouncementRequestDTOV1 searchAnnouncementRequestDTOV1 = new SearchAnnouncementRequestDTOV1(); - searchAnnouncementRequestDTOV1.setPageSize(pageSize); - searchAnnouncementRequestDTOV1.setPageNumber(pageNumber); - var response = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .body(searchAnnouncementRequestDTOV1) - .post(ANNOUNCEMENT_CONTROLLER_V1_ENDPOINT + "/announcements/search") - .prettyPeek(); - - AnnouncementPageResultDTOV1 announcements = response.as(AnnouncementPageResultDTOV1.class); - // then - response.then().statusCode(200); - assertThat(announcements.getTotalElements()).isEqualTo(500); - assertThat(announcements.getTotalPages()).isEqualTo(50); - assertThat(announcements.getSize()).isEqualTo(pageSize); - assertThat(announcements.getNumber()).isEqualTo(pageNumber); - } - - @Test - @WithDBData(value = "ahm-testdata.xml", deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullyFetchAnnouncementsWithPageSize100() throws ParseException { - int pageSize = 100; - int pageNumber = 0; - SearchAnnouncementRequestDTOV1 searchAnnouncementRequestDTOV1 = new SearchAnnouncementRequestDTOV1(); - searchAnnouncementRequestDTOV1.setPageSize(pageSize); - searchAnnouncementRequestDTOV1.setPageNumber(pageNumber); - var response = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .body(searchAnnouncementRequestDTOV1) - .post(ANNOUNCEMENT_CONTROLLER_V1_ENDPOINT + "/announcements/search") - .prettyPeek(); - - AnnouncementPageResultDTOV1 announcements = response.as(AnnouncementPageResultDTOV1.class); - // then - response.then().statusCode(200); - assertThat(announcements.getTotalElements()).isEqualTo(500); - assertThat(announcements.getTotalPages()).isEqualTo(5); - assertThat(announcements.getSize()).isEqualTo(pageSize); - assertThat(announcements.getNumber()).isEqualTo(pageNumber); - } - - @Test - @WithDBData(value = { "ahm-testdata.xml" }, deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullyFetchAnnouncementsWithPageSize200() throws ParseException { - int pageSize = 200; - int pageNumber = 1; - SearchAnnouncementRequestDTOV1 searchAnnouncementRequestDTOV1 = new SearchAnnouncementRequestDTOV1(); - searchAnnouncementRequestDTOV1.setPageSize(pageSize); - searchAnnouncementRequestDTOV1.setPageNumber(pageNumber); - var response = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .body(searchAnnouncementRequestDTOV1) - .post(ANNOUNCEMENT_CONTROLLER_V1_ENDPOINT + "/announcements/search") - .prettyPeek(); - - AnnouncementPageResultDTOV1 announcements = response.as(AnnouncementPageResultDTOV1.class); - // then - response.then().statusCode(200); - assertThat(announcements.getTotalElements()).isEqualTo(500); - assertThat(announcements.getTotalPages()).isEqualTo(3); - assertThat(announcements.getSize()).isEqualTo(pageSize); - assertThat(announcements.getNumber()).isEqualTo(pageNumber); - } - - @Test - @WithDBData(value = { "ahm-testdata.xml" }, deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullyFetchAnnouncementsWithPageSize500() throws ParseException { - int pageSize = 500; - int pageNumber = 0; - SearchAnnouncementRequestDTOV1 searchAnnouncementRequestDTOV1 = new SearchAnnouncementRequestDTOV1(); - searchAnnouncementRequestDTOV1.setPageSize(pageSize); - searchAnnouncementRequestDTOV1.setPageNumber(pageNumber); - var response = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .body(searchAnnouncementRequestDTOV1) - .post(ANNOUNCEMENT_CONTROLLER_V1_ENDPOINT + "/announcements/search") - .prettyPeek(); - - AnnouncementPageResultDTOV1 announcements = response.as(AnnouncementPageResultDTOV1.class); - // then - response.then().statusCode(200); - assertThat(announcements.getTotalElements()).isEqualTo(500); - assertThat(announcements.getTotalPages()).isEqualTo(1); - assertThat(announcements.getSize()).isEqualTo(pageSize); - assertThat(announcements.getNumber()).isEqualTo(pageNumber); - } - - @Test - @WithDBData(value = { "ahm-testdata.xml" }, deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullyDeleteAnnouncementsWithAppIds() throws ParseException { - List appIds = new ArrayList<>(); - appIds.add("support-tool-ui"); - DeleteAnnouncementRequestDTOV1 deleteAnnouncementRequestDTOV1 = new DeleteAnnouncementRequestDTOV1(); - deleteAnnouncementRequestDTOV1.setAppIds(appIds); - - var response = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .body(deleteAnnouncementRequestDTOV1) - .delete(ANNOUNCEMENT_CONTROLLER_V1_ENDPOINT) - .prettyPeek(); - - response.then().statusCode(204); - } -} diff --git a/src/test/java/org/onecx/announcement/rs/external/v1/AnnouncementExternalControllerTestIT.java b/src/test/java/org/onecx/announcement/rs/external/v1/AnnouncementExternalControllerTestIT.java deleted file mode 100644 index c534908..0000000 --- a/src/test/java/org/onecx/announcement/rs/external/v1/AnnouncementExternalControllerTestIT.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.onecx.announcement.rs.external.v1; - -import io.quarkus.test.junit.QuarkusIntegrationTest; - -@QuarkusIntegrationTest -public class AnnouncementExternalControllerTestIT extends AnnouncementExternalControllerTest { -} diff --git a/src/test/java/org/onecx/announcement/rs/internal/AnnouncementAPITest.java b/src/test/java/org/onecx/announcement/rs/internal/AnnouncementAPITest.java deleted file mode 100644 index 756be07..0000000 --- a/src/test/java/org/onecx/announcement/rs/internal/AnnouncementAPITest.java +++ /dev/null @@ -1,172 +0,0 @@ -package org.onecx.announcement.rs.internal; - -import static io.restassured.RestAssured.given; -import static org.assertj.core.api.Assertions.assertThat; - -import java.text.ParseException; -import java.time.*; - -import jakarta.ws.rs.core.MediaType; - -import org.junit.jupiter.api.Test; -import org.tkit.quarkus.test.WithDBData; - -import gen.io.github.onecx.announcement.rs.internal.model.*; -import io.quarkus.test.junit.QuarkusTest; -import lombok.extern.slf4j.Slf4j; - -@QuarkusTest -@Slf4j -class AnnouncementAPITest { - String ANNOUNCEMENT_ITEM_INTERNAL_ENDPOINT = "/internal/announcements"; - - @Test - @WithDBData(value = { "ahm-testdata.xml" }, deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullySearchForOneResultWithCriteria() throws ParseException { - String fetchedId = "123"; - SearchAnnouncementRequestDTO searchAnnouncementRequestDTO = new SearchAnnouncementRequestDTO(); - OffsetDateTime startDateFrom = OffsetDateTime.parse("2009-12-30T14:55:00+00:00"); - OffsetDateTime startDateTo = OffsetDateTime.parse("2010-01-01T14:55:00+00:00"); - - searchAnnouncementRequestDTO.setStartDateFrom(startDateFrom); - searchAnnouncementRequestDTO.setStartDateTo(startDateTo); - searchAnnouncementRequestDTO.setType(AnnouncementTypeDTO.EVENT); - - // when - var response = given() - .when() - .body(searchAnnouncementRequestDTO) - .contentType(MediaType.APPLICATION_JSON) - .post(ANNOUNCEMENT_ITEM_INTERNAL_ENDPOINT + "/search") - .prettyPeek(); - - AnnouncementPageResultDTO announcementPageResultDTO = response.as(AnnouncementPageResultDTO.class); - // then - response.then().statusCode(200); - assertThat(announcementPageResultDTO.getTotalElements()).isEqualTo(1); - assertThat(announcementPageResultDTO.getStream().get(0).getId()).isEqualTo(fetchedId); - } - - @Test - @WithDBData(value = { "ahm-testdata.xml" }, deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullyFetchAllAnnouncements() throws ParseException { - // when - SearchAnnouncementRequestDTO searchAnnouncementRequestDTO = new SearchAnnouncementRequestDTO(); - var response = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .body(searchAnnouncementRequestDTO) - .post(ANNOUNCEMENT_ITEM_INTERNAL_ENDPOINT + "/search") - .prettyPeek(); - - AnnouncementPageResultDTO announcementPageResultDTO = response.as(AnnouncementPageResultDTO.class); - // then - response.then().statusCode(200); - assertThat(announcementPageResultDTO.getTotalElements()).isEqualTo(500); - } - - @Test - @WithDBData(value = { "ahm-testdata.xml" }, deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullyDeleteAnnouncement() { - String announcementId = "123"; - // when - var deleteResponse = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .delete(ANNOUNCEMENT_ITEM_INTERNAL_ENDPOINT + '/' + announcementId) - .prettyPeek(); - - // then - deleteResponse.then().statusCode(204); - - var getResponse = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .get(ANNOUNCEMENT_ITEM_INTERNAL_ENDPOINT + '/' + announcementId) - .prettyPeek(); - - // then - getResponse.then().statusCode(404); - } - - @Test - @WithDBData(value = { "ahm-testdata.xml" }, deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullyFetchAnnouncementWithId() throws ParseException { - String announcementId = "123"; - // when - var response = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .get(ANNOUNCEMENT_ITEM_INTERNAL_ENDPOINT + "/" + announcementId) - .prettyPeek(); - - AnnouncementDTO announcementDTO = response.as(AnnouncementDTO.class); - // then - response.then().statusCode(200); - assertThat(announcementDTO.getId()).isEqualTo(announcementId); - } - - @Test - @WithDBData(value = { "ahm-testdata.xml" }, deleteAfterTest = true, deleteBeforeInsert = true) - void shouldCorrectlyCreateAnnouncement() { - CreateAnnouncementRequestDTO announcementCreateDTO = new CreateAnnouncementRequestDTO(); - String appId = "support-tool-ui"; - String content = "Some content of the announcement"; - String title = "Important Announcement"; - AnnouncementTypeDTO type = AnnouncementTypeDTO.INFO; - - announcementCreateDTO.setAppId(appId); - announcementCreateDTO.setContent(content); - announcementCreateDTO.setTitle(title); - announcementCreateDTO.setType(type); - // when - var createResponse = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .body(announcementCreateDTO) - .post(ANNOUNCEMENT_ITEM_INTERNAL_ENDPOINT) - .prettyPeek(); - - // then - createResponse.then().statusCode(201); - AnnouncementDTO announcementDTO = createResponse.as(AnnouncementDTO.class); - assertThat(announcementDTO.getAppId()).isEqualTo(appId); - assertThat(announcementDTO.getType()).isEqualTo(type); - assertThat(announcementDTO.getTitle()).isEqualTo(title); - } - - @Test - @WithDBData(value = { "ahm-testdata.xml" }, deleteAfterTest = true, deleteBeforeInsert = true) - void shouldSuccessfullyUpdateAnnouncement() throws ParseException { - String announcementId = "123"; - UpdateAnnouncementRequestDTO updateAnnouncementRequestDTO = new UpdateAnnouncementRequestDTO(); - String appId = "ahm-ui"; - - updateAnnouncementRequestDTO.setAppId(appId); - updateAnnouncementRequestDTO.setPriority(AnnouncementPriorityTypeDTO.LOW); - updateAnnouncementRequestDTO.setType(AnnouncementTypeDTO.INFO); - // when - var patchResponse = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .body(updateAnnouncementRequestDTO) - .put(ANNOUNCEMENT_ITEM_INTERNAL_ENDPOINT + '/' + announcementId) - .prettyPeek(); - - // then - patchResponse.then().statusCode(200); - - AnnouncementDTO response = given() - .when() - .contentType(MediaType.APPLICATION_JSON) - .get(ANNOUNCEMENT_ITEM_INTERNAL_ENDPOINT + '/' + announcementId) - .then() - .statusCode(200) - .extract().body().as(AnnouncementDTO.class); - - // then - assertThat(response.getAppId()).isEqualTo(appId); - assertThat(response.getPriority()).isEqualTo(AnnouncementPriorityTypeDTO.LOW); - assertThat(response.getType()).isEqualTo(AnnouncementTypeDTO.INFO); - } -} diff --git a/src/test/java/org/onecx/announcement/rs/internal/AnnouncementItemAPITestIT.java b/src/test/java/org/onecx/announcement/rs/internal/AnnouncementItemAPITestIT.java deleted file mode 100644 index b689044..0000000 --- a/src/test/java/org/onecx/announcement/rs/internal/AnnouncementItemAPITestIT.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.onecx.announcement.rs.internal; - -import io.quarkus.test.junit.QuarkusIntegrationTest; - -@QuarkusIntegrationTest -public class AnnouncementItemAPITestIT extends AnnouncementAPITest { -} diff --git a/src/test/java/org/onecx/announcement/rs/test/AbstractTest.java b/src/test/java/org/onecx/announcement/rs/test/AbstractTest.java deleted file mode 100644 index 609ffaa..0000000 --- a/src/test/java/org/onecx/announcement/rs/test/AbstractTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.onecx.announcement.rs.test; - -import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS; -import static io.restassured.RestAssured.config; -import static io.restassured.config.ObjectMapperConfig.objectMapperConfig; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; - -import io.restassured.config.RestAssuredConfig; - -@SuppressWarnings("java:S2187") -public class AbstractTest { - - static { - config = RestAssuredConfig.config().objectMapperConfig( - objectMapperConfig().jackson2ObjectMapperFactory( - (cls, charset) -> { - var objectMapper = new ObjectMapper(); - objectMapper.registerModule(new JavaTimeModule()); - objectMapper.configure(WRITE_DATES_AS_TIMESTAMPS, false); - return objectMapper; - })); - } -} diff --git a/src/test/resources/META-INF/resources/test_privateKey.pem b/src/test/resources/META-INF/resources/test_privateKey.pem deleted file mode 100644 index 82e5e9b..0000000 --- a/src/test/resources/META-INF/resources/test_privateKey.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCWK8UjyoHgPTLa -PLQJ8SoXLLjpHSjtLxMqmzHnFscqhTVVaDpCRCb6e3Ii/WniQTWw8RA7vf4djz4H -OzvlfBFNgvUGZHXDwnmGaNVaNzpHYFMEYBhE8VGGiveSkzqeLZI+Y02G6sQAfDtN -qqzM/l5QX8X34oQFaTBW1r49nftvCpITiwJvWyhkWtXP9RP8sXi1im5Vi3dhupOh -nelk5n0BfajUYIbfHA6ORzjHRbt7NtBl0L2J+0/FUdHyKs6KMlFGNw8O0Dq88qnM -uXoLJiewhg9332W3DFMeOveel+//cvDnRsCRtPgd4sXFPHh+UShkso7+DRsChXa6 -oGGQD3GdAgMBAAECggEAAjfTSZwMHwvIXIDZB+yP+pemg4ryt84iMlbofclQV8hv -6TsI4UGwcbKxFOM5VSYxbNOisb80qasb929gixsyBjsQ8284bhPJR7r0q8h1C+jY -URA6S4pk8d/LmFakXwG9Tz6YPo3pJziuh48lzkFTk0xW2Dp4SLwtAptZY/+ZXyJ6 -96QXDrZKSSM99Jh9s7a0ST66WoxSS0UC51ak+Keb0KJ1jz4bIJ2C3r4rYlSu4hHB -Y73GfkWORtQuyUDa9yDOem0/z0nr6pp+pBSXPLHADsqvZiIhxD/O0Xk5I6/zVHB3 -zuoQqLERk0WvA8FXz2o8AYwcQRY2g30eX9kU4uDQAQKBgQDmf7KGImUGitsEPepF -KH5yLWYWqghHx6wfV+fdbBxoqn9WlwcQ7JbynIiVx8MX8/1lLCCe8v41ypu/eLtP -iY1ev2IKdrUStvYRSsFigRkuPHUo1ajsGHQd+ucTDf58mn7kRLW1JGMeGxo/t32B -m96Af6AiPWPEJuVfgGV0iwg+HQKBgQCmyPzL9M2rhYZn1AozRUguvlpmJHU2DpqS -34Q+7x2Ghf7MgBUhqE0t3FAOxEC7IYBwHmeYOvFR8ZkVRKNF4gbnF9RtLdz0DMEG -5qsMnvJUSQbNB1yVjUCnDAtElqiFRlQ/k0LgYkjKDY7LfciZl9uJRl0OSYeX/qG2 -tRW09tOpgQKBgBSGkpM3RN/MRayfBtmZvYjVWh3yjkI2GbHA1jj1g6IebLB9SnfL -WbXJErCj1U+wvoPf5hfBc7m+jRgD3Eo86YXibQyZfY5pFIh9q7Ll5CQl5hj4zc4Y -b16sFR+xQ1Q9Pcd+BuBWmSz5JOE/qcF869dthgkGhnfVLt/OQzqZluZRAoGAXQ09 -nT0TkmKIvlza5Af/YbTqEpq8mlBDhTYXPlWCD4+qvMWpBII1rSSBtftgcgca9XLB -MXmRMbqtQeRtg4u7dishZVh1MeP7vbHsNLppUQT9Ol6lFPsd2xUpJDc6BkFat62d -Xjr3iWNPC9E9nhPPdCNBv7reX7q81obpeXFMXgECgYEAmk2Qlus3OV0tfoNRqNpe -Mb0teduf2+h3xaI1XDIzPVtZF35ELY/RkAHlmWRT4PCdR0zXDidE67L6XdJyecSt -FdOUH8z5qUraVVebRFvJqf/oGsXc4+ex1ZKUTbY0wqY1y9E39yvB3MaTmZFuuqk8 -f3cg+fr8aou7pr9SHhJlZCU= ------END PRIVATE KEY----- \ No newline at end of file diff --git a/src/test/resources/META-INF/resources/test_publicKey.pem b/src/test/resources/META-INF/resources/test_publicKey.pem deleted file mode 100644 index 12a18c1..0000000 --- a/src/test/resources/META-INF/resources/test_publicKey.pem +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq -Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR -TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e -UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9 -AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn -sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x -nQIDAQAB ------END PUBLIC KEY----- \ No newline at end of file diff --git a/src/test/resources/META-INF/resources/test_tokens/admin_token.json b/src/test/resources/META-INF/resources/test_tokens/admin_token.json deleted file mode 100644 index a50871d..0000000 --- a/src/test/resources/META-INF/resources/test_tokens/admin_token.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "jti": "e734f6c2-f1af-4e4d-b373-64d6b7f66655", - "nbf": 0, - "iss": "https://quarkus.io/using-jwt-rbac", - "aud": "portal-launchpad-ui", - "sub": "f586d429-3da2-40cf-94e2-de21276917f8", - "typ": "Bearer", - "azp": "portal-launchpad-ui", - "auth_time": 0, - "session_state": "e3307cd4-2f2e-4373-b754-7091dad3d6e8", - "acr": "1", - "allowed-origins": [ - "http://localhost:4500" - ], - "realm_access": { - "roles": [ - "tkit-portal-admin" - ] - }, - "resource_access": { - "realm-management": { - "roles": [ - "view-realm", - "view-identity-providers", - "manage-identity-providers", - "impersonation", - "realm-admin", - "create-client", - "manage-users", - "query-realms", - "view-authorization", - "query-clients", - "query-users", - "manage-events", - "manage-realm", - "view-events", - "view-users", - "view-clients", - "manage-authorization", - "manage-clients", - "query-groups" - ] - }, - "account": { - "roles": [ - "manage-account", - "manage-account-links", - "view-profile" - ] - } - }, - "name": "Test Test", - "preferred_username": "admin", - "given_name": "TestGivenName", - "family_name": "TestFamilyName" -} \ No newline at end of file diff --git a/src/test/resources/META-INF/resources/test_tokens/non_admin_token.json b/src/test/resources/META-INF/resources/test_tokens/non_admin_token.json deleted file mode 100644 index bd92787..0000000 --- a/src/test/resources/META-INF/resources/test_tokens/non_admin_token.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "jti": "e734f6c2-f1af-4e4d-b373-64d6b7f66655", - "nbf": 0, - "iss": "https://quarkus.io/using-jwt-rbac", - "aud": "portal-launchpad-ui", - "sub": "f586d429-3da2-40cf-94e2-de21276917f8", - "typ": "Bearer", - "azp": "portal-launchpad-ui", - "auth_time": 0, - "session_state": "e3307cd4-2f2e-4373-b754-7091dad3d6e8", - "acr": "1", - "allowed-origins": [ - "http://localhost:4500" - ], - "realm_access": { - "roles": [ - "portal-user" - ] - }, - "resource_access": { - "realm-management": { - "roles": [ - "view-realm", - "view-identity-providers", - "manage-identity-providers", - "impersonation", - "realm-admin", - "create-client", - "manage-users", - "query-realms", - "view-authorization", - "query-clients", - "query-users", - "manage-events", - "manage-realm", - "view-events", - "view-users", - "view-clients", - "manage-authorization", - "manage-clients", - "query-groups" - ] - }, - "account": { - "roles": [ - "manage-account", - "manage-account-links", - "view-profile" - ] - } - }, - "name": "Test Test", - "preferred_username": "1", - "given_name": "TestGivenName", - "family_name": "TestFamilyName" -} \ No newline at end of file diff --git a/src/test/resources/data/test-internal.xml b/src/test/resources/data/test-internal.xml new file mode 100644 index 0000000..4202405 --- /dev/null +++ b/src/test/resources/data/test-internal.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/data/test-v1.xml b/src/test/resources/data/test-v1.xml new file mode 100644 index 0000000..bac8231 --- /dev/null +++ b/src/test/resources/data/test-v1.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file