diff --git a/pom.xml b/pom.xml index 2713e81d..91c05f6e 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ 3.8.1 1.7.10 1.18.24 - 11 + 17 UTF-8 UTF-8 quarkus-bom @@ -177,6 +177,7 @@ + org.apache.maven.plugins maven-surefire-plugin ${surefire-plugin.version} @@ -208,6 +209,7 @@ + org.apache.maven.plugins maven-failsafe-plugin ${surefire-plugin.version} diff --git a/src/main/kotlin/org/kravbank/domain/Publication.kt b/src/main/kotlin/org/kravbank/domain/Publication.kt index 071bbbe1..889dd011 100644 --- a/src/main/kotlin/org/kravbank/domain/Publication.kt +++ b/src/main/kotlin/org/kravbank/domain/Publication.kt @@ -1,14 +1,13 @@ -package org.kravbank.domain; +package org.kravbank.domain import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonManagedReference -import io.quarkus.hibernate.orm.panache.PanacheEntity; import java.time.LocalDateTime import java.util.* import javax.persistence.* @Entity -class Publication : PanacheEntity() { +class Publication : SoftDeletable() { var comment: String = "" @@ -19,7 +18,7 @@ class Publication : PanacheEntity() { @Column(unique = true) var ref: String = UUID.randomUUID().toString() - var deletedDate: LocalDateTime? = null + override var deletedDate: LocalDateTime? = null @ManyToOne( cascade = [CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH], //CascadeType.Detach diff --git a/src/main/kotlin/org/kravbank/domain/SoftDeletable.kt b/src/main/kotlin/org/kravbank/domain/SoftDeletable.kt new file mode 100644 index 00000000..a15b957e --- /dev/null +++ b/src/main/kotlin/org/kravbank/domain/SoftDeletable.kt @@ -0,0 +1,8 @@ +package org.kravbank.domain + +import io.quarkus.hibernate.orm.panache.PanacheEntity +import java.time.LocalDateTime + +sealed class SoftDeletable: PanacheEntity() { + abstract var deletedDate: LocalDateTime? +} \ No newline at end of file diff --git a/src/main/kotlin/org/kravbank/repository/BackendRepository.kt b/src/main/kotlin/org/kravbank/repository/BackendRepository.kt new file mode 100644 index 00000000..6b6e4fa9 --- /dev/null +++ b/src/main/kotlin/org/kravbank/repository/BackendRepository.kt @@ -0,0 +1,18 @@ +package org.kravbank.repository + +import io.quarkus.hibernate.orm.panache.PanacheEntity +import io.quarkus.hibernate.orm.panache.PanacheRepository +import org.kravbank.domain.SoftDeletable +import java.time.LocalDateTime + +open class BackendRepository : PanacheRepository { + override fun delete(entity: T) = when (entity) { + is SoftDeletable -> { + val deletedDate = LocalDateTime.now() + entity.deletedDate = deletedDate + persistAndFlush(entity) + } else -> { + super.delete(entity) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/kravbank/repository/CodelistRepository.kt b/src/main/kotlin/org/kravbank/repository/CodelistRepository.kt index 3d801d41..0869c446 100644 --- a/src/main/kotlin/org/kravbank/repository/CodelistRepository.kt +++ b/src/main/kotlin/org/kravbank/repository/CodelistRepository.kt @@ -1,19 +1,17 @@ package org.kravbank.repository -import io.quarkus.hibernate.orm.panache.PanacheRepository import org.kravbank.domain.Codelist import org.kravbank.lang.BackendException import org.kravbank.lang.BadRequestException import org.kravbank.lang.NotFoundException import org.kravbank.utils.Messages.RepoErrorMsg.CODELIST_BADREQUEST_CREATE -import org.kravbank.utils.Messages.RepoErrorMsg.CODELIST_BADREQUEST_DELETE import org.kravbank.utils.Messages.RepoErrorMsg.CODELIST_BADREQUEST_UPDATE import org.kravbank.utils.Messages.RepoErrorMsg.CODELIST_NOTFOUND import java.util.* import javax.enterprise.context.ApplicationScoped @ApplicationScoped -class CodelistRepository : PanacheRepository { +class CodelistRepository : BackendRepository() { @Throws(BackendException::class) fun findByRef(projectId: Long, ref: String): Codelist { @@ -43,12 +41,9 @@ class CodelistRepository : PanacheRepository { } @Throws(BackendException::class) - fun deleteCodelist(projectId: Long, codelistRef: String): Codelist { - val deleted: Boolean + fun deleteCodelist(projectId: Long, codelistRef: String): Boolean { val found = findByRef(projectId, codelistRef) - deleted = deleteById(found.id) - if (!deleted) throw BadRequestException(CODELIST_BADREQUEST_DELETE) - return found + return deleteById(found.id) } @Throws(BackendException::class) diff --git a/src/main/kotlin/org/kravbank/repository/PublicationRepository.kt b/src/main/kotlin/org/kravbank/repository/PublicationRepository.kt index eee77746..0a4836a2 100644 --- a/src/main/kotlin/org/kravbank/repository/PublicationRepository.kt +++ b/src/main/kotlin/org/kravbank/repository/PublicationRepository.kt @@ -1,6 +1,5 @@ package org.kravbank.repository -import io.quarkus.hibernate.orm.panache.PanacheRepository import org.kravbank.domain.Publication import org.kravbank.lang.BackendException import org.kravbank.lang.BadRequestException @@ -8,13 +7,11 @@ import org.kravbank.lang.NotFoundException import org.kravbank.utils.Messages.RepoErrorMsg.PUBLICATION_BADREQUEST_CREATE import org.kravbank.utils.Messages.RepoErrorMsg.PUBLICATION_BADREQUEST_UPDATE import org.kravbank.utils.Messages.RepoErrorMsg.PUBLICATION_NOTFOUND -import java.time.LocalDateTime import java.util.* import javax.enterprise.context.ApplicationScoped -import kotlin.streams.toList @ApplicationScoped -class PublicationRepository : PanacheRepository { +class PublicationRepository : BackendRepository() { @Throws(BackendException::class) fun findByRef(projectId: Long, ref: String): Publication { val publication = @@ -43,13 +40,6 @@ class PublicationRepository : PanacheRepository { } } - fun deletePublication(id: Long): Boolean { - val deletedDate = LocalDateTime.now() - val updates = update("deleteddate = ?1 where id = ?2", deletedDate, id) - if (updates > 0) return true - return false - } - @Throws(BackendException::class) fun updatePublication(id: Long, publication: Publication) { val updated = update( diff --git a/src/main/kotlin/org/kravbank/resource/CodelistResource.kt b/src/main/kotlin/org/kravbank/resource/CodelistResource.kt index c45ccd74..645c8672 100644 --- a/src/main/kotlin/org/kravbank/resource/CodelistResource.kt +++ b/src/main/kotlin/org/kravbank/resource/CodelistResource.kt @@ -8,7 +8,6 @@ import javax.transaction.Transactional import javax.ws.rs.* import javax.ws.rs.core.MediaType.APPLICATION_JSON import javax.ws.rs.core.Response -import kotlin.streams.toList @Path("/api/v1/projects/{projectRef}/codelists") @Produces(APPLICATION_JSON) @@ -56,9 +55,8 @@ class CodelistResource(val codelistService: CodelistService) { @PathParam("projectRef") projectRef: String, @PathParam("codelistRef") codelistRef: String ): Response { - val codelist = codelistService.delete(projectRef, codelistRef) - val form = CodelistForm().fromEntity(codelist) - return Response.ok(form.ref).build() + codelistService.delete(projectRef, codelistRef) + return Response.ok(codelistRef).build() } @PUT diff --git a/src/main/kotlin/org/kravbank/service/CodelistService.kt b/src/main/kotlin/org/kravbank/service/CodelistService.kt index 1dc46eaa..e7d9fbbd 100644 --- a/src/main/kotlin/org/kravbank/service/CodelistService.kt +++ b/src/main/kotlin/org/kravbank/service/CodelistService.kt @@ -34,7 +34,7 @@ class CodelistService( } @Throws(BackendException::class) - fun delete(projectRef: String, codelistRef: String): Codelist { + fun delete(projectRef: String, codelistRef: String): Boolean { val foundProject = projectRepository.findByRef(projectRef) return codelistRepository.deleteCodelist(foundProject.id, codelistRef) } diff --git a/src/main/kotlin/org/kravbank/service/PublicationService.kt b/src/main/kotlin/org/kravbank/service/PublicationService.kt index e1f8e9a8..b92850f3 100644 --- a/src/main/kotlin/org/kravbank/service/PublicationService.kt +++ b/src/main/kotlin/org/kravbank/service/PublicationService.kt @@ -3,7 +3,6 @@ package org.kravbank.service import org.kravbank.dao.PublicationForm import org.kravbank.domain.Publication import org.kravbank.lang.BackendException -import org.kravbank.lang.BadRequestException import org.kravbank.repository.ProjectRepository import org.kravbank.repository.PublicationRepository import java.time.LocalDateTime @@ -39,9 +38,9 @@ class PublicationService( fun delete(projectRef: String, publicationRef: String): Publication { val foundProject = projectRepository.findByRef(projectRef) val publication = publicationRepository.findByRef(foundProject.id, publicationRef) - val deleted = publicationRepository.deletePublication(publication.id) - if (deleted) return publication - throw BadRequestException("Bad request! Did not delete publication") + publicationRepository.delete(publication) + return publication + // throw BadRequestException("Bad request! Did not delete publication") TODO: Put somewhere else further up in chain } @Throws(BackendException::class) diff --git a/src/test/kotlin/org/kravbank/resource/mock/CodelistResourceMockTest.kt b/src/test/kotlin/org/kravbank/resource/mock/CodelistResourceMockTest.kt index b166c1e9..e4fad7de 100644 --- a/src/test/kotlin/org/kravbank/resource/mock/CodelistResourceMockTest.kt +++ b/src/test/kotlin/org/kravbank/resource/mock/CodelistResourceMockTest.kt @@ -6,6 +6,7 @@ import io.quarkus.test.security.TestSecurity import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +import org.junit.jupiter.api.fail import org.kravbank.dao.CodelistForm import org.kravbank.domain.Codelist import org.kravbank.lang.BadRequestException @@ -17,7 +18,6 @@ import org.kravbank.utils.Messages.RepoErrorMsg.CODELIST_NOTFOUND import org.kravbank.utils.TestSetup import org.kravbank.utils.TestSetup.Arrange.codelist import org.kravbank.utils.TestSetup.Arrange.codelists -import org.kravbank.utils.TestSetup.Arrange.newCodelist_2 import org.kravbank.utils.TestSetup.Arrange.updatedCodelistForm import org.mockito.ArgumentMatchers import org.mockito.Mockito @@ -90,14 +90,31 @@ internal class CodelistResourceMockTest { val response: Response = codelistResource.listCodelists(projectRef) - val entity: List = response.entity as List + val entity = response.entity + + // Litt over-the-top her kanskje, men det viser "type narrowing", kalt "smart casts" i Kotlin + // + if (entity is List<*>) { + + assertNotNull(response) + assertEquals(Response.Status.OK.statusCode, response.status) + assertNotNull(response.entity) + assertFalse(entity.isEmpty()) + val firstObjectInList = entity[0] + if (firstObjectInList is CodelistForm) { + assertEquals(codelists[0].title, firstObjectInList.title) + assertEquals(codelists[0].description, firstObjectInList.description) + } else { + if (firstObjectInList !== null) { + fail("""Expected a list of CodelistForm, but the list contained: ${firstObjectInList::class.java.typeName}""") + } else { + fail("""Expected a list of CodelistForm, but there was no object in the list.""") + } + } + } else { + fail("""Expected a list of CodelistForm, got: ${entity::class.java.typeName}""") + } - assertNotNull(response) - assertEquals(Response.Status.OK.statusCode, response.status) - assertNotNull(response.entity) - assertFalse(entity.isEmpty()) - assertEquals(codelists[0].title, entity[0].title) - assertEquals(codelists[0].description, entity[0].description) } @Test @@ -127,13 +144,13 @@ internal class CodelistResourceMockTest { codelistRef ) ) - .thenReturn(newCodelist_2) + .thenReturn(true) val response: Response = codelistResource.deleteCodelist(projectRef, codelistRef) assertNotNull(response) - assertEquals(newCodelist_2.ref, response.entity) + assertEquals(codelistRef, response.entity) } @Test @@ -146,16 +163,17 @@ internal class CodelistResourceMockTest { ) ) .thenThrow(BadRequestException(CODELIST_BADREQUEST_DELETE)) - try { + val exception = assertThrows( + BadRequestException::class.java + ) { codelistResource.deleteCodelist( projectRef, codelistRef - ).entity as BadRequestException - - } catch (e: Exception) { - assertEquals(CODELIST_BADREQUEST_DELETE, e.message) + ) } + + assertEquals(CODELIST_BADREQUEST_DELETE, exception.message) } @Test diff --git a/src/test/kotlin/org/kravbank/service/CodelistServiceTest.kt b/src/test/kotlin/org/kravbank/service/CodelistServiceTest.kt index c140c129..b0c6af6d 100644 --- a/src/test/kotlin/org/kravbank/service/CodelistServiceTest.kt +++ b/src/test/kotlin/org/kravbank/service/CodelistServiceTest.kt @@ -11,7 +11,6 @@ import org.kravbank.utils.TestSetup import org.kravbank.utils.TestSetup.Arrange.codelist import org.kravbank.utils.TestSetup.Arrange.codelistForm import org.kravbank.utils.TestSetup.Arrange.codelists -import org.kravbank.utils.TestSetup.Arrange.newCodelist_2 import org.kravbank.utils.TestSetup.Arrange.updatedCodelistForm import org.mockito.ArgumentMatchers import org.mockito.Mockito @@ -105,13 +104,12 @@ internal class CodelistServiceTest { codelistRef ) ) - .thenReturn(newCodelist_2) + .thenReturn(true) - val mockedCodelist: Codelist = - codelistService.delete(projectRef, codelistRef) + val result = codelistService.delete(projectRef, codelistRef) - Assertions.assertNotNull(mockedCodelist) - Assertions.assertEquals(newCodelist_2, mockedCodelist) + Assertions.assertNotNull(result) + Assertions.assertEquals(true, result) } @Test