This commit is contained in:
Michael Hoennig 2024-06-30 10:58:01 +02:00
parent 7b82be64a4
commit 9ddca24446
19 changed files with 179 additions and 124 deletions

View File

@ -15,7 +15,7 @@ public class MultiValidationException extends ValidationException {
); );
} }
public static void throwInvalid(final List<String> violations) { public static void throwIfNotEmpty(final List<String> violations) {
if (!violations.isEmpty()) { if (!violations.isEmpty()) {
throw new MultiValidationException(violations); throw new MultiValidationException(violations);
} }

View File

@ -20,7 +20,13 @@ public class HsBookingItemEntityValidator extends HsEntityValidator<HsBookingIte
super(properties); super(properties);
} }
public List<String> validate(final HsBookingItemEntity bookingItem) { @Override
public List<String> validateEntity(final HsBookingItemEntity bookingItem) {
return validateProperties(bookingItem);
}
@Override
public List<String> validateContext(final HsBookingItemEntity bookingItem) {
return sequentiallyValidate( return sequentiallyValidate(
() -> validateProperties(bookingItem), () -> validateProperties(bookingItem),
() -> optionallyValidate(bookingItem.getParentItem()), () -> optionallyValidate(bookingItem.getParentItem()),

View File

@ -45,11 +45,13 @@ public class HsBookingItemEntityValidatorRegistry {
} }
public static List<String> doValidate(final HsBookingItemEntity bookingItem) { public static List<String> doValidate(final HsBookingItemEntity bookingItem) {
return HsBookingItemEntityValidatorRegistry.forType(bookingItem.getType()).validate(bookingItem); return HsEntityValidator.sequentiallyValidate(
() -> HsBookingItemEntityValidatorRegistry.forType(bookingItem.getType()).validateEntity(bookingItem),
() -> HsBookingItemEntityValidatorRegistry.forType(bookingItem.getType()).validateContext(bookingItem));
} }
public static HsBookingItemEntity validated(final HsBookingItemEntity entityToSave) { public static HsBookingItemEntity validated(final HsBookingItemEntity entityToSave) {
MultiValidationException.throwInvalid(doValidate(entityToSave)); MultiValidationException.throwIfNotEmpty(doValidate(entityToSave));
return entityToSave; return entityToSave;
} }
} }

View File

@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.hs.hosting.asset; package net.hostsharing.hsadminng.hs.hosting.asset;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRepository; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRepository;
import net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityProcessor;
import net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidatorRegistry; import net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidatorRegistry;
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingAssetsApi; import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.api.HsHostingAssetsApi;
@ -21,11 +22,10 @@ import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityNotFoundException; import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsHostingAssetEntityValidatorRegistry.validated;
@RestController @RestController
public class HsHostingAssetController implements HsHostingAssetsApi { public class HsHostingAssetController implements HsHostingAssetsApi {
@ -56,7 +56,7 @@ public class HsHostingAssetController implements HsHostingAssetsApi {
final var entities = assetRepo.findAllByCriteria(debitorUuid, parentAssetUuid, HsHostingAssetType.of(type)); final var entities = assetRepo.findAllByCriteria(debitorUuid, parentAssetUuid, HsHostingAssetType.of(type));
final var resources = mapper.mapList(entities, HsHostingAssetResource.class); final var resources = mapper.mapList(entities, HsHostingAssetResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
return ResponseEntity.ok(resources); return ResponseEntity.ok(resources);
} }
@ -70,16 +70,21 @@ public class HsHostingAssetController implements HsHostingAssetsApi {
context.define(currentUser, assumedRoles); context.define(currentUser, assumedRoles);
final var entityToSave = mapper.map(body, HsHostingAssetEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER); final var entity = mapper.map(body, HsHostingAssetEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER);
final var saved = validated(assetRepo.save(entityToSave)); final var mapped = new HsHostingAssetEntityProcessor(entity)
.validateEntity()
.prepareForSave()
.saveUsing(assetRepo::save)
.validateContext()
.mapUsing(e -> mapper.map(e, HsHostingAssetResource.class))
.revampProperties();
final var uri = final var uri =
MvcUriComponentsBuilder.fromController(getClass()) MvcUriComponentsBuilder.fromController(getClass())
.path("/api/hs/hosting/assets/{id}") .path("/api/hs/hosting/assets/{id}")
.buildAndExpand(saved.getUuid()) .buildAndExpand(mapped.getUuid())
.toUri(); .toUri();
final var mapped = mapper.map(saved, HsHostingAssetResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
return ResponseEntity.created(uri).body(mapped); return ResponseEntity.created(uri).body(mapped);
} }
@ -123,21 +128,18 @@ public class HsHostingAssetController implements HsHostingAssetsApi {
context.define(currentUser, assumedRoles); context.define(currentUser, assumedRoles);
final var current = assetRepo.findByUuid(assetUuid).orElseThrow(); final var entity = assetRepo.findByUuid(assetUuid).orElseThrow();
new HsHostingAssetEntityPatcher(em, current).apply(body); new HsHostingAssetEntityPatcher(em, entity).apply(body);
// TODO.refa: draft for an alternative API final var mapped = new HsHostingAssetEntityProcessor(entity)
// validate(current) // self-validation, hashing passwords etc. .validateEntity()
// .then(HsHostingAssetEntityValidatorRegistry::prepareForSave) // hashing passwords etc. .prepareForSave()
// .then(assetRepo::save) .saveUsing(assetRepo::save)
// .then(HsHostingAssetEntityValidatorRegistry::validateInContext) .validateContext()
// // In this last step we need the entity and the mapped resource instance, .mapUsing(e -> mapper.map(e, HsHostingAssetResource.class))
// // which is exactly what a postmapper takes as arguments. .revampProperties();
// .then(this::mapToResource) using postProcessProperties to remove write-only + add read-only properties
final var saved = validated(assetRepo.save(current));
final var mapped = mapper.map(saved, HsHostingAssetResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
return ResponseEntity.ok(mapped); return ResponseEntity.ok(mapped);
} }
@ -155,6 +157,8 @@ public class HsHostingAssetController implements HsHostingAssetsApi {
} }
}; };
final BiConsumer<HsHostingAssetEntity, HsHostingAssetResource> ENTITY_TO_RESOURCE_POSTMAPPER @SuppressWarnings("unchecked")
= HsHostingAssetEntityValidatorRegistry::postprocessProperties; final BiConsumer<HsHostingAssetEntity, HsHostingAssetResource> ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource)
-> HsHostingAssetEntityValidatorRegistry.forType(entity.getType())
.revampProperties(entity, (Map<String, Object>) resource.getConfig());
} }

View File

@ -0,0 +1,61 @@
package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.errors.MultiValidationException;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import net.hostsharing.hsadminng.hs.hosting.generated.api.v1.model.HsHostingAssetResource;
import net.hostsharing.hsadminng.hs.validation.HsEntityValidator;
import java.util.Map;
import java.util.function.Function;
/**
* Wraps the steps of the pararation, validation, mapping and revamp around saving of a HsHostingAssetEntity into a readable API.
*/
public class HsHostingAssetEntityProcessor {
private final HsEntityValidator<HsHostingAssetEntity> validator;
private HsHostingAssetEntity entity;
private HsHostingAssetResource resource;
public HsHostingAssetEntityProcessor(final HsHostingAssetEntity entity) {
this.entity = entity;
this.validator = HsHostingAssetEntityValidatorRegistry.forType(entity.getType());
}
/// validates the entity itself including its properties
public HsHostingAssetEntityProcessor validateEntity() {
MultiValidationException.throwIfNotEmpty(validator.validateEntity(entity));
return this;
}
/// hashing passwords etc.
public HsHostingAssetEntityProcessor prepareForSave() {
// FIXME: add computed properties
return this;
}
public HsHostingAssetEntityProcessor saveUsing(final Function<HsHostingAssetEntity, HsHostingAssetEntity> saveFunction) {
entity = saveFunction.apply(entity);
return this;
}
/// validates the entity within it's parent and child hierarchy (e.g. totals validators and other limits)
public HsHostingAssetEntityProcessor validateContext() {
MultiValidationException.throwIfNotEmpty(validator.validateContext(entity));
return this;
}
/// maps entity to JSON resource representation
public HsHostingAssetEntityProcessor mapUsing(
final Function<HsHostingAssetEntity, HsHostingAssetResource> mapFunction) {
resource = mapFunction.apply(entity);
return this;
}
/// removes write-only-properties and ads computed-properties
@SuppressWarnings("unchecked")
public HsHostingAssetResource revampProperties() {
validator.revampProperties(entity, (Map<String, Object>) resource.getConfig());
return resource;
}
}

View File

@ -45,10 +45,16 @@ public abstract class HsHostingAssetEntityValidator extends HsEntityValidator<Hs
} }
@Override @Override
public List<String> validate(final HsHostingAssetEntity assetEntity) { public List<String> validateEntity(final HsHostingAssetEntity assetEntity) {
return sequentiallyValidate( return sequentiallyValidate(
() -> validateEntityReferencesAndProperties(assetEntity), () -> validateEntityReferencesAndProperties(assetEntity),
() -> validateIdentifierPattern(assetEntity), // might need proper parentAsset or billingItem () -> validateIdentifierPattern(assetEntity)
);
}
@Override
public List<String> validateContext(final HsHostingAssetEntity assetEntity) {
return sequentiallyValidate(
() -> optionallyValidate(assetEntity.getBookingItem()), () -> optionallyValidate(assetEntity.getBookingItem()),
() -> optionallyValidate(assetEntity.getParentAsset()), () -> optionallyValidate(assetEntity.getParentAsset()),
() -> validateAgainstSubEntities(assetEntity) () -> validateAgainstSubEntities(assetEntity)
@ -82,13 +88,15 @@ public abstract class HsHostingAssetEntityValidator extends HsEntityValidator<Hs
private static List<String> optionallyValidate(final HsHostingAssetEntity assetEntity) { private static List<String> optionallyValidate(final HsHostingAssetEntity assetEntity) {
return assetEntity != null return assetEntity != null
? enrich(prefix(assetEntity.toShortString(), "parentAsset"), ? enrich(prefix(assetEntity.toShortString(), "parentAsset"),
HsHostingAssetEntityValidatorRegistry.forType(assetEntity.getType()).validate(assetEntity)) // FIXME: actually only validateSubEntities is necessary
HsHostingAssetEntityValidatorRegistry.forType(assetEntity.getType()).validateContext(assetEntity))
: emptyList(); : emptyList();
} }
private static List<String> optionallyValidate(final HsBookingItemEntity bookingItem) { private static List<String> optionallyValidate(final HsBookingItemEntity bookingItem) {
return bookingItem != null return bookingItem != null
? enrich(prefix(bookingItem.toShortString(), "bookingItem"), ? enrich(prefix(bookingItem.toShortString(), "bookingItem"),
// FIXME: actually only validateSubEntities is necessary
HsBookingItemEntityValidatorRegistry.doValidate(bookingItem)) HsBookingItemEntityValidatorRegistry.doValidate(bookingItem))
: emptyList(); : emptyList();
} }

View File

@ -40,22 +40,6 @@ public class HsHostingAssetEntityValidatorRegistry {
return validators.keySet(); return validators.keySet();
} }
public static List<String> doValidate(final HsHostingAssetEntity hostingAsset) {
final var validator = HsHostingAssetEntityValidatorRegistry.forType(hostingAsset.getType());
return validator.validate(hostingAsset);
}
public static HsHostingAssetEntity validated(final HsHostingAssetEntity entityToSave) {
MultiValidationException.throwInvalid(doValidate(entityToSave));
return entityToSave;
}
public static void postprocessProperties(final HsHostingAssetEntity entity, final HsHostingAssetResource resource) {
final var validator = HsHostingAssetEntityValidatorRegistry.forType(entity.getType());
final var config = validator.postProcess(entity, asMap(resource));
resource.setConfig(config);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static Map<String, Object> asMap(final HsHostingAssetResource resource) { private static Map<String, Object> asMap(final HsHostingAssetResource resource) {
if (resource.getConfig() instanceof Map map) { if (resource.getConfig() instanceof Map map) {

View File

@ -96,7 +96,7 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse
validateDebitTransaction(requestBody, violations); validateDebitTransaction(requestBody, violations);
validateCreditTransaction(requestBody, violations); validateCreditTransaction(requestBody, violations);
validateAssetValue(requestBody, violations); validateAssetValue(requestBody, violations);
MultiValidationException.throwInvalid(violations); MultiValidationException.throwIfNotEmpty(violations);
} }
private static void validateDebitTransaction( private static void validateDebitTransaction(

View File

@ -98,7 +98,7 @@ public class HsOfficeCoopSharesTransactionController implements HsOfficeCoopShar
validateSubscriptionTransaction(requestBody, violations); validateSubscriptionTransaction(requestBody, violations);
validateCancellationTransaction(requestBody, violations); validateCancellationTransaction(requestBody, violations);
validateshareCount(requestBody, violations); validateshareCount(requestBody, violations);
MultiValidationException.throwInvalid(violations); MultiValidationException.throwIfNotEmpty(violations);
} }
private static void validateSubscriptionTransaction( private static void validateSubscriptionTransaction(

View File

@ -32,7 +32,8 @@ public abstract class HsEntityValidator<E extends PropertiesProvider> {
return String.join(".", parts); return String.join(".", parts);
} }
public abstract List<String> validate(final E entity); public abstract List<String> validateEntity(final E entity);
public abstract List<String> validateContext(final E entity);
public final List<Map<String, Object>> properties() { public final List<Map<String, Object>> properties() {
return Arrays.stream(propertyValidators) return Arrays.stream(propertyValidators)
@ -60,7 +61,7 @@ public abstract class HsEntityValidator<E extends PropertiesProvider> {
} }
@SafeVarargs @SafeVarargs
protected static List<String> sequentiallyValidate(final Supplier<List<String>>... validators) { public static List<String> sequentiallyValidate(final Supplier<List<String>>... validators) {
return new ArrayList<>(stream(validators) return new ArrayList<>(stream(validators)
.map(Supplier::get) .map(Supplier::get)
.filter(violations -> !violations.isEmpty()) .filter(violations -> !violations.isEmpty())
@ -89,7 +90,7 @@ public abstract class HsEntityValidator<E extends PropertiesProvider> {
throw new IllegalArgumentException("Integer value (or null) expected, but got " + value); throw new IllegalArgumentException("Integer value (or null) expected, but got " + value);
} }
public Map<String, Object> postProcess(final E entity, final Map<String, Object> config) { public Map<String, Object> revampProperties(final E entity, final Map<String, Object> config) {
final var copy = new HashMap<>(config); final var copy = new HashMap<>(config);
stream(propertyValidators).forEach(p -> { stream(propertyValidators).forEach(p -> {
// FIXME: maybe move to ValidatableProperty.postProcess(...)? // FIXME: maybe move to ValidatableProperty.postProcess(...)?

View File

@ -55,13 +55,13 @@ class HsCloudServerBookingItemValidatorUnitTest {
// then // then
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder( assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
"{type=boolean, propertyName=active, required=false, defaultValue=true, isTotalsValidator=false}", "{type=boolean, propertyName=active, defaultValue=true}",
"{type=integer, propertyName=CPUs, min=1, max=32, required=true, isTotalsValidator=false}", "{type=integer, propertyName=CPUs, min=1, max=32, required=true}",
"{type=integer, propertyName=RAM, unit=GB, min=1, max=128, required=true, isTotalsValidator=false}", "{type=integer, propertyName=RAM, unit=GB, min=1, max=128, required=true}",
"{type=integer, propertyName=SSD, unit=GB, min=0, max=1000, step=25, required=true, isTotalsValidator=false}", "{type=integer, propertyName=SSD, unit=GB, min=0, max=1000, step=25, required=true}",
"{type=integer, propertyName=HDD, unit=GB, min=0, max=4000, step=250, required=false, defaultValue=0, isTotalsValidator=false}", "{type=integer, propertyName=HDD, unit=GB, min=0, max=4000, step=250, defaultValue=0}",
"{type=integer, propertyName=Traffic, unit=GB, min=250, max=10000, step=250, required=true, isTotalsValidator=false}", "{type=integer, propertyName=Traffic, unit=GB, min=250, max=10000, step=250, required=true}",
"{type=enumeration, propertyName=SLA-Infrastructure, values=[BASIC, EXT8H, EXT4H, EXT2H], required=false, isTotalsValidator=false}"); "{type=enumeration, propertyName=SLA-Infrastructure, values=[BASIC, EXT8H, EXT4H, EXT2H]}");
} }
@Test @Test

View File

@ -63,17 +63,17 @@ class HsManagedServerBookingItemValidatorUnitTest {
// then // then
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder( assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
"{type=integer, propertyName=CPUs, min=1, max=32, required=true, isTotalsValidator=false}", "{type=integer, propertyName=CPUs, min=1, max=32, required=true}",
"{type=integer, propertyName=RAM, unit=GB, min=1, max=128, required=true, isTotalsValidator=false}", "{type=integer, propertyName=RAM, unit=GB, min=1, max=128, required=true}",
"{type=integer, propertyName=SSD, unit=GB, min=25, max=1000, step=25, required=true, isTotalsValidator=true, thresholdPercentage=200}", "{type=integer, propertyName=SSD, unit=GB, min=25, max=1000, step=25, required=true, isTotalsValidator=true, thresholdPercentage=200}",
"{type=integer, propertyName=HDD, unit=GB, min=0, max=4000, step=250, required=false, defaultValue=0, isTotalsValidator=true, thresholdPercentage=200}", "{type=integer, propertyName=HDD, unit=GB, min=0, max=4000, step=250, defaultValue=0, isTotalsValidator=true, thresholdPercentage=200}",
"{type=integer, propertyName=Traffic, unit=GB, min=250, max=10000, step=250, required=true, isTotalsValidator=true, thresholdPercentage=200}", "{type=integer, propertyName=Traffic, unit=GB, min=250, max=10000, step=250, required=true, isTotalsValidator=true, thresholdPercentage=200}",
"{type=enumeration, propertyName=SLA-Platform, values=[BASIC, EXT8H, EXT4H, EXT2H], required=false, defaultValue=BASIC, isTotalsValidator=false}", "{type=enumeration, propertyName=SLA-Platform, values=[BASIC, EXT8H, EXT4H, EXT2H], defaultValue=BASIC}",
"{type=boolean, propertyName=SLA-EMail, required=false, defaultValue=false, isTotalsValidator=false}", "{type=boolean, propertyName=SLA-EMail}", // TODO.impl: falseIf-validation is missing in output
"{type=boolean, propertyName=SLA-Maria, required=false, isTotalsValidator=false}", "{type=boolean, propertyName=SLA-Maria}",
"{type=boolean, propertyName=SLA-PgSQL, required=false, isTotalsValidator=false}", "{type=boolean, propertyName=SLA-PgSQL}",
"{type=boolean, propertyName=SLA-Office, required=false, isTotalsValidator=false}", "{type=boolean, propertyName=SLA-Office}",
"{type=boolean, propertyName=SLA-Web, required=false, isTotalsValidator=false}"); "{type=boolean, propertyName=SLA-Web}");
} }
@Test @Test

View File

@ -55,12 +55,12 @@ class HsManagedWebspaceBookingItemValidatorUnitTest {
// then // then
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder( assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
"{type=integer, propertyName=SSD, unit=GB, min=1, max=100, step=1, required=true, isTotalsValidator=false}", "{type=integer, propertyName=SSD, unit=GB, min=1, max=100, step=1, required=true}",
"{type=integer, propertyName=HDD, unit=GB, min=0, max=250, step=10, required=false, isTotalsValidator=false}", "{type=integer, propertyName=HDD, unit=GB, min=0, max=250, step=10}",
"{type=integer, propertyName=Traffic, unit=GB, min=10, max=1000, step=10, required=true, isTotalsValidator=false}", "{type=integer, propertyName=Traffic, unit=GB, min=10, max=1000, step=10, required=true}",
"{type=integer, propertyName=Multi, min=1, max=100, step=1, required=false, defaultValue=1, isTotalsValidator=false}", "{type=integer, propertyName=Multi, min=1, max=100, step=1, defaultValue=1}",
"{type=integer, propertyName=Daemons, min=0, max=10, required=false, defaultValue=0, isTotalsValidator=false}", "{type=integer, propertyName=Daemons, min=0, max=10, defaultValue=0}",
"{type=boolean, propertyName=Online Office Server, required=false, isTotalsValidator=false}", "{type=boolean, propertyName=Online Office Server}",
"{type=enumeration, propertyName=SLA-Platform, values=[BASIC, EXT24H], required=false, defaultValue=BASIC, isTotalsValidator=false}"); "{type=enumeration, propertyName=SLA-Platform, values=[BASIC, EXT24H], defaultValue=BASIC}");
} }
} }

View File

@ -29,7 +29,7 @@ class HsCloudServerHostingAssetValidatorUnitTest {
// when // when
final var result = validator.validate(cloudServerHostingAssetEntity); final var result = validator.validateEntity(cloudServerHostingAssetEntity);
// then // then
assertThat(result).containsExactlyInAnyOrder( assertThat(result).containsExactlyInAnyOrder(
@ -49,7 +49,7 @@ class HsCloudServerHostingAssetValidatorUnitTest {
// when // when
final var result = validator.validate(cloudServerHostingAssetEntity); final var result = validator.validateEntity(cloudServerHostingAssetEntity);
// then // then
assertThat(result).containsExactlyInAnyOrder( assertThat(result).containsExactlyInAnyOrder(
@ -71,12 +71,12 @@ class HsCloudServerHostingAssetValidatorUnitTest {
final var mangedServerHostingAssetEntity = HsHostingAssetEntity.builder() final var mangedServerHostingAssetEntity = HsHostingAssetEntity.builder()
.type(MANAGED_SERVER) .type(MANAGED_SERVER)
.identifier("xyz00") .identifier("xyz00")
.bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.CLOUD_SERVER).build()) .bookingItem(TEST_CLOUD_SERVER_BOOKING_ITEM)
.build(); .build();
final var validator = HsHostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType()); final var validator = HsHostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType());
// when // when
final var result = validator.validate(mangedServerHostingAssetEntity); final var result = validator.validateContext(mangedServerHostingAssetEntity);
// then // then
assertThat(result).containsExactlyInAnyOrder( assertThat(result).containsExactlyInAnyOrder(
@ -96,7 +96,7 @@ class HsCloudServerHostingAssetValidatorUnitTest {
final var validator = HsHostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType()); final var validator = HsHostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType());
// when // when
final var result = validator.validate(mangedServerHostingAssetEntity); final var result = validator.validateEntity(mangedServerHostingAssetEntity);
// then // then
assertThat(result).containsExactlyInAnyOrder( assertThat(result).containsExactlyInAnyOrder(

View File

@ -1,16 +1,10 @@
package net.hostsharing.hsadminng.hs.hosting.asset.validators; package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable; import static org.assertj.core.api.Assertions.catchThrowable;
import static org.assertj.core.api.Assertions.entry;
class HsHostingAssetEntityValidatorRegistryUnitTest { class HsHostingAssetEntityValidatorRegistryUnitTest {
@ -41,24 +35,4 @@ class HsHostingAssetEntityValidatorRegistryUnitTest {
HsHostingAssetType.UNIX_USER HsHostingAssetType.UNIX_USER
); );
} }
@Test
void validatedDoesNotThrowAnExceptionForValidEntity() {
final var givenBookingItem = HsBookingItemEntity.builder()
.type(HsBookingItemType.CLOUD_SERVER)
.resources(Map.ofEntries(
entry("CPUs", 4),
entry("RAM", 20),
entry("SSD", 50),
entry("Traffic", 250)
))
.build();
final var validEntity = HsHostingAssetEntity.builder()
.type(HsHostingAssetType.CLOUD_SERVER)
.bookingItem(givenBookingItem)
.identifier("vm1234")
.caption("some valid cloud server")
.build();
HsHostingAssetEntityValidatorRegistry.validated(validEntity);
}
} }

View File

@ -2,34 +2,43 @@ package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
import net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity;
import net.hostsharing.hsadminng.mapper.Array;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.stream.Stream;
import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_MANAGED_SERVER_BOOKING_ITEM;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
class HsHostingAssetEntityValidatorUnitTest { class HsHostingAssetEntityValidatorUnitTest {
@Test @Test
void validThrowsException() { void validatesEntity() {
// given // given
final var managedServerHostingAssetEntity = HsHostingAssetEntity.builder() final var managedServerHostingAssetEntity = HsHostingAssetEntity.builder()
.type(MANAGED_SERVER) .type(MANAGED_SERVER)
.identifier("vm1234") .identifier("vm1234")
.bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.MANAGED_SERVER).build()) .bookingItem(TEST_MANAGED_SERVER_BOOKING_ITEM)
.parentAsset(HsHostingAssetEntity.builder().type(MANAGED_SERVER).build()) .parentAsset(HsHostingAssetEntity.builder().type(MANAGED_SERVER).build())
.assignedToAsset(HsHostingAssetEntity.builder().type(MANAGED_SERVER).build()) .assignedToAsset(HsHostingAssetEntity.builder().type(MANAGED_SERVER).build())
.build(); .build();
// when // when
final var result = catchThrowable( ()-> HsHostingAssetEntityValidatorRegistry.validated(managedServerHostingAssetEntity)); final var validator = HsHostingAssetEntityValidatorRegistry.forType(managedServerHostingAssetEntity.getType());
final List<String> result = Stream.concat(
validator.validateEntity(managedServerHostingAssetEntity).stream(),
validator.validateContext(managedServerHostingAssetEntity).stream()
).toList();
// then // then
assertThat(result.getMessage()).contains( assertThat(result).containsExactlyInAnyOrder(
"'MANAGED_SERVER:vm1234.parentAsset' must be null but is set to D-???????-?:null", "'MANAGED_SERVER:vm1234.parentAsset' must be null but is set to D-???????-?:null",
"'MANAGED_SERVER:vm1234.assignedToAsset' must be null but is set to D-???????-?:null" "'MANAGED_SERVER:vm1234.assignedToAsset' must be null but is set to D-???????-?:null");
);
} }
} }
// FIXME: add tests validatesContext + revampProperties

View File

@ -8,6 +8,8 @@ import org.junit.jupiter.api.Test;
import java.util.Map; import java.util.Map;
import static java.util.Map.entry; import static java.util.Map.entry;
import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_CLOUD_SERVER_BOOKING_ITEM;
import static net.hostsharing.hsadminng.hs.booking.item.TestHsBookingItem.TEST_MANAGED_SERVER_BOOKING_ITEM;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_SERVER;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -19,7 +21,7 @@ class HsManagedServerHostingAssetValidatorUnitTest {
final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder() final var mangedWebspaceHostingAssetEntity = HsHostingAssetEntity.builder()
.type(MANAGED_SERVER) .type(MANAGED_SERVER)
.identifier("vm1234") .identifier("vm1234")
.bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.MANAGED_SERVER).build()) .bookingItem(TEST_MANAGED_SERVER_BOOKING_ITEM)
.parentAsset(HsHostingAssetEntity.builder().build()) .parentAsset(HsHostingAssetEntity.builder().build())
.assignedToAsset(HsHostingAssetEntity.builder().build()) .assignedToAsset(HsHostingAssetEntity.builder().build())
.config(Map.ofEntries( .config(Map.ofEntries(
@ -31,7 +33,7 @@ class HsManagedServerHostingAssetValidatorUnitTest {
final var validator = HsHostingAssetEntityValidatorRegistry.forType(mangedWebspaceHostingAssetEntity.getType()); final var validator = HsHostingAssetEntityValidatorRegistry.forType(mangedWebspaceHostingAssetEntity.getType());
// when // when
final var result = validator.validate(mangedWebspaceHostingAssetEntity); final var result = validator.validateContext(mangedWebspaceHostingAssetEntity);
// then // then
assertThat(result).containsExactlyInAnyOrder( assertThat(result).containsExactlyInAnyOrder(
@ -53,7 +55,7 @@ class HsManagedServerHostingAssetValidatorUnitTest {
final var validator = HsHostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType()); final var validator = HsHostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType());
// when // when
final var result = validator.validate(mangedServerHostingAssetEntity); final var result = validator.validateEntity(mangedServerHostingAssetEntity);
// then // then
assertThat(result).containsExactlyInAnyOrder( assertThat(result).containsExactlyInAnyOrder(
@ -68,12 +70,12 @@ class HsManagedServerHostingAssetValidatorUnitTest {
.identifier("xyz00") .identifier("xyz00")
.parentAsset(HsHostingAssetEntity.builder().build()) .parentAsset(HsHostingAssetEntity.builder().build())
.assignedToAsset(HsHostingAssetEntity.builder().build()) .assignedToAsset(HsHostingAssetEntity.builder().build())
.bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.CLOUD_SERVER).build()) .bookingItem(TEST_CLOUD_SERVER_BOOKING_ITEM)
.build(); .build();
final var validator = HsHostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType()); final var validator = HsHostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType());
// when // when
final var result = validator.validate(mangedServerHostingAssetEntity); final var result = validator.validateContext(mangedServerHostingAssetEntity);
// then // then
assertThat(result).containsExactlyInAnyOrder( assertThat(result).containsExactlyInAnyOrder(

View File

@ -7,6 +7,7 @@ import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.Map; import java.util.Map;
import java.util.stream.Stream;
import static java.util.Map.entry; import static java.util.Map.entry;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE;
@ -70,7 +71,7 @@ class HsManagedWebspaceHostingAssetValidatorUnitTest {
.build(); .build();
// when // when
final var result = validator.validate(mangedWebspaceHostingAssetEntity); final var result = validator.validateContext(mangedWebspaceHostingAssetEntity);
// then // then
assertThat(result).isEmpty(); assertThat(result).isEmpty();
@ -88,7 +89,7 @@ class HsManagedWebspaceHostingAssetValidatorUnitTest {
.build(); .build();
// when // when
final var result = validator.validate(mangedWebspaceHostingAssetEntity); final var result = validator.validateEntity(mangedWebspaceHostingAssetEntity);
// then // then
assertThat(result).containsExactly("'identifier' expected to match '^abc[0-9][0-9]$', but is 'xyz00'"); assertThat(result).containsExactly("'identifier' expected to match '^abc[0-9][0-9]$', but is 'xyz00'");
@ -109,7 +110,7 @@ class HsManagedWebspaceHostingAssetValidatorUnitTest {
.build(); .build();
// when // when
final var result = validator.validate(mangedWebspaceHostingAssetEntity); final var result = validator.validateEntity(mangedWebspaceHostingAssetEntity);
// then // then
assertThat(result).containsExactly("'MANAGED_WEBSPACE:abc00.config.unknown' is not expected but is set to 'some value'"); assertThat(result).containsExactly("'MANAGED_WEBSPACE:abc00.config.unknown' is not expected but is set to 'some value'");
@ -131,7 +132,10 @@ class HsManagedWebspaceHostingAssetValidatorUnitTest {
.build(); .build();
// when // when
final var result = validator.validate(mangedWebspaceHostingAssetEntity); final var result = Stream.concat(
validator.validateEntity(mangedWebspaceHostingAssetEntity).stream(),
validator.validateContext(mangedWebspaceHostingAssetEntity).stream())
.toList();
// then // then
assertThat(result).isEmpty(); assertThat(result).isEmpty();
@ -154,7 +158,7 @@ class HsManagedWebspaceHostingAssetValidatorUnitTest {
.build(); .build();
// when // when
final var result = validator.validate(mangedWebspaceHostingAssetEntity); final var result = validator.validateContext(mangedWebspaceHostingAssetEntity);
// then // then
assertThat(result).containsExactly( assertThat(result).containsExactly(

View File

@ -46,7 +46,7 @@ class HsUnixUserHostingAssetValidatorUnitTest {
final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType()); final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType());
// when // when
final var result = validator.validate(unixUserHostingAsset); final var result = validator.validateEntity(unixUserHostingAsset); // FIXME: validateContext
// then // then
assertThat(result).isEmpty(); assertThat(result).isEmpty();
@ -74,7 +74,7 @@ class HsUnixUserHostingAssetValidatorUnitTest {
final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType()); final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType());
// when // when
final var result = validator.validate(unixUserHostingAsset); final var result = validator.validateEntity(unixUserHostingAsset);
// then // then
assertThat(result).containsExactlyInAnyOrder( assertThat(result).containsExactlyInAnyOrder(
@ -101,7 +101,7 @@ class HsUnixUserHostingAssetValidatorUnitTest {
final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType()); final var validator = HsHostingAssetEntityValidatorRegistry.forType(unixUserHostingAsset.getType());
// when // when
final var result = validator.validate(unixUserHostingAsset); final var result = validator.validateEntity(unixUserHostingAsset);
// then // then
assertThat(result).containsExactly( assertThat(result).containsExactly(