Skip to content

Commit

Permalink
JNG-6082 Refactor required validation and default value processing (#229
Browse files Browse the repository at this point in the history
)

[2025-01-20 14:01:19 +0100] bence.gelei: revert rename
[2025-01-19 23:03:45 +0100] bence.gelei: JNG-6082 [Release] Updating versions
[2025-01-19 22:49:34 +0100] bence.gelei: do not load entity defaults if mapped to is the same
[2025-01-19 20:28:34 +0100] bence.gelei: pre-pr changes
[2025-01-17 11:23:36 +0100] bence.gelei: QoL
[2025-01-16 18:03:36 +0100] bence.gelei: flexible traverser
[2025-01-16 15:21:57 +0100] bence.gelei: JNG-6082 [Release] Updating versions
[2025-01-16 15:09:33 +0100] bence.gelei: fix apply logic
[2025-01-16 15:09:23 +0100] bence.gelei: use default value applier and do not copy default values
[2025-01-15 19:09:49 +0100] bence.gelei: rename
[2025-01-15 17:45:58 +0100] bence.gelei: JNG-6082 [Release] Updating versions
[2025-01-15 17:29:52 +0100] bence.gelei: populators implemented
[2025-01-14 15:59:44 +0100] bence.gelei: fix string validator
[2025-01-14 15:51:20 +0100] bence.gelei: optional dao parameter for request converter
[2025-01-14 15:28:17 +0100] bence.gelei: fix default value loading
[2025-01-13 18:26:31 +0100] bence.gelei: JNG-6082 [Release] Updating versions
[2025-01-13 17:48:03 +0100] bence.gelei: Merge branch 'develop' into feature/JNG-6082_Refactor_required_validation_and_default_value_processing
[2025-01-13 16:02:39 +0100] bence.gelei: validator improvements
[2025-01-13 14:35:16 +0100] bence.gelei: fix validator
[2025-01-10 16:43:17 +0100] bence.gelei: fill default values in request converter
[2025-01-10 12:13:03 +0100] bence.gelei: QoL
[2025-01-10 11:45:22 +0100] bence.gelei: QoL
[2025-01-10 11:40:45 +0100] bence.gelei: RequiredStringValidatorOption: ACCEPT_NON_EMPTY -> REJECT_EMPTY
[2025-01-09 16:06:47 +0100] bence.gelei: small optimization for if evaluations
[2025-01-09 16:00:50 +0100] bence.gelei: imports
[2025-01-09 15:58:23 +0100] bence.gelei: QoL and default value logic removed from required checking
[2025-01-09 15:16:20 +0100] bence.gelei: imports
[2025-01-09 14:51:12 +0100] bence.gelei: QoL and during mapped reference checking check if it's not in the payload instead of if it's null
[2025-01-09 13:57:28 +0100] bence.gelei: do not check required properties during reading default values
[2025-01-09 13:54:44 +0100] bence.gelei: QoL and do not load default value for containments
[2025-01-09 13:29:29 +0100] bence.gelei: QoL
[2025-01-09 13:24:06 +0100] bence.gelei: avoid using unnecessary lambdas
[2025-01-08 15:28:57 +0100] bence.gelei: JNG-6082 Initial feature commit
  • Loading branch information
bencegelei authored Jan 20, 2025
1 parent c60b40e commit dff27af
Show file tree
Hide file tree
Showing 13 changed files with 354 additions and 255 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
import org.eclipse.emf.ecore.resource.ResourceSet;

import java.util.*;
import java.util.function.Function;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkArgument;
Expand All @@ -47,8 +47,8 @@


