refactoring for implicit creation of dependend hosting-assets #108

Merged
hsh-michaelhoennig merged 22 commits from refactoring-for-implicit-creation-of-dependend-hosting-assets into master 2024-09-26 10:51:30 +02:00
4 changed files with 56 additions and 19 deletions
Showing only changes of commit dc4cd818b4 - Show all commits

View File

@ -11,13 +11,18 @@ import java.lang.annotation.Target;
public @interface DisplayAs { public @interface DisplayAs {
class DisplayName { class DisplayName {
public static String of(final Class<?> clazz) { public static String of(final Class<?> clazz) {
final var displayNameAnnot = clazz.getAnnotation(DisplayAs.class); final var displayNameAnnot = getDisplayNameAnnotation(clazz);
return displayNameAnnot != null ? displayNameAnnot.value() : clazz.getSimpleName(); return displayNameAnnot != null ? displayNameAnnot.value() : clazz.getSimpleName();
} }
public static String of(@NotNull final Object instance) { public static String of(@NotNull final Object instance) {
return of(instance.getClass()); return of(instance.getClass());
} }
private static DisplayAs getDisplayNameAnnotation(final Class<?> clazz) {
final var annot = clazz.getAnnotation(DisplayAs.class);
return annot != null ? annot : getDisplayNameAnnotation(clazz.getSuperclass());
}
} }
String value() default ""; String value() default "";

View File

@ -8,7 +8,7 @@ import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeDebito
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealEntity;
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealRepository; import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationRealRepository;
import net.hostsharing.hsadminng.mapper.StandardMapper; import net.hostsharing.hsadminng.mapper.StandardMapper;
import net.hostsharing.hsadminng.rbac.object.BaseEntity; import net.hostsharing.hsadminng.persistence.EntityExistsValidator;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -23,7 +23,6 @@ import jakarta.validation.ValidationException;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import static net.hostsharing.hsadminng.errors.DisplayAs.DisplayName;
import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.DEBITOR; import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.DEBITOR;
@RestController @RestController
@ -42,6 +41,9 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi {
@Autowired @Autowired
private HsOfficeRelationRealRepository relrealRepo; private HsOfficeRelationRealRepository relrealRepo;
@Autowired
private EntityExistsValidator entityValidator;
@PersistenceContext @PersistenceContext
private EntityManager em; private EntityManager em;
@ -85,9 +87,9 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi {
if ( body.getDebitorRel() != null ) { if ( body.getDebitorRel() != null ) {
body.getDebitorRel().setType(DEBITOR.name()); body.getDebitorRel().setType(DEBITOR.name());
final var debitorRel = mapper.map("debitorRel.", body.getDebitorRel(), HsOfficeRelationRealEntity.class); final var debitorRel = mapper.map("debitorRel.", body.getDebitorRel(), HsOfficeRelationRealEntity.class);
validateEntityExists("debitorRel.anchorUuid", debitorRel.getAnchor()); entityValidator.validateEntityExists("debitorRel.anchorUuid", debitorRel.getAnchor());
validateEntityExists("debitorRel.holderUuid", debitorRel.getHolder()); entityValidator.validateEntityExists("debitorRel.holderUuid", debitorRel.getHolder());
validateEntityExists("debitorRel.contactUuid", debitorRel.getContact()); entityValidator.validateEntityExists("debitorRel.contactUuid", debitorRel.getContact());
entityToSave.setDebitorRel(relrealRepo.save(debitorRel)); entityToSave.setDebitorRel(relrealRepo.save(debitorRel));
} else { } else {
final var debitorRelOptional = relrealRepo.findByUuid(body.getDebitorRelUuid()); final var debitorRelOptional = relrealRepo.findByUuid(body.getDebitorRelUuid());
@ -160,15 +162,4 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi {
final var mapped = mapper.map(saved, HsOfficeDebitorResource.class); final var mapped = mapper.map(saved, HsOfficeDebitorResource.class);
return ResponseEntity.ok(mapped); return ResponseEntity.ok(mapped);
} }
// TODO.impl: extract this to some generally usable class?
private <T extends BaseEntity<T>> T validateEntityExists(final String property, final T entitySkeleton) {
final var foundEntity = em.find(entitySkeleton.getClass(), entitySkeleton.getUuid());
if ( foundEntity == null) {
throw new ValidationException("Unable to find " + DisplayName.of(entitySkeleton) + " by " + property + ": " + entitySkeleton.getUuid());
}
//noinspection unchecked
return (T) foundEntity;
}
} }

View File

@ -0,0 +1,41 @@
package net.hostsharing.hsadminng.persistence;
import lombok.experimental.UtilityClass;
import net.hostsharing.hsadminng.errors.DisplayAs;
import net.hostsharing.hsadminng.errors.DisplayAs.DisplayName;
import net.hostsharing.hsadminng.rbac.object.BaseEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import jakarta.persistence.Entity;
import jakarta.validation.ValidationException;
@Service
public class EntityExistsValidator {
@Autowired
private EntityManagerWrapper em;
public <T extends BaseEntity<T>> void validateEntityExists(final String property, final T entitySkeleton) {
final var foundEntity = em.find(entityClass(entitySkeleton), entitySkeleton.getUuid());
if ( foundEntity == null) {
throw new ValidationException("Unable to find " + DisplayName.of(entitySkeleton) + " by " + property + ": " + entitySkeleton.getUuid());
}
}
private static <T extends BaseEntity<T>> Class<?> entityClass(final T entityOrProxy) {
final var entityClass = entityClass(entityOrProxy.getClass());
if (entityClass == null) {
throw new IllegalArgumentException("@Entity not found in superclass hierarchy of " + entityOrProxy.getClass());
}
return entityClass;
}
private static Class<?> entityClass(final Class<?> entityOrProxyClass) {
return entityOrProxyClass.isAnnotationPresent(Entity.class)
? entityOrProxyClass
: entityOrProxyClass.getSuperclass() == null
? null
: entityClass(entityOrProxyClass.getSuperclass());
}
}

View File

@ -405,7 +405,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
.post("http://localhost/api/hs/office/debitors") .post("http://localhost/api/hs/office/debitors")
.then().log().all().assertThat() .then().log().all().assertThat()
.statusCode(400) .statusCode(400)
.body("message", is("ERROR: [400] Unable to find RealContact by debitorRel.contact.uuid: 00000000-0000-0000-0000-000000000000")); .body("message", is("ERROR: [400] Unable to find RealContact by debitorRel.contactUuid: 00000000-0000-0000-0000-000000000000"));
// @formatter:on // @formatter:on
} }
@ -433,7 +433,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
.post("http://localhost/api/hs/office/debitors") .post("http://localhost/api/hs/office/debitors")
.then().log().all().assertThat() .then().log().all().assertThat()
.statusCode(400) .statusCode(400)
.body("message", is("ERROR: [400] Unable to find RealRelation by debitorRel.uuid: 00000000-0000-0000-0000-000000000000")); .body("message", is("ERROR: [400] Unable to find RealRelation by debitorRelUuid: 00000000-0000-0000-0000-000000000000"));
// @formatter:on // @formatter:on
} }
} }