Michael Hoennig
2022-10-23 6f3c03e6b68b784bf543a36df4b68aea629b8f97
ModelMapper as Spring Bean
1 files added
44 files modified
609 ■■■■ changed files
src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountController.java 13 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java 15 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionController.java 62 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java 10 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorController.java 44 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipController.java 20 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcher.java 8 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java 58 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonController.java 15 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipController.java 22 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java 15 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/mapper/Mapper.java 22 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/mapper/MapperConfiguration.java 13 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantController.java 16 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleController.java 11 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserController.java 17 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerController.java 14 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageController.java 11 ●●●● patch | view | raw | blame | history
src/main/resources/api-definition/hs-office/hs-office-partner-schemas.yaml 5 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountControllerAcceptanceTest.java 4 ●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountControllerRestTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java 10 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRepositoryIntegrationTest.java 8 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionControllerRestTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerRestTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java 3 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerRestTest.java 7 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcherUnitTest.java 9 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java 19 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRepositoryIntegrationTest.java 8 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipRepositoryIntegrationTest.java 5 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantRepositoryIntegrationTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleControllerRestTest.java 36 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepositoryIntegrationTest.java 5 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserControllerRestTest.java 8 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserRepositoryIntegrationTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerRepositoryIntegrationTest.java 5 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageRepositoryIntegrationTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/test/MapperUnitTest.java 43 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountController.java
@@ -16,14 +16,15 @@
import java.util.List;
import java.util.UUID;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
@RestController
public class HsOfficeBankAccountController implements HsOfficeBankAccountsApi {
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private HsOfficeBankAccountRepository bankAccountRepo;
@@ -38,7 +39,7 @@
        final var entities = bankAccountRepo.findByOptionalHolderLike(holder);
        final var resources = Mapper.mapList(entities, HsOfficeBankAccountResource.class);
        final var resources = mapper.mapList(entities, HsOfficeBankAccountResource.class);
        return ResponseEntity.ok(resources);
    }
@@ -54,7 +55,7 @@
        IbanUtil.validate(body.getIban());
        BicUtil.validate(body.getBic());
        final var entityToSave = map(body, HsOfficeBankAccountEntity.class);
        final var entityToSave = mapper.map(body, HsOfficeBankAccountEntity.class);
        entityToSave.setUuid(UUID.randomUUID());
        final var saved = bankAccountRepo.save(entityToSave);
@@ -64,7 +65,7 @@
                        .path("/api/hs/office/BankAccounts/{id}")
                        .buildAndExpand(entityToSave.getUuid())
                        .toUri();
        final var mapped = map(saved, HsOfficeBankAccountResource.class);
        final var mapped = mapper.map(saved, HsOfficeBankAccountResource.class);
        return ResponseEntity.created(uri).body(mapped);
    }
@@ -81,7 +82,7 @@
        if (result.isEmpty()) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(map(result.get(), HsOfficeBankAccountResource.class));
        return ResponseEntity.ok(mapper.map(result.get(), HsOfficeBankAccountResource.class));
    }
    @Override
src/main/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactController.java
@@ -15,14 +15,15 @@
import java.util.List;
import java.util.UUID;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
@RestController
public class HsOfficeContactController implements HsOfficeContactsApi {
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private HsOfficeContactRepository contactRepo;
@@ -37,7 +38,7 @@
        final var entities = contactRepo.findContactByOptionalLabelLike(label);
        final var resources = Mapper.mapList(entities, HsOfficeContactResource.class);
        final var resources = mapper.mapList(entities, HsOfficeContactResource.class);
        return ResponseEntity.ok(resources);
    }
@@ -50,7 +51,7 @@
        context.define(currentUser, assumedRoles);
        final var entityToSave = map(body, HsOfficeContactEntity.class);
        final var entityToSave = mapper.map(body, HsOfficeContactEntity.class);
        entityToSave.setUuid(UUID.randomUUID());
        final var saved = contactRepo.save(entityToSave);
@@ -60,7 +61,7 @@
                        .path("/api/hs/office/contacts/{id}")
                        .buildAndExpand(entityToSave.getUuid())
                        .toUri();
        final var mapped = map(saved, HsOfficeContactResource.class);
        final var mapped = mapper.map(saved, HsOfficeContactResource.class);
        return ResponseEntity.created(uri).body(mapped);
    }
@@ -77,7 +78,7 @@
        if (result.isEmpty()) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(map(result.get(), HsOfficeContactResource.class));
        return ResponseEntity.ok(mapper.map(result.get(), HsOfficeContactResource.class));
    }
    @Override
@@ -111,7 +112,7 @@
        new HsOfficeContactEntityPatch(current).apply(body);
        final var saved = contactRepo.save(current);
        final var mapped = map(saved, HsOfficeContactResource.class);
        final var mapped = mapper.map(saved, HsOfficeContactResource.class);
        return ResponseEntity.ok(mapped);
    }
}
src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionController.java
@@ -22,7 +22,6 @@
import static java.lang.String.join;
import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionTypeResource.*;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
@RestController
public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAssetsApi {
@@ -31,48 +30,51 @@
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private HsOfficeCoopAssetsTransactionRepository coopAssetsTransactionRepo;
    @Override
    @Transactional(readOnly = true)
    public ResponseEntity<List<HsOfficeCoopAssetsTransactionResource>> listCoopAssets(
        final String currentUser,
        final String assumedRoles,
        final UUID membershipUuid,
        final @DateTimeFormat(iso = ISO.DATE) LocalDate fromValueDate,
        final @DateTimeFormat(iso = ISO.DATE) LocalDate toValueDate) {
            final String currentUser,
            final String assumedRoles,
            final UUID membershipUuid,
            final @DateTimeFormat(iso = ISO.DATE) LocalDate fromValueDate,
            final @DateTimeFormat(iso = ISO.DATE) LocalDate toValueDate) {
        context.define(currentUser, assumedRoles);
        final var entities = coopAssetsTransactionRepo.findCoopAssetsTransactionByOptionalMembershipUuidAndDateRange(
            membershipUuid,
            fromValueDate,
            toValueDate);
                membershipUuid,
                fromValueDate,
                toValueDate);
        final var resources = Mapper.mapList(entities, HsOfficeCoopAssetsTransactionResource.class);
        final var resources = mapper.mapList(entities, HsOfficeCoopAssetsTransactionResource.class);
        return ResponseEntity.ok(resources);
    }
    @Override
    @Transactional
    public ResponseEntity<HsOfficeCoopAssetsTransactionResource> addCoopAssetsTransaction(
        final String currentUser,
        final String assumedRoles,
        @Valid final HsOfficeCoopAssetsTransactionInsertResource requestBody) {
            final String currentUser,
            final String assumedRoles,
            @Valid final HsOfficeCoopAssetsTransactionInsertResource requestBody) {
        context.define(currentUser, assumedRoles);
        validate(requestBody);
        final var entityToSave = map(requestBody, HsOfficeCoopAssetsTransactionEntity.class);
        final var entityToSave = mapper.map(requestBody, HsOfficeCoopAssetsTransactionEntity.class);
        entityToSave.setUuid(UUID.randomUUID());
        final var saved = coopAssetsTransactionRepo.save(entityToSave);
        final var uri =
            MvcUriComponentsBuilder.fromController(getClass())
                .path("/api/hs/office/coopassetstransactions/{id}")
                .buildAndExpand(entityToSave.getUuid())
                .toUri();
        final var mapped = map(saved, HsOfficeCoopAssetsTransactionResource.class);
                MvcUriComponentsBuilder.fromController(getClass())
                        .path("/api/hs/office/coopassetstransactions/{id}")
                        .buildAndExpand(entityToSave.getUuid())
                        .toUri();
        final var mapped = mapper.map(saved, HsOfficeCoopAssetsTransactionResource.class);
        return ResponseEntity.created(uri).body(mapped);
    }