/**
* Analyzing the inserted entities recursively and generating the required executable statements.
* The entities have be transfer objects which are mapped to other entities via aliases.
* Analyze the inserted entities recursively and generate the required executable statements.
* The entities must be transfer objects mapped to other entities through aliases.
*
* Rules:
* - The root type cannot have ID - because its is update
Expand All @@ -60,18 +60,18 @@ public class InsertPayloadDaoProcessor<ID> extends PayloadDaoProcessor<ID> {

private final AddReferencePayloadDaoProcessor<ID> addReferenceProcessor;

private final Function<EClass, Payload> defaultValuesProvider;
private final BiConsumer<EClass, Payload> defaultValuesApplier;

Metadata<ID> metadata;

public InsertPayloadDaoProcessor(ResourceSet resourceSet, IdentifierProvider<ID> identifierProvider,
QueryFactory queryFactory, InstanceCollector<ID> instanceCollector,
Function<EClass, Payload> defaultValuesProvider,
BiConsumer<EClass, Payload> defaultValuesApplier,
Metadata<ID> metadata) {
super(resourceSet, identifierProvider, queryFactory, instanceCollector);
addReferenceProcessor =
new AddReferencePayloadDaoProcessor<ID>(resourceSet, identifierProvider, queryFactory, instanceCollector);
this.defaultValuesProvider = defaultValuesProvider;
this.defaultValuesApplier = defaultValuesApplier;
this.metadata = metadata;
}

Expand All @@ -94,11 +94,7 @@ Collection<Statement<ID>> collectStatements(EClass mappedTransferObjectType,

checkArgument(getAsmUtils().isMappedTransferObjectType(mappedTransferObjectType), "Type have to be mapped transfer object");

// Set default values of transfer object type (that are missing from payload)
Payload defaults = defaultValuesProvider.apply(mappedTransferObjectType);
payload.putAll(defaults.entrySet().stream()
.filter(e -> !payload.containsKey(e.getKey()) && e.getValue() != null)
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())));
defaultValuesApplier.accept(mappedTransferObjectType, payload);

InsertStatement.InsertStatementBuilder<ID> currentStatementBuilder =
InsertStatement.<ID>buildInsertStatement()
Expand All @@ -123,9 +119,6 @@ Collection<Statement<ID>> collectStatements(EClass mappedTransferObjectType,
.map(defaultTransferObjectTypeName -> getAsmUtils().resolve(defaultTransferObjectTypeName).orElse(null))
.filter(t -> t instanceof EClass).map(t -> (EClass) t);

// Get default values of entity type
final Payload entityDefaults = defaultTransferObjectType.map(t -> defaultValuesProvider.apply(t)).orElse(Payload.empty());

// Processing attributes
attributes = mappedTransferObjectType.getEAllAttributes().stream()
.filter(
Expand Down Expand Up @@ -154,7 +147,6 @@ Collection<Statement<ID>> collectStatements(EClass mappedTransferObjectType,

checkForbiddenReferenceUpdates(references, payload);


// Add attributes (mapped name of attribute resolved here)
attributes.stream()
.collect(Collectors.toMap(
Expand Down Expand Up @@ -184,21 +176,27 @@ && getAsmUtils().getMappedReference(r).orElseThrow().isContainment()
)
);


// Add entity default attributes that are not mapped to transfer object type
defaultTransferObjectType.ifPresent(t -> t.getEAllAttributes().stream()
.filter(a -> entityDefaults.get(a.getName()) != null)
.collect(Collectors.toMap(
identity(),
a -> getAsmUtils().getMappedAttribute(a).orElse(a)))
.entrySet().stream()
.filter(e -> !mappedTransferObjectType.getEAllAttributes().stream().anyMatch(ta -> AsmUtils.equals(e.getValue(), getAsmUtils().getMappedAttribute(ta).orElse(null))))
.forEach(
a -> currentStatement.getInstance().addAttributeValue(
a.getValue(),
getTransferObjectValueAsEntityValueFromPayload(entityDefaults, a.getKey(), a.getValue()))
)
);
// Get default values of entity type
final Payload entityDefaults = Payload.empty();

boolean isDTOPresentAndDifferentThanMappedTO =
defaultTransferObjectType.isPresent() && !AsmUtils.equals(defaultTransferObjectType.get(), mappedTransferObjectType);
if (isDTOPresentAndDifferentThanMappedTO) {
defaultValuesApplier.accept(defaultTransferObjectType.get(), entityDefaults);

// Add entity default attributes that are not mapped to transfer object type
Map<EAttribute, EAttribute> dtoAttributeDefaults =
defaultTransferObjectType.get().getEAllAttributes().stream()
.filter(a -> entityDefaults.get(a.getName()) != null)
.collect(Collectors.toMap(identity(), a -> getAsmUtils().getMappedAttribute(a).orElse(a)));
for (Map.Entry<EAttribute, EAttribute> e : dtoAttributeDefaults.entrySet()) {
EAttribute dtoAttribute = e.getKey();
EAttribute mappedAttribute = e.getValue();
if (mappedTransferObjectType.getEAllAttributes().stream().noneMatch(ta -> AsmUtils.equals(mappedAttribute, getAsmUtils().getMappedAttribute(ta).orElse(null)))) {
currentStatement.getInstance().addAttributeValue(mappedAttribute, getTransferObjectValueAsEntityValueFromPayload(entityDefaults, dtoAttribute, mappedAttribute));
}
}
}

// Inserting all embedded reference
references.stream()
Expand Down Expand Up @@ -257,26 +255,28 @@ && getAsmUtils().getMappedReference(r).orElseThrow().isContainment()
);

// Add entity default references that are not mapped to transfer object type
defaultTransferObjectType.ifPresent(t -> t.getEAllReferences().stream()
.filter(r -> entityDefaults.get(r.getName()) != null)
.collect(Collectors.toMap(
identity(),
r -> getAsmUtils().getMappedReference(r).orElse(r)))
.entrySet().stream()
.filter(e -> !mappedTransferObjectType.getEAllReferences().stream().anyMatch(tr -> AsmUtils.equals(e.getValue(), getAsmUtils().getMappedReference(tr).orElse(null))))
.forEach(
r -> currentStatements.addAll(
addReferenceProcessor.addReference(
r.getValue(),
r.getKey().isMany()
? entityDefaults.getAsCollectionPayload(r.getKey().getName()).stream().map(p -> p.getAs(getIdentifierProvider().getType(), getIdentifierProvider().getName())).collect(Collectors.toSet())
: Collections.singleton(entityDefaults.getAsPayload(r.getKey().getName()).getAs(getIdentifierProvider().getType(), getIdentifierProvider().getName())),
currentStatement.getInstance().getIdentifier(),
true
)
)
)
);
if (isDTOPresentAndDifferentThanMappedTO) {
Map<EReference, EReference> dtoReferences =
defaultTransferObjectType.get().getEAllReferences().stream()
.filter(r -> entityDefaults.get(r.getName()) != null)
.collect(Collectors.toMap(identity(), r -> getAsmUtils().getMappedReference(r).orElse(r)));
for (Map.Entry<EReference, EReference> e : dtoReferences.entrySet()) {
EReference dtoReference = e.getKey();
EReference mappedReference = e.getValue();
if (mappedTransferObjectType.getEAllReferences().stream().noneMatch(tr -> AsmUtils.equals(mappedReference, getAsmUtils().getMappedReference(tr).orElse(null)))) {
Set<ID> ids;
if (dtoReference.isMany()) {
ids = entityDefaults.getAsCollectionPayload(dtoReference.getName()).stream()
.map(p -> p.getAs(getIdentifierProvider().getType(), getIdentifierProvider().getName()))
.collect(Collectors.toSet());
} else {
ids = Collections.singleton(entityDefaults.getAsPayload(dtoReference.getName())
.getAs(getIdentifierProvider().getType(), getIdentifierProvider().getName()));
}
currentStatements.addAll(addReferenceProcessor.addReference(mappedReference, ids, currentStatement.getInstance().getIdentifier(), true));
}
}
}

statements.addAll(currentStatements);
return ImmutableSet.copyOf(currentStatements);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.emf.ecore.resource.ResourceSet;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -67,14 +68,14 @@ public class UpdatePayloadDaoProcessor<ID> extends PayloadDaoProcessor<ID> {

public UpdatePayloadDaoProcessor(ResourceSet resourceSet, IdentifierProvider<ID> identifierProvider,
QueryFactory queryFactory, InstanceCollector<ID> instanceCollector,
Function<EClass, Payload> defaultValuesProvider,
BiConsumer<EClass, Payload> defaultValuesApplier,
Metadata<ID> metadata,
boolean optimisticLockEnabled) {
super(resourceSet, identifierProvider, queryFactory, instanceCollector);
this.metadata = metadata;
this.optimisticLockEnabled = optimisticLockEnabled;
insertPayloadDaoProcessor = new InsertPayloadDaoProcessor<ID>(resourceSet, identifierProvider,
queryFactory, instanceCollector, defaultValuesProvider, metadata);
queryFactory, instanceCollector, defaultValuesApplier, metadata);
deletePayloadDaoProcessor = new DeletePayloadDaoProcessor<ID>(resourceSet, identifierProvider,
queryFactory, instanceCollector);
addReferencePayloadDaoProcessor = new AddReferencePayloadDaoProcessor<ID>(resourceSet, identifierProvider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ public Payload getDefaultsOf(EClass clazz) {
}
}

@Override
public void applyDefaultsOf(EClass clazz, Payload payload) {
try (MetricsCancelToken ct = getMetricsCollector().start(METRICS_DAO_QUERY)) {
applyDeepDefaultsOf(clazz, payload);
logResult(payload);
}
}

@Override
public Collection<Payload> getRangeOf(EReference reference, Payload payload, QueryCustomizer<ID> queryCustomizer, boolean stateful) {
try (MetricsCancelToken ct = getMetricsCollector().start(METRICS_DAO_QUERY)) {
Expand Down Expand Up @@ -628,6 +636,8 @@ private boolean addStaticFeaturesToPayload(final Payload payload, final EClass c

protected abstract Payload readDefaultsOf(EClass clazz);

protected abstract void applyDeepDefaultsOf(EClass clazz, Payload payload);

protected abstract Collection<Payload> readRangeOf(EReference reference, Payload payload, QueryCustomizer<ID> queryCustomizer, boolean stateful);

protected abstract long calculateNumberRangeOf(EReference reference, Payload payload, QueryCustomizer<ID> queryCustomizer, boolean stateful);
Expand Down
Loading

0 comments on commit dff27af

Please sign in to comment.