@@ -87,31 +89,31 @@
    }
    private static void validateDebitTransaction(
        final HsOfficeCoopAssetsTransactionInsertResource requestBody,
        final ArrayList<String> violations) {
            final HsOfficeCoopAssetsTransactionInsertResource requestBody,
            final ArrayList<String> violations) {
        if (List.of(DEPOSIT, ADOPTION).contains(requestBody.getTransactionType())
            && requestBody.getAssetValue().signum() < 0) {
                && requestBody.getAssetValue().signum() < 0) {
            violations.add("for %s, assetValue must be positive but is \"%.2f\"".formatted(
                requestBody.getTransactionType(), requestBody.getAssetValue()));
                    requestBody.getTransactionType(), requestBody.getAssetValue()));
        }
    }
    private static void validateCreditTransaction(
        final HsOfficeCoopAssetsTransactionInsertResource requestBody,
        final ArrayList<String> violations) {
            final HsOfficeCoopAssetsTransactionInsertResource requestBody,
            final ArrayList<String> violations) {
        if (List.of(DISBURSAL, TRANSFER, CLEARING, LOSS).contains(requestBody.getTransactionType())
            && requestBody.getAssetValue().signum() > 0) {
                && requestBody.getAssetValue().signum() > 0) {
            violations.add("for %s, assetValue must be negative but is \"%.2f\"".formatted(
                requestBody.getTransactionType(), requestBody.getAssetValue()));
                    requestBody.getTransactionType(), requestBody.getAssetValue()));
        }
    }
    private static void validateAssetValue(
        final HsOfficeCoopAssetsTransactionInsertResource requestBody,
        final ArrayList<String> violations) {
            final HsOfficeCoopAssetsTransactionInsertResource requestBody,
            final ArrayList<String> violations) {
        if (requestBody.getAssetValue().signum() == 0) {
            violations.add("assetValue must not be 0 but is \"%.2f\"".formatted(
                requestBody.getAssetValue()));
                    requestBody.getAssetValue()));
        }
    }
src/main/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionController.java
@@ -21,7 +21,6 @@
import java.util.UUID;
import static java.lang.String.join;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopSharesTransactionTypeResource.CANCELLATION;
import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopSharesTransactionTypeResource.SUBSCRIPTION;
@@ -30,6 +29,9 @@
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private HsOfficeCoopSharesTransactionRepository coopSharesTransactionRepo;
@@ -49,7 +51,7 @@
                fromValueDate,
                toValueDate);
        final var resources = Mapper.mapList(entities, HsOfficeCoopSharesTransactionResource.class);
        final var resources = mapper.mapList(entities, HsOfficeCoopSharesTransactionResource.class);
        return ResponseEntity.ok(resources);
    }
@@ -63,7 +65,7 @@
        context.define(currentUser, assumedRoles);
        validate(requestBody);
        final var entityToSave = map(requestBody, HsOfficeCoopSharesTransactionEntity.class);
        final var entityToSave = mapper.map(requestBody, HsOfficeCoopSharesTransactionEntity.class);
        entityToSave.setUuid(UUID.randomUUID());
        final var saved = coopSharesTransactionRepo.save(entityToSave);
@@ -73,7 +75,7 @@
                        .path("/api/hs/office/coopsharestransactions/{id}")
                        .buildAndExpand(entityToSave.getUuid())
                        .toUri();
        final var mapped = map(saved, HsOfficeCoopSharesTransactionResource.class);
        final var mapped = mapper.map(saved, HsOfficeCoopSharesTransactionResource.class);
        return ResponseEntity.created(uri).body(mapped);
    }
src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorController.java
@@ -1,12 +1,11 @@
package net.hostsharing.hsadminng.hs.office.debitor;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeDebitorsApi;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.*;
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorInsertResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorPatchResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebitorResource;
import net.hostsharing.hsadminng.mapper.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
@@ -16,9 +15,6 @@
import javax.persistence.EntityManager;
import java.util.List;
import java.util.UUID;
import java.util.function.BiConsumer;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
@RestController
@@ -26,6 +22,9 @@
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private HsOfficeDebitorRepository debitorRepo;
@@ -46,8 +45,7 @@
                ? debitorRepo.findDebitorByDebitorNumber(debitorNumber)
                : debitorRepo.findDebitorByOptionalNameLike(name);
        final var resources = Mapper.mapList(entities, HsOfficeDebitorResource.class,
                DEBITOR_ENTITY_TO_RESOURCE_POSTMAPPER);
        final var resources = mapper.mapList(entities, HsOfficeDebitorResource.class);
        return ResponseEntity.ok(resources);
    }
@@ -60,7 +58,7 @@
        context.define(currentUser, assumedRoles);
        final var entityToSave = map(body, HsOfficeDebitorEntity.class, DEBITOR_RESOURCE_TO_ENTITY_POSTMAPPER);
        final var entityToSave = mapper.map(body, HsOfficeDebitorEntity.class);
        entityToSave.setUuid(UUID.randomUUID());
        final var saved = debitorRepo.save(entityToSave);
@@ -70,8 +68,7 @@
                        .path("/api/hs/office/debitors/{id}")
                        .buildAndExpand(entityToSave.getUuid())
                        .toUri();
        final var mapped = map(saved, HsOfficeDebitorResource.class,
                DEBITOR_ENTITY_TO_RESOURCE_POSTMAPPER);
        final var mapped = mapper.map(saved, HsOfficeDebitorResource.class);
        return ResponseEntity.created(uri).body(mapped);
    }
@@ -88,7 +85,7 @@
        if (result.isEmpty()) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(map(result.get(), HsOfficeDebitorResource.class, DEBITOR_ENTITY_TO_RESOURCE_POSTMAPPER));
        return ResponseEntity.ok(mapper.map(result.get(), HsOfficeDebitorResource.class));
    }
    @Override
@@ -122,24 +119,7 @@
        new HsOfficeDebitorEntityPatcher(em, current).apply(body);
        final var saved = debitorRepo.save(current);
        final var mapped = map(saved, HsOfficeDebitorResource.class);
        final var mapped = mapper.map(saved, HsOfficeDebitorResource.class);
        return ResponseEntity.ok(mapped);
    }
    final BiConsumer<HsOfficeDebitorEntity, HsOfficeDebitorResource> DEBITOR_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
        resource.setPartner(map(entity.getPartner(), HsOfficePartnerResource.class));
        resource.setBillingContact(map(entity.getBillingContact(), HsOfficeContactResource.class));
        if ( entity.getRefundBankAccount() != null ) {
            resource.setRefundBankAccount(map(entity.getRefundBankAccount(), HsOfficeBankAccountResource.class));
        }
    };
    final BiConsumer<HsOfficeDebitorInsertResource, HsOfficeDebitorEntity> DEBITOR_RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
        entity.setPartner(em.getReference(HsOfficePartnerEntity.class, resource.getPartnerUuid()));
        entity.setBillingContact(em.getReference(HsOfficeContactEntity.class, resource.getBillingContactUuid()));
        if ( resource.getRefundBankAccountUuid() != null ) {
            entity.setRefundBankAccount(em.getReference(HsOfficeBankAccountEntity.class, resource.getRefundBankAccountUuid()));
        }
    };
}
src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipController.java
@@ -5,6 +5,7 @@
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipInsertResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipPatchResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipResource;
import net.hostsharing.hsadminng.mapper.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
@@ -17,15 +18,15 @@
import java.util.UUID;
import java.util.function.BiConsumer;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
import static net.hostsharing.hsadminng.mapper.Mapper.mapList;
@RestController
public class HsOfficeMembershipController implements HsOfficeMembershipsApi {
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private HsOfficeMembershipRepository membershipRepo;
@@ -45,7 +46,7 @@
        final var entities =
                membershipRepo.findMembershipsByOptionalPartnerUuidAndOptionalMemberNumber(partnerUuid, memberNumber);
        final var resources = mapList(entities, HsOfficeMembershipResource.class,
        final var resources = mapper.mapList(entities, HsOfficeMembershipResource.class,
                SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER);
        return ResponseEntity.ok(resources);
    }
@@ -59,7 +60,7 @@
        context.define(currentUser, assumedRoles);
        final var entityToSave = map(body, HsOfficeMembershipEntity.class);
        final var entityToSave = mapper.map(body, HsOfficeMembershipEntity.class);
        entityToSave.setUuid(UUID.randomUUID());
        final var saved = membershipRepo.save(entityToSave);
@@ -69,7 +70,7 @@
                        .path("/api/hs/office/Memberships/{id}")
                        .buildAndExpand(entityToSave.getUuid())
                        .toUri();
        final var mapped = map(saved, HsOfficeMembershipResource.class,
        final var mapped = mapper.map(saved, HsOfficeMembershipResource.class,
                SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER);
        return ResponseEntity.created(uri).body(mapped);
    }
@@ -87,7 +88,7 @@
        if (result.isEmpty()) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(map(result.get(), HsOfficeMembershipResource.class,
        return ResponseEntity.ok(mapper.map(result.get(), HsOfficeMembershipResource.class,
                SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER));
    }
@@ -119,14 +120,15 @@
        final var current = membershipRepo.findByUuid(membershipUuid).orElseThrow();
        new HsOfficeMembershipEntityPatcher(em, current).apply(body);
        new HsOfficeMembershipEntityPatcher(em, mapper, current).apply(body);
        final var saved = membershipRepo.save(current);
        final var mapped = map(saved, HsOfficeMembershipResource.class, SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER);
        final var mapped = mapper.map(saved, HsOfficeMembershipResource.class, SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER);
        return ResponseEntity.ok(mapped);
    }
    final BiConsumer<HsOfficeMembershipEntity, HsOfficeMembershipResource> SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
        // TODO.refa: this should be possible via ModelMapper config
        resource.setValidFrom(entity.getValidity().lower());
        if (entity.getValidity().hasUpperBound()) {
            resource.setValidTo(entity.getValidity().upper().minusDays(1));
src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcher.java
@@ -3,23 +3,25 @@
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipPatchResource;
import net.hostsharing.hsadminng.mapper.EntityPatcher;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
import javax.persistence.EntityManager;
import java.util.Optional;
import java.util.UUID;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
public class HsOfficeMembershipEntityPatcher implements EntityPatcher<HsOfficeMembershipPatchResource> {
    private final EntityManager em;
    private final Mapper mapper;
    private final HsOfficeMembershipEntity entity;
    public HsOfficeMembershipEntityPatcher(
            final EntityManager em,
            final Mapper mapper,
            final HsOfficeMembershipEntity entity) {
        this.em = em;
        this.mapper = mapper;
        this.entity = entity;
    }
@@ -33,7 +35,7 @@
        OptionalFromJson.of(resource.getValidTo()).ifPresent(
                entity::setValidTo);
        Optional.ofNullable(resource.getReasonForTermination())
                .map(v -> map(v, HsOfficeReasonForTermination.class))
                .map(v -> mapper.map(v, HsOfficeReasonForTermination.class))
                .ifPresent(entity::setReasonForTermination);
    }
src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java
@@ -1,11 +1,11 @@
package net.hostsharing.hsadminng.hs.office.partner;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficePartnersApi;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.*;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerInsertResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerResource;
import net.hostsharing.hsadminng.mapper.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
@@ -14,11 +14,7 @@
import javax.persistence.EntityManager;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.UUID;
import java.util.function.BiConsumer;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
@RestController
@@ -28,13 +24,10 @@
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private HsOfficePartnerRepository partnerRepo;
    @Autowired
    private HsOfficePersonRepository personRepo;
    @Autowired
    private HsOfficeContactRepository contactRepo;
    @Autowired
    private EntityManager em;
@@ -49,8 +42,7 @@
        final var entities = partnerRepo.findPartnerByOptionalNameLike(name);
        final var resources = Mapper.mapList(entities, HsOfficePartnerResource.class,
                PARTNER_ENTITY_TO_RESOURCE_POSTMAPPER);
        final var resources = mapper.mapList(entities, HsOfficePartnerResource.class);
        return ResponseEntity.ok(resources);
    }
@@ -63,16 +55,9 @@
        context.define(currentUser, assumedRoles);
        final var entityToSave = mapToHsOfficePartnerEntity(body);
        final var entityToSave = mapper.map(body, HsOfficePartnerEntity.class);
        entityToSave.setUuid(UUID.randomUUID());
        // TODO.impl: use getReference
        entityToSave.setContact(contactRepo.findByUuid(body.getContactUuid()).orElseThrow(
                () -> new NoSuchElementException("cannot find contact uuid " + body.getContactUuid())
        ));
        entityToSave.setPerson(personRepo.findByUuid(body.getPersonUuid()).orElseThrow(
                () -> new NoSuchElementException("cannot find person uuid " + body.getPersonUuid())
        ));
        entityToSave.setDetails(map(body.getDetails(), HsOfficePartnerDetailsEntity.class));
        entityToSave.setDetails(mapper.map(body.getDetails(), HsOfficePartnerDetailsEntity.class));
        entityToSave.getDetails().setUuid(UUID.randomUUID());
        final var saved = partnerRepo.save(entityToSave);
@@ -82,8 +67,7 @@
                        .path("/api/hs/office/partners/{id}")
                        .buildAndExpand(entityToSave.getUuid())
                        .toUri();
        final var mapped = map(saved, HsOfficePartnerResource.class,
                PARTNER_ENTITY_TO_RESOURCE_POSTMAPPER);
        final var mapped = mapper.map(saved, HsOfficePartnerResource.class);
        return ResponseEntity.created(uri).body(mapped);
    }
@@ -100,7 +84,7 @@
        if (result.isEmpty()) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(map(result.get(), HsOfficePartnerResource.class, PARTNER_ENTITY_TO_RESOURCE_POSTMAPPER));
        return ResponseEntity.ok(mapper.map(result.get(), HsOfficePartnerResource.class));
    }
    @Override
@@ -134,23 +118,7 @@
        new HsOfficePartnerEntityPatcher(em, current).apply(body);
        final var saved = partnerRepo.save(current);
        final var mapped = map(saved, HsOfficePartnerResource.class);
        final var mapped = mapper.map(saved, HsOfficePartnerResource.class);
        return ResponseEntity.ok(mapped);
    }
    final BiConsumer<HsOfficePartnerEntity, HsOfficePartnerResource> PARTNER_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
        resource.setPerson(map(entity.getPerson(), HsOfficePersonResource.class));
        resource.setContact(map(entity.getContact(), HsOfficeContactResource.class));
    };
    // TODO.impl: user postmapper + getReference
    private HsOfficePartnerEntity mapToHsOfficePartnerEntity(final HsOfficePartnerInsertResource resource) {
        final var entity = new HsOfficePartnerEntity();
        //        entity.setBirthday(resource.getBirthday());
        //        entity.setBirthName(resource.getBirthName());
        //        entity.setDateOfDeath(resource.getDateOfDeath());
        //        entity.setRegistrationNumber(resource.getRegistrationNumber());
        //        entity.setRegistrationOffice(resource.getRegistrationOffice());
        return entity;
    }
}
src/main/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonController.java
@@ -15,14 +15,15 @@
import java.util.List;
import java.util.UUID;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
@RestController
public class HsOfficePersonController implements HsOfficePersonsApi {
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private HsOfficePersonRepository personRepo;
@@ -37,7 +38,7 @@
        final var entities = personRepo.findPersonByOptionalNameLike(label);
        final var resources = Mapper.mapList(entities, HsOfficePersonResource.class);
        final var resources = mapper.mapList(entities, HsOfficePersonResource.class);
        return ResponseEntity.ok(resources);
    }
@@ -50,7 +51,7 @@
        context.define(currentUser, assumedRoles);
        final var entityToSave = map(body, HsOfficePersonEntity.class);
        final var entityToSave = mapper.map(body, HsOfficePersonEntity.class);
        entityToSave.setUuid(UUID.randomUUID());
        final var saved = personRepo.save(entityToSave);
@@ -60,7 +61,7 @@
                        .path("/api/hs/office/persons/{id}")
                        .buildAndExpand(entityToSave.getUuid())
                        .toUri();
        final var mapped = map(saved, HsOfficePersonResource.class);
        final var mapped = mapper.map(saved, HsOfficePersonResource.class);
        return ResponseEntity.created(uri).body(mapped);
    }
@@ -77,7 +78,7 @@
        if (result.isEmpty()) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(map(result.get(), HsOfficePersonResource.class));
        return ResponseEntity.ok(mapper.map(result.get(), HsOfficePersonResource.class));
    }
    @Override
@@ -111,7 +112,7 @@
        new HsOfficePersonEntityPatcher(current).apply(body);
        final var saved = personRepo.save(current);
        final var mapped = map(saved, HsOfficePersonResource.class);
        final var mapped = mapper.map(saved, HsOfficePersonResource.class);
        return ResponseEntity.ok(mapped);
    }
}
src/main/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipController.java
@@ -5,6 +5,7 @@
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeRelationshipsApi;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.*;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
import net.hostsharing.hsadminng.mapper.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
@@ -17,8 +18,6 @@
import java.util.UUID;
import java.util.function.BiConsumer;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
import static net.hostsharing.hsadminng.mapper.Mapper.mapList;
@RestController
@@ -26,6 +25,9 @@
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private HsOfficeRelationshipRepository relationshipRepo;
@@ -49,9 +51,9 @@
        context.define(currentUser, assumedRoles);
        final var entities = relationshipRepo.findRelationshipRelatedToPersonUuid(personUuid,
                map(relationshipType, HsOfficeRelationshipType.class));
                mapper.map(relationshipType, HsOfficeRelationshipType.class));
        final var resources = mapList(entities, HsOfficeRelationshipResource.class,
        final var resources = mapper.mapList(entities, HsOfficeRelationshipResource.class,
                RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER);
        return ResponseEntity.ok(resources);
    }
@@ -85,7 +87,7 @@
                        .path("/api/hs/office/relationships/{id}")
                        .buildAndExpand(entityToSave.getUuid())
                        .toUri();
        final var mapped = map(saved, HsOfficeRelationshipResource.class,
        final var mapped = mapper.map(saved, HsOfficeRelationshipResource.class,
                RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER);
        return ResponseEntity.created(uri).body(mapped);
    }
@@ -103,7 +105,7 @@
        if (result.isEmpty()) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(map(result.get(), HsOfficeRelationshipResource.class, RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER));
        return ResponseEntity.ok(mapper.map(result.get(), HsOfficeRelationshipResource.class, RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER));
    }
    @Override
@@ -137,14 +139,14 @@
        new HsOfficeRelationshipEntityPatcher(em, current).apply(body);
        final var saved = relationshipRepo.save(current);
        final var mapped = map(saved, HsOfficeRelationshipResource.class);
        final var mapped = mapper.map(saved, HsOfficeRelationshipResource.class);
        return ResponseEntity.ok(mapped);
    }
    final BiConsumer<HsOfficeRelationshipEntity, HsOfficeRelationshipResource> RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
        resource.setRelAnchor(map(entity.getRelAnchor(), HsOfficePersonResource.class));
        resource.setRelHolder(map(entity.getRelHolder(), HsOfficePersonResource.class));
        resource.setContact(map(entity.getContact(), HsOfficeContactResource.class));
        resource.setRelAnchor(mapper.map(entity.getRelAnchor(), HsOfficePersonResource.class));
        resource.setRelHolder(mapper.map(entity.getRelHolder(), HsOfficePersonResource.class));
        resource.setContact(mapper.map(entity.getContact(), HsOfficeContactResource.class));
    };
}
src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java
@@ -15,12 +15,10 @@
import javax.persistence.EntityManager;
import javax.validation.Valid;
import java.time.LocalDate;
import java.util.List;
import java.util.UUID;
import java.util.function.BiConsumer;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
@RestController
@@ -29,6 +27,9 @@
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private HsOfficeSepaMandateRepository SepaMandateRepo;
@@ -46,7 +47,7 @@
        final var entities = SepaMandateRepo.findSepaMandateByOptionalIban(iban);
        final var resources = Mapper.mapList(entities, HsOfficeSepaMandateResource.class,
        final var resources = mapper.mapList(entities, HsOfficeSepaMandateResource.class,
                SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER);
        return ResponseEntity.ok(resources);
    }
@@ -60,7 +61,7 @@
        context.define(currentUser, assumedRoles);
        final var entityToSave = map(body, HsOfficeSepaMandateEntity.class, SEPA_MANDATE_RESOURCE_TO_ENTITY_POSTMAPPER);
        final var entityToSave = mapper.map(body, HsOfficeSepaMandateEntity.class, SEPA_MANDATE_RESOURCE_TO_ENTITY_POSTMAPPER);
        entityToSave.setUuid(UUID.randomUUID());
        final var saved = SepaMandateRepo.save(entityToSave);
@@ -70,7 +71,7 @@
                        .path("/api/hs/office/SepaMandates/{id}")
                        .buildAndExpand(entityToSave.getUuid())
                        .toUri();
        final var mapped = map(saved, HsOfficeSepaMandateResource.class,
        final var mapped = mapper.map(saved, HsOfficeSepaMandateResource.class,
                SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER);
        return ResponseEntity.created(uri).body(mapped);
    }
@@ -88,7 +89,7 @@
        if (result.isEmpty()) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(map(result.get(), HsOfficeSepaMandateResource.class,
        return ResponseEntity.ok(mapper.map(result.get(), HsOfficeSepaMandateResource.class,
                SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER));
    }
@@ -123,7 +124,7 @@
        current.setValidity(toPostgresDateRange(current.getValidity().lower(), body.getValidTo()));
        final var saved = SepaMandateRepo.save(current);
        final var mapped = map(saved, HsOfficeSepaMandateResource.class, SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER);
        final var mapped = mapper.map(saved, HsOfficeSepaMandateResource.class, SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER);
        return ResponseEntity.ok(mapped);
    }
src/main/java/net/hostsharing/hsadminng/mapper/Mapper.java
@@ -9,15 +9,17 @@
/**
 * A nicer API for ModelMapper.
 */
public abstract class Mapper {
public class Mapper extends ModelMapper {
    public final static ModelMapper modelMapper = new ModelMapper();
    public Mapper() {
        getConfiguration().setAmbiguityIgnored(true);
    }
    public static <S, T> List<T> mapList(final List<S> source, final Class<T> targetClass) {
    public <S, T> List<T> mapList(final List<S> source, final Class<T> targetClass) {
        return mapList(source, targetClass, null);
    }
    public static <S, T> List<T> mapList(final List<S> source, final Class<T> targetClass, final BiConsumer<S, T> postMapper) {
    public <S, T> List<T> mapList(final List<S> source, final Class<T> targetClass, final BiConsumer<S, T> postMapper) {
        return source
                .stream()
                .map(element -> {
@@ -30,18 +32,12 @@
                .collect(Collectors.toList());
    }
    public static <S, T> T map(final S source, final Class<T> targetClass) {
        return map(source, targetClass, null);
    }
    public static <S, T> T map(final S source, final Class<T> targetClass, final BiConsumer<S, T> postMapper) {
    public <S, T> T map(final S source, final Class<T> targetClass, final BiConsumer<S, T> postMapper) {
        if (source == null) {
            return null;
        }
        final var target = modelMapper.map(source, targetClass);
        if (postMapper != null) {
            postMapper.accept(source, target);
        }
        final var target = map(source, targetClass);
        postMapper.accept(source, target);
        return target;
    }
}
src/main/java/net/hostsharing/hsadminng/mapper/MapperConfiguration.java
New file
@@ -0,0 +1,13 @@
package net.hostsharing.hsadminng.mapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MapperConfiguration {
    @Bean
    public Mapper modelMapper() {
        return new Mapper();
    }
}
src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantController.java
@@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.rbac.rbacgrant;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.rbac.generated.api.v1.api.RbacGrantsApi;
import net.hostsharing.hsadminng.rbac.generated.api.v1.model.RbacGrantResource;
import org.springframework.beans.factory.annotation.Autowired;
@@ -13,15 +14,14 @@
import java.util.List;
import java.util.UUID;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
import static net.hostsharing.hsadminng.mapper.Mapper.mapList;
@RestController
public class RbacGrantController implements RbacGrantsApi {
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private RbacGrantRepository rbacGrantRepository;
@@ -44,7 +44,7 @@
        if (result == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(map(result, RbacGrantResource.class));
        return ResponseEntity.ok(mapper.map(result, RbacGrantResource.class));
    }
    @Override
@@ -55,7 +55,7 @@
        context.define(currentUser, assumedRoles);
        return ResponseEntity.ok(mapList(rbacGrantRepository.findAll(), RbacGrantResource.class));
        return ResponseEntity.ok(mapper.mapList(rbacGrantRepository.findAll(), RbacGrantResource.class));
    }
    @Override
@@ -67,7 +67,7 @@
        context.define(currentUser, assumedRoles);
        final var granted = rbacGrantRepository.save(map(body, RbacGrantEntity.class));
        final var granted = rbacGrantRepository.save(mapper.map(body, RbacGrantEntity.class));
        em.flush();
        em.refresh(granted);
@@ -76,7 +76,7 @@
                        .path("/api/rbac.yaml/grants/{roleUuid}")
                        .buildAndExpand(body.getGrantedRoleUuid())
                        .toUri();
        return ResponseEntity.created(uri).body(map(granted, RbacGrantResource.class));
        return ResponseEntity.created(uri).body(mapper.map(granted, RbacGrantResource.class));
    }
    @Override
src/main/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleController.java
@@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.rbac.rbacrole;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.rbac.generated.api.v1.api.RbacRolesApi;
import net.hostsharing.hsadminng.rbac.generated.api.v1.model.RbacRoleResource;
import org.springframework.beans.factory.annotation.Autowired;
@@ -10,14 +11,14 @@
import java.util.List;
import static net.hostsharing.hsadminng.mapper.Mapper.mapList;
@RestController
public class RbacRoleController implements RbacRolesApi {
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private RbacRoleRepository rbacRoleRepository;
@@ -30,7 +31,9 @@
        context.define(currentUser, assumedRoles);
        return ResponseEntity.ok(mapList(rbacRoleRepository.findAll(), RbacRoleResource.class));
        final List<RbacRoleEntity> result = rbacRoleRepository.findAll();
        return ResponseEntity.ok(mapper.mapList(result, RbacRoleResource.class));
    }
}
src/main/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserController.java
@@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.rbac.rbacuser;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.rbac.generated.api.v1.api.RbacUsersApi;
import net.hostsharing.hsadminng.rbac.generated.api.v1.model.RbacUserPermissionResource;
import net.hostsharing.hsadminng.rbac.generated.api.v1.model.RbacUserResource;
@@ -13,14 +14,14 @@
import java.util.List;
import java.util.UUID;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
import static net.hostsharing.hsadminng.mapper.Mapper.mapList;
@RestController
public class RbacUserController implements RbacUsersApi {
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private RbacUserRepository rbacUserRepository;
@@ -35,14 +36,14 @@
        if (body.getUuid() == null) {
            body.setUuid(UUID.randomUUID());
        }
        final var saved = map(body, RbacUserEntity.class);
        final var saved = mapper.map(body, RbacUserEntity.class);
        rbacUserRepository.create(saved);
        final var uri =
                MvcUriComponentsBuilder.fromController(getClass())
                        .path("/api/rbac.yaml/users/{id}")
                        .buildAndExpand(saved.getUuid())
                        .toUri();
        return ResponseEntity.created(uri).body(map(saved, RbacUserResource.class));
        return ResponseEntity.created(uri).body(mapper.map(saved, RbacUserResource.class));
    }
    @Override
@@ -72,7 +73,7 @@
        if (result == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(map(result, RbacUserResource.class));
        return ResponseEntity.ok(mapper.map(result, RbacUserResource.class));
    }
    @Override
@@ -84,7 +85,7 @@
    ) {
        context.define(currentUser, assumedRoles);
        return ResponseEntity.ok(mapList(rbacUserRepository.findByOptionalNameLike(userName), RbacUserResource.class));
        return ResponseEntity.ok(mapper.mapList(rbacUserRepository.findByOptionalNameLike(userName), RbacUserResource.class));
    }
    @Override
@@ -96,7 +97,7 @@
    ) {
        context.define(currentUser, assumedRoles);
        return ResponseEntity.ok(mapList(
        return ResponseEntity.ok(mapper.mapList(
                rbacUserRepository.findPermissionsOfUserByUuid(userUuid),
                RbacUserPermissionResource.class));
    }
src/main/java/net/hostsharing/hsadminng/test/cust/TestCustomerController.java
@@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.test.cust;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.test.generated.api.v1.api.TestCustomersApi;
import net.hostsharing.hsadminng.test.generated.api.v1.model.TestCustomerResource;
import org.springframework.beans.factory.annotation.Autowired;
@@ -12,15 +13,14 @@
import java.util.List;
import java.util.UUID;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
import static net.hostsharing.hsadminng.mapper.Mapper.mapList;
@RestController
public class TestCustomerController implements TestCustomersApi {
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private TestCustomerRepository testCustomerRepository;
@@ -36,7 +36,7 @@
        final var result = testCustomerRepository.findCustomerByOptionalPrefixLike(prefix);
        return ResponseEntity.ok(mapList(result, TestCustomerResource.class));
        return ResponseEntity.ok(mapper.mapList(result, TestCustomerResource.class));
    }
    @Override
@@ -52,14 +52,14 @@
            customer.setUuid(UUID.randomUUID());
        }
        final var saved = testCustomerRepository.save(map(customer, TestCustomerEntity.class));
        final var saved = testCustomerRepository.save(mapper.map(customer, TestCustomerEntity.class));
        final var uri =
                MvcUriComponentsBuilder.fromController(getClass())
                        .path("/api/test/customers/{id}")
                        .buildAndExpand(customer.getUuid())
                        .toUri();
        return ResponseEntity.created(uri).body(map(saved, TestCustomerResource.class));
        return ResponseEntity.created(uri).body(mapper.map(saved, TestCustomerResource.class));
    }
}
src/main/java/net/hostsharing/hsadminng/test/pac/TestPackageController.java
@@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.test.pac;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.test.generated.api.v1.api.TestPackagesApi;
@@ -13,14 +14,14 @@
import java.util.List;
import java.util.UUID;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
import static net.hostsharing.hsadminng.mapper.Mapper.mapList;
@RestController
public class TestPackageController implements TestPackagesApi {
    @Autowired
    private Context context;
    @Autowired
    private Mapper mapper;
    @Autowired
    private TestPackageRepository testPackageRepository;
@@ -35,7 +36,7 @@
        context.define(currentUser, assumedRoles);
        final var result = testPackageRepository.findAllByOptionalNameLike(name);
        return ResponseEntity.ok(mapList(result, TestPackageResource.class));
        return ResponseEntity.ok(mapper.mapList(result, TestPackageResource.class));
    }
    @Override
@@ -51,7 +52,7 @@
        final var current = testPackageRepository.findByUuid(packageUuid);
        OptionalFromJson.of(body.getDescription()).ifPresent(current::setDescription);
        final var saved = testPackageRepository.save(current);
        final var mapped = map(saved, TestPackageResource.class);
        final var mapped = mapper.map(saved, TestPackageResource.class);
        return ResponseEntity.ok(mapped);
    }
}
src/main/resources/api-definition/hs-office/hs-office-partner-schemas.yaml
@@ -18,6 +18,7 @@
        HsOfficePartnerDetails:
            type: object
            nullable: false
            properties:
                uuid:
                    type: string
@@ -56,7 +57,7 @@
        HsOfficePartnerDetailsPatch:
            type: object
            nullable: true
            nullable: false
            properties:
                registrationOffice:
                    type: string
@@ -90,9 +91,11 @@
            required:
                - personUuid
                - contactUuid
                - details
        HsOfficePartnerDetailsInsert:
            type: object
            nullable: false
            properties:
                registrationOffice:
                    type: string
src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountControllerAcceptanceTest.java
@@ -2,6 +2,7 @@
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.test.Accepts;
import net.hostsharing.hsadminng.HsadminNgApplication;
import net.hostsharing.hsadminng.context.Context;
@@ -35,9 +36,6 @@
    @Autowired
    Context context;
    @Autowired
    Context contextMock;
    @Autowired
    HsOfficeBankAccountRepository bankAccountRepo;
src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountControllerRestTest.java
@@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.hs.office.bankaccount;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.springframework.beans.factory.annotation.Autowired;
@@ -24,6 +25,9 @@
    Context contextMock;
    @MockBean
    Mapper mapper;
    @MockBean
    HsOfficeBankAccountRepository bankAccountRepo;
    enum InvalidIbanTestCase {
src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java
@@ -6,16 +6,19 @@
import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository;
import net.hostsharing.test.Array;
import net.hostsharing.test.JpaAttempt;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.modelmapper.internal.bytebuddy.utility.RandomString;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.junit.jupiter.Container;
import javax.persistence.EntityManager;
@@ -31,8 +34,7 @@
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { HsOfficeBankAccountRepository.class, Context.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class HsOfficeBankAccountRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
@@ -311,7 +313,7 @@
    }
    private HsOfficeBankAccountEntity givenSomeTemporaryBankAccount(final String createdByUser) {
        final var random = RandomString.make(3);
        final var random = RandomStringUtils.randomAlphabetic(3);
        return givenSomeTemporaryBankAccount(createdByUser, () ->
                hsOfficeBankAccount(
                        "some temp acc #" + random,
src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRepositoryIntegrationTest.java
@@ -6,15 +6,16 @@
import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository;
import net.hostsharing.test.Array;
import net.hostsharing.test.JpaAttempt;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.modelmapper.internal.bytebuddy.utility.RandomString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import org.testcontainers.junit.jupiter.Container;
@@ -32,8 +33,7 @@
import static org.assertj.core.api.Assumptions.assumeThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { HsOfficeContactRepository.class, Context.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class HsOfficeContactRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
@@ -305,7 +305,7 @@
    }
    private HsOfficeContactEntity givenSomeTemporaryContact(final String createdByUser) {
        final var random = RandomString.make(12);
        final var random = RandomStringUtils.randomAlphabetic(12);
        return givenSomeTemporaryContact(createdByUser, () ->
                hsOfficeContact(
                        "some temporary contact #" + random,
src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionControllerRestTest.java
@@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.hs.office.coopassets;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.test.JsonBuilder;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
@@ -29,6 +30,9 @@
    Context contextMock;
    @MockBean
    Mapper mapper;
    @MockBean
    HsOfficeCoopAssetsTransactionRepository coopAssetsTransactionRepo;
    static final String VALID_INSERT_REQUEST_BODY = """
src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java
@@ -15,6 +15,7 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.transaction.annotation.Transactional;
@@ -32,8 +33,7 @@
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { HsOfficeCoopAssetsTransactionRepository.class, Context.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionControllerRestTest.java
@@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.hs.office.coopshares;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.test.JsonBuilder;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
@@ -29,6 +30,9 @@
    Context contextMock;
    @MockBean
    Mapper mapper;
    @MockBean
    HsOfficeCoopSharesTransactionRepository coopSharesTransactionRepo;
    static final String VALID_INSERT_REQUEST_BODY = """
src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java
@@ -15,6 +15,7 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import javax.persistence.EntityManager;
@@ -30,8 +31,7 @@
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { HsOfficeCoopSharesTransactionRepository.class, Context.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorControllerAcceptanceTest.java
@@ -44,9 +44,6 @@
    Context context;
    @Autowired
    Context contextMock;
    @Autowired
    HsOfficeDebitorRepository debitorRepo;
    @Autowired
src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java
@@ -19,6 +19,7 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.test.annotation.DirtiesContext;
@@ -32,8 +33,7 @@
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { HsOfficeDebitorRepository.class, Context.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerRestTest.java
@@ -2,12 +2,17 @@
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.coopassets.HsOfficeCoopAssetsTransactionRepository;
import net.hostsharing.hsadminng.mapper.Mapper;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.orm.jpa.JpaObjectRetrievalFailureException;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@@ -22,6 +27,8 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(HsOfficeMembershipController.class)
@Import(Mapper.class)
@RunWith(SpringRunner.class)
public class HsOfficeMembershipControllerRestTest {
    @Autowired
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcherUnitTest.java
@@ -4,12 +4,14 @@
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipPatchResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeReasonForTerminationResource;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.test.PatchUnitTestBase;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import javax.persistence.EntityManager;
import java.time.LocalDate;
@@ -31,13 +33,14 @@
        > {
    private static final UUID INITIAL_MEMBERSHIP_UUID = UUID.randomUUID();
    private static final UUID INITIAL_MAIN_DEBITOR_UUID = UUID.randomUUID();
    private static final UUID PATCHED_MAIN_DEBITOR_UUID = UUID.randomUUID();
    private static final LocalDate GIVEN_VALID_FROM = LocalDate.parse("2020-04-15");
    private static final LocalDate PATCHED_VALID_TO = LocalDate.parse("2022-12-31");
    @Mock
    private EntityManager em;
    private Mapper mapper = new Mapper();
    @BeforeEach
    void initMocks() {
@@ -63,8 +66,8 @@
    }
    @Override
    protected HsOfficeMembershipEntityPatcher createPatcher(final HsOfficeMembershipEntity Membership) {
        return new HsOfficeMembershipEntityPatcher(em, Membership);
    protected HsOfficeMembershipEntityPatcher createPatcher(final HsOfficeMembershipEntity membership) {
        return new HsOfficeMembershipEntityPatcher(em, mapper, membership);
    }
    @Override
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java
@@ -17,6 +17,7 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.test.annotation.DirtiesContext;
@@ -32,8 +33,7 @@
import static org.assertj.core.api.Assumptions.assumeThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { HsOfficeMembershipRepository.class, Context.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java
@@ -2,11 +2,11 @@
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import net.hostsharing.test.Accepts;
import net.hostsharing.hsadminng.HsadminNgApplication;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
import net.hostsharing.test.Accepts;
import net.hostsharing.test.JpaAttempt;
import org.json.JSONException;
import org.junit.jupiter.api.AfterEach;
@@ -166,15 +166,16 @@
                    .body("""
                               {
                                   "contactUuid": "%s",
                                   "personUuid": "%s"
                                   "personUuid": "%s",
                                   "details": {}
                                 }
                            """.formatted(givenContactUuid, givenPerson.getUuid()))
                    .port(port)
                .when()
                    .post("http://localhost/api/hs/office/partners")
                .then().log().all().assertThat()
                    .statusCode(404)
                    .body("message", is("cannot find contact uuid 3fa85f64-5717-4562-b3fc-2c963f66afa6"));
                    .statusCode(400)
                    .body("message", is("Unable to find Contact with uuid 3fa85f64-5717-4562-b3fc-2c963f66afa6"));
            // @formatter:on
        }
@@ -193,19 +194,15 @@
                               {
                                   "contactUuid": "%s",
                                   "personUuid": "%s",
                                   "registrationOffice": "Registergericht Hamburg",
                                   "registrationNumber": "123456",
                                   "birthName": null,
                                   "birthday": null,
                                   "dateOfDeath": null
                                   "details": {}
                                 }
                            """.formatted(givenContact.getUuid(), givenPersonUuid))
                    .port(port)
                .when()
                    .post("http://localhost/api/hs/office/partners")
                .then().log().all().assertThat()
                    .statusCode(404)
                    .body("message", is("cannot find person uuid 3fa85f64-5717-4562-b3fc-2c963f66afa6"));
                    .statusCode(400)
                    .body("message", is("Unable to find Person with uuid 3fa85f64-5717-4562-b3fc-2c963f66afa6"));
                // @formatter:on
        }
    }
src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java
@@ -15,6 +15,7 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.test.annotation.DirtiesContext;
@@ -29,8 +30,7 @@
import static org.assertj.core.api.Assumptions.assumeThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { HsOfficePartnerRepository.class, Context.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRepositoryIntegrationTest.java
@@ -6,14 +6,15 @@
import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository;
import net.hostsharing.test.Array;
import net.hostsharing.test.JpaAttempt;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.modelmapper.internal.bytebuddy.utility.RandomString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import javax.persistence.EntityManager;
@@ -30,8 +31,7 @@
import static org.assertj.core.api.Assumptions.assumeThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { HsOfficePersonRepository.class, Context.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
@@ -304,7 +304,7 @@
    private HsOfficePersonEntity givenSomeTemporaryPerson(final String createdByUser) {
        return givenSomeTemporaryPerson(createdByUser, () ->
                hsOfficePerson("some temporary person #" + RandomString.make(12)));
                hsOfficePerson("some temporary person #" + RandomStringUtils.random(12)));
    }
    void exactlyThesePersonsAreReturned(final List<HsOfficePersonEntity> actualResult, final String... personLabels) {
src/test/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipRepositoryIntegrationTest.java
@@ -1,5 +1,6 @@
package net.hostsharing.hsadminng.hs.office.relationship;
import net.hostsharing.hsadminng.HsadminNgApplication;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.context.ContextBasedTest;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
@@ -15,6 +16,7 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.test.annotation.DirtiesContext;
@@ -28,8 +30,7 @@
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { HsOfficeRelationshipRepository.class, Context.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class HsOfficeRelationshipRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java
@@ -17,6 +17,7 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.test.annotation.DirtiesContext;
@@ -32,8 +33,7 @@
import static org.assertj.core.api.Assumptions.assumeThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { HsOfficeSepaMandateRepository.class, Context.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
src/test/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantRepositoryIntegrationTest.java
@@ -13,6 +13,7 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.transaction.annotation.Propagation;
@@ -28,8 +29,7 @@
import static org.assertj.core.api.Assumptions.assumeThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { RbacGrantRepository.class, Context.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class RbacGrantRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleControllerRestTest.java
@@ -1,11 +1,15 @@
package net.hostsharing.hsadminng.rbac.rbacrole;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@@ -18,12 +22,16 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(RbacRoleController.class)
@Import(Mapper.class)
@RunWith(SpringRunner.class)
class RbacRoleControllerRestTest {
    @Autowired
    MockMvc mockMvc;
    @MockBean
    Context contextMock;
    @MockBean
    RbacRoleRepository rbacRoleRepository;
@@ -32,23 +40,23 @@
        // given
        when(rbacRoleRepository.findAll()).thenReturn(
            asList(hostmasterRole, customerXxxOwner, customerXxxAdmin));
                asList(hostmasterRole, customerXxxOwner, customerXxxAdmin));
        // when
        mockMvc.perform(MockMvcRequestBuilders
                .get("/api/rbac/roles")
                .header("current-user", "superuser-alex@hostsharing.net")
                .accept(MediaType.APPLICATION_JSON))
                        .get("/api/rbac/roles")
                        .header("current-user", "superuser-alex@hostsharing.net")
                        .accept(MediaType.APPLICATION_JSON))
            // then
            .andExpect(status().isOk())
            .andExpect(jsonPath("$", hasSize(3)))
            .andExpect(jsonPath("$[0].roleName", is("global#global.admin")))
            .andExpect(jsonPath("$[1].roleName", is("test_customer#xxx.owner")))
            .andExpect(jsonPath("$[2].roleName", is("test_customer#xxx.admin")))
            .andExpect(jsonPath("$[2].uuid", is(customerXxxAdmin.getUuid().toString())))
            .andExpect(jsonPath("$[2].objectUuid", is(customerXxxAdmin.getObjectUuid().toString())))
            .andExpect(jsonPath("$[2].objectTable", is(customerXxxAdmin.getObjectTable().toString())))
            .andExpect(jsonPath("$[2].objectIdName", is(customerXxxAdmin.getObjectIdName().toString())));
                // then
                .andExpect(status().isOk())
                .andExpect(jsonPath("$", hasSize(3)))
                .andExpect(jsonPath("$[0].roleName", is("global#global.admin")))
                .andExpect(jsonPath("$[1].roleName", is("test_customer#xxx.owner")))
                .andExpect(jsonPath("$[2].roleName", is("test_customer#xxx.admin")))
                .andExpect(jsonPath("$[2].uuid", is(customerXxxAdmin.getUuid().toString())))
                .andExpect(jsonPath("$[2].objectUuid", is(customerXxxAdmin.getObjectUuid().toString())))
                .andExpect(jsonPath("$[2].objectTable", is(customerXxxAdmin.getObjectTable().toString())))
                .andExpect(jsonPath("$[2].objectIdName", is(customerXxxAdmin.getObjectIdName().toString())));
    }
}
src/test/java/net/hostsharing/hsadminng/rbac/rbacrole/RbacRoleRepositoryIntegrationTest.java
@@ -2,12 +2,14 @@
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.test.Array;
import net.hostsharing.test.JpaAttempt;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.test.annotation.DirtiesContext;
@@ -19,8 +21,7 @@
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { Context.class, RbacRoleRepository.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class RbacRoleRepositoryIntegrationTest {
    @Autowired
src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserControllerRestTest.java
@@ -1,11 +1,15 @@
package net.hostsharing.hsadminng.rbac.rbacuser;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.mapper.Mapper;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@@ -19,12 +23,16 @@
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(RbacUserController.class)
@Import(Mapper.class)
@RunWith(SpringRunner.class)
class RbacUserControllerRestTest {
    @Autowired
    MockMvc mockMvc;
    @MockBean
    Context contextMock;
    @MockBean
    RbacUserRepository rbacUserRepository;
src/test/java/net/hostsharing/hsadminng/rbac/rbacuser/RbacUserRepositoryIntegrationTest.java
@@ -10,6 +10,7 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.transaction.annotation.Propagation;
@@ -24,8 +25,7 @@
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { RbacUserRepository.class, Context.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class RbacUserRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
src/test/java/net/hostsharing/hsadminng/test/cust/TestCustomerRepositoryIntegrationTest.java
@@ -2,12 +2,14 @@
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.context.ContextBasedTest;
import net.hostsharing.test.JpaAttempt;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import javax.persistence.EntityManager;
@@ -20,8 +22,7 @@
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { Context.class, TestCustomerRepository.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class TestCustomerRepositoryIntegrationTest extends ContextBasedTest {
    @Autowired
src/test/java/net/hostsharing/hsadminng/test/pac/TestPackageRepositoryIntegrationTest.java
@@ -9,6 +9,7 @@
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.test.annotation.DirtiesContext;
@@ -19,8 +20,7 @@
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@ComponentScan(basePackageClasses = { Context.class, TestCustomerRepository.class, JpaAttempt.class })
@DirtiesContext
@Import( { Context.class, JpaAttempt.class })
class TestPackageRepositoryIntegrationTest {
    @Autowired
src/test/java/net/hostsharing/test/MapperUnitTest.java
@@ -7,16 +7,21 @@
import net.hostsharing.hsadminng.mapper.Mapper;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.fail;
class MapperUnitTest {
    private Mapper mapper = new Mapper();
    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    public static class SourceBean {
        private String a;
        private String b;
    }
@@ -26,6 +31,7 @@
    @NoArgsConstructor
    @AllArgsConstructor
    public static class TargetBean {
        private String a;
        private String b;
        private String c;
@@ -34,14 +40,14 @@
    @Test
    void mapsNullBeanToNull() {
        final SourceBean givenSource = null;
        final var result = Mapper.map(givenSource, TargetBean.class, (s, t) -> { fail("should not have been called"); });
        final var result = mapper.map(givenSource, TargetBean.class, (s, t) -> {fail("should not have been called");});
        assertThat(result).isNull();
    }
    @Test
    void mapsBean() {
        final SourceBean givenSource = new SourceBean("1234", "Text");
        final var result = Mapper.map(givenSource, TargetBean.class, null);
        final var result = mapper.map(givenSource, TargetBean.class);
        assertThat(result).usingRecursiveComparison().isEqualTo(
                new TargetBean("1234", "Text", null)
        );
@@ -50,9 +56,38 @@
    @Test
    void mapsBeanWithPostmapper() {
        final SourceBean givenSource = new SourceBean("1234", "Text");
        final var result = Mapper.map(givenSource, TargetBean.class, (s, t) -> { t.setC("Extra"); });
        final var result = mapper.map(givenSource, TargetBean.class, (s, t) -> {t.setC("Extra");});
        assertThat(result).usingRecursiveComparison().isEqualTo(
                new TargetBean("1234", "Text", "Extra")
        );
    }
    @Test
    void mapsList() {
        final var givenSource = List.of(
                new SourceBean("111", "Text A"),
                new SourceBean("222", "Text B"),
                new SourceBean("333", "Text C"));
        final var result = mapper.mapList(givenSource, TargetBean.class);
        assertThat(result).usingRecursiveComparison().isEqualTo(
                List.of(
                        new TargetBean("111", "Text A", null),
                        new TargetBean("222", "Text B", null),
                        new TargetBean("333", "Text C", null)));
    }
    @Test
    void mapsListWithPostMapper() {
        final var givenSource = List.of(
                new SourceBean("111", "Text A"),
                new SourceBean("222", "Text B"),
                new SourceBean("333", "Text C"));
        final var result = mapper.mapList(givenSource, TargetBean.class, (s, t) -> {t.setC("Extra");});
        assertThat(result).usingRecursiveComparison().isEqualTo(
                List.of(
                        new TargetBean("111", "Text A", "Extra"),
                        new TargetBean("222", "Text B", "Extra"),
                        new TargetBean("333", "Text C", "Extra")));
    }
}