Skip to content

Commit

Permalink
[graph-system] Refactor AddAggregateGraphStateModificator
Browse files Browse the repository at this point in the history
  • Loading branch information
clickout committed Jul 19, 2023
1 parent 9f09dc2 commit dfbfba4
Show file tree
Hide file tree
Showing 11 changed files with 460 additions and 215 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ai.stapi.graphsystem.aggregategraphstatemodifier;

import ai.stapi.graph.Graph;
import ai.stapi.graph.graphelements.Node;
import ai.stapi.graph.inMemoryGraph.InMemoryGraphRepository;
import ai.stapi.graph.traversableGraphElements.TraversableNode;
import ai.stapi.graphoperations.graphLanguage.graphDescription.graphDescriptionBuilder.GraphDescriptionBuilder;
Expand Down Expand Up @@ -62,55 +63,56 @@ public GraphMappingResult modify(
var inputValue = command.getData().get(inputValueParameterName);
if (inputValue == null) {
return new GraphMappingResult(
new Graph(),
new Graph(new Node(command.getTargetIdentifier(), aggregateType)),
List.of()
);
}
var resourceStructureType = (ResourceStructureType) this.structureSchemaFinder.getStructureType(
aggregateType
);

var modificationPath = modificationDefinition.getModificationPath();
var splitPath = modificationPath.split("\\.");
var closestListNodePaths = this.findClosestListNodePaths(
resourceStructureType,
new String[] {aggregateType},
Arrays.copyOfRange(splitPath, 1, splitPath.length),
operationStructureType,
modificationDefinition
);
if (closestListNodePaths instanceof ErrorFindClosestListNodePathsOutput error) {
throw error.getError();
}
var successOutput = (HappyFindClosestListNodePathsOutput) closestListNodePaths;
var closestListPath = successOutput.getPathsAndTypes().toList().get(0);
var aggregateRepo = currentAggregateState.traversable();

var startIdParameterName = modificationDefinition.getStartIdParameterName();

TraversableNode traversingStartNode;
if (closestListPath.getPath().length <= 1) {
if (startIdParameterName == null) {
var aggregateId = command.getTargetIdentifier();
if (aggregateRepo.nodeExists(aggregateId, aggregateType)) {
traversingStartNode = aggregateRepo.loadNode(aggregateId, aggregateType);
} else {
traversingStartNode = new TraversableNode(aggregateId, aggregateType);
}
} else {
traversingStartNode = this.getTraversingStart(
command,
modificationDefinition,
operationStructureType,
closestListPath,
aggregateRepo
var startIdValue = command.getData().get(startIdParameterName);
if (!(startIdValue instanceof String stringStartId) ) {
throw CannotAddToAggregateState.becauseThereIsNoIdInCommandAtStartIdParameterName();
}
if (!stringStartId.contains("/")) {
throw CannotAddToAggregateState.becauseStartIdIsNotOfCorrectFormat(
stringStartId,
startIdParameterName,
modificationDefinition,
operationStructureType
);
}
var splitId = stringStartId.split("/");
if (splitId.length != 2) {
throw CannotAddToAggregateState.becauseStartIdIsNotOfCorrectFormat(
stringStartId,
startIdParameterName,
modificationDefinition,
operationStructureType
);
}
traversingStartNode = aggregateRepo.loadNode(
new UniqueIdentifier(splitId[0]),
splitId[1]
);
}

var modifiedNode = this.traverseToModifiedNode(
traversingStartNode,
Arrays.copyOfRange(
splitPath,
closestListPath.getPath().length,
splitPath.length
),
Arrays.stream(closestListPath.getPath()).toList(),
modificationPath.split("\\."),
List.of(),
operationStructureType,
modificationDefinition
);
Expand Down Expand Up @@ -168,8 +170,7 @@ public GraphMappingResult modify(
inputValueSchema.getParentDefinitionType()
)
);
var primitiveOgmBuilder = new GenericOGMBuilder()
.copyGraphMappingAsBuilder(primitiveOgm);
var primitiveOgmBuilder = new GenericOGMBuilder().copyGraphMappingAsBuilder(primitiveOgm);
dataField.setOgmBuilder(primitiveOgmBuilder);
}
}
Expand All @@ -190,80 +191,6 @@ public boolean supports(EventFactoryModification modificationDefinition) {
return modificationDefinition.getKind().equals(EventFactoryModification.ADD);
}

private FindClosestListNodePathsOutput findClosestListNodePaths(
ComplexStructureType currentStructure,
String[] lastPathToList,
String[] pathToTraverse,
ComplexStructureType operationDefinition,
EventFactoryModification modificationDefinition
) {
var currentLastPathToList = lastPathToList;
if (pathToTraverse.length < 2) {
return new HappyFindClosestListNodePathsOutput(
Stream.of(
new PathAndType(lastPathToList, currentStructure.getDefinitionType())
)
);
}
var fieldName = pathToTraverse[0];
var restOfPath = Arrays.copyOfRange(pathToTraverse, 1, pathToTraverse.length);
var fieldDefinition = currentStructure.getAllFields().get(fieldName);
if (fieldDefinition == null) {
return new ErrorFindClosestListNodePathsOutput(
CannotAddToAggregateState.becauseModificationPathContainsFieldNameNotPresentInSchema(
modificationDefinition,
operationDefinition
)
);
}
if (fieldDefinition.isList()) {
var wholePath = modificationDefinition.getModificationPath().split("\\.");
currentLastPathToList = Arrays.copyOfRange(
wholePath,
0,
wholePath.length - restOfPath.length
);
}
var finalCurrentLastPathToList = currentLastPathToList;
var typeResults = fieldDefinition.getTypes().stream().map(fieldType -> {
if (fieldType.isPrimitiveType()) {
return new ErrorFindClosestListNodePathsOutput(
CannotAddToAggregateState.becauseModificationPathContainsFieldNameWhichIsPrimitiveButItShouldNot(
modificationDefinition,
operationDefinition
)
);
}
var type = fieldType.getType();
var structureType = (ComplexStructureType) this.structureSchemaFinder.getStructureType(
type
);
return this.findClosestListNodePaths(
structureType,
finalCurrentLastPathToList,
restOfPath,
operationDefinition,
modificationDefinition
);
}).toList();
if (typeResults.stream().allMatch(ErrorFindClosestListNodePathsOutput.class::isInstance)) {
return new ErrorFindClosestListNodePathsOutput(
new CannotAddToAggregateState(
typeResults.stream()
.map(ErrorFindClosestListNodePathsOutput.class::cast)
.map(ErrorFindClosestListNodePathsOutput::getError)
.toList()
)
);
}
return new HappyFindClosestListNodePathsOutput(
typeResults.stream()
.filter(HappyFindClosestListNodePathsOutput.class::isInstance)
.map(HappyFindClosestListNodePathsOutput.class::cast)
.flatMap(HappyFindClosestListNodePathsOutput::getPathsAndTypes)
);
}

private TraversableNode traverseToModifiedNode(
TraversableNode currentNode,
String[] pathToTraverse,
Expand Down Expand Up @@ -300,108 +227,4 @@ private TraversableNode traverseToModifiedNode(
modificationDefinition
);
}

private TraversableNode getTraversingStart(
DynamicCommand command,
EventFactoryModification modificationDefinition,
ComplexStructureType operationStructureType,
PathAndType closestListPath,
InMemoryGraphRepository aggregateRepo
) {
var sourcePathOfId = String.format(
"%s.id",
String.join(".", closestListPath.getPath())
);
var idParametersWithSameSourcePath = operationStructureType.getAllFields()
.values()
.stream()
.map(FieldDefinitionWithSource.class::cast)
.filter(fieldDefinition -> fieldDefinition.getSource().equals(sourcePathOfId))
.toList();

if (idParametersWithSameSourcePath.isEmpty()) {
throw CannotAddToAggregateState.becauseThereAreIndistinguishableNodes(
modificationDefinition,
operationStructureType,
sourcePathOfId
);
}
if (idParametersWithSameSourcePath.size() > 1) {
throw CannotAddToAggregateState.becauseThereAreMoreWaysToDistinguisNodes(
modificationDefinition,
operationStructureType,
sourcePathOfId
);
}
var idParameter = idParametersWithSameSourcePath.get(0);
var idValue = command.getData().get(idParameter.getName());
if (!(idValue instanceof String stringIdValue)) {
throw new CannotAddToAggregateState(List.of());
}
var id = new UniqueIdentifier(stringIdValue);
if (aggregateRepo.nodeExists(id, closestListPath.getType())) {
return aggregateRepo.loadNode(id, closestListPath.getType());
} else {
throw CannotAddToAggregateState.becauseThereIsNoNodeWithIdSpecifiedAtSourcePath(
modificationDefinition,
operationStructureType,
String.join(".", closestListPath.getPath()),
id
);
}
}

private record ClosestJoinInfo(String nodeId, String nodeType, String fieldName) {

}

private interface FindClosestListNodePathsOutput {

}

private static class HappyFindClosestListNodePathsOutput implements FindClosestListNodePathsOutput {

private final Stream<PathAndType> pathAndTypes;

public HappyFindClosestListNodePathsOutput(Stream<PathAndType> pathAndTypes) {
this.pathAndTypes = pathAndTypes;
}

public Stream<PathAndType> getPathsAndTypes() {
return pathAndTypes;
}
}

private static class ErrorFindClosestListNodePathsOutput
implements FindClosestListNodePathsOutput {

private final CannotAddToAggregateState error;

public ErrorFindClosestListNodePathsOutput(CannotAddToAggregateState error) {
this.error = error;
}

public CannotAddToAggregateState getError() {
return error;
}
}

private static class PathAndType {

private final String[] path;
private final String type;

public PathAndType(String[] path, String type) {
this.path = path;
this.type = type;
}

public String[] getPath() {
return path;
}

public String getType() {
return type;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package ai.stapi.graphsystem.aggregategraphstatemodifier.exceptions;

import ai.stapi.identity.UniqueIdentifier;
import ai.stapi.graphsystem.aggregatedefinition.model.CommandHandlerDefinitionDTO.EventFactory.EventFactoryModification;
import ai.stapi.identity.UniqueIdentifier;
import ai.stapi.schema.structureSchema.ComplexStructureType;
import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -180,6 +180,53 @@ public static CannotAddToAggregateState becauseThereIsNoNodeWithIdSpecifiedAtSou
);
}

public static CannotAddToAggregateState becauseThereIsNoNodeWithIdSpecifiedAtStartIdParameterName(
EventFactoryModification modificationDefinition,
ComplexStructureType operationStructureType,
String sourcePathOfId,
UniqueIdentifier id,
String startIdParameterName
) {
return new CannotAddToAggregateState(
String.format(
"there is no node with id specified at start id parameter name.%n" +
"Operation name: '%s'%nNode path: '%s'%nId: '%s'%nModification kind: '%s'%n"
+ "Start id parameter name: '%s'",
operationStructureType.getDefinitionType(),
sourcePathOfId,
id.getId(),
modificationDefinition.getKind(),
startIdParameterName
)
);
}

public static CannotAddToAggregateState becauseThereIsNoSourcePathAtStartIdParameterName(
EventFactoryModification modificationDefinition,
ComplexStructureType operationStructureType,
UniqueIdentifier id,
String startIdParameterName
) {
return new CannotAddToAggregateState(
String.format(
"there is no node with source path specified at start id parameter name.%n" +
"Operation name: '%s'%nId: '%s'%nModification kind: '%s'%n"
+ "Start id parameter name: '%s'",
operationStructureType.getDefinitionType(),
id.getId(),
modificationDefinition.getKind(),
startIdParameterName
)
);
}

public static CannotAddToAggregateState becauseThereIsNoIdInCommandAtStartIdParameterName() {
return new CannotAddToAggregateState(
"there is no id in command at start id parameter name. " +
"Should not ever happen, bcs validator already should prevent this."
);
}

public static CannotAddToAggregateState becauseThereAreEdgesOnPathEvenThoughtThereShouldBeMaxOne(
EventFactoryModification modificationDefinition,
ComplexStructureType operationDefinition,
Expand Down Expand Up @@ -214,4 +261,23 @@ public static CannotAddToAggregateState becauseThereAreIsNodeEdgeOnPathEvenThoug
)
);
}

public static CannotAddToAggregateState becauseStartIdIsNotOfCorrectFormat(
String startIdValue,
String startIdParameterName,
EventFactoryModification modificationDefinition,
ComplexStructureType operationStructureType
) {
return new CannotAddToAggregateState(
String.format(
"start id found at start id parameter name is not of correct format (Id/Type).%n" +
"Operation name: '%s'%%nModification kind: '%s'%n"
+ "Start id parameter name: '%s' Start id value: %s",
operationStructureType.getDefinitionType(),
modificationDefinition.getKind(),
startIdParameterName,
startIdValue
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ default List<? extends AggregateGraphUpdatedEvent<? extends UniqueIdentifier>> p
AbstractCommand<? extends UniqueIdentifier> command,
Graph currentAggregateState
) {
return this.processCommand(command, currentAggregateState,
MissingFieldResolvingStrategy.STRICT);
return this.processCommand(
command,
currentAggregateState,
MissingFieldResolvingStrategy.STRICT
);
}

List<? extends AggregateGraphUpdatedEvent<? extends UniqueIdentifier>> processCommand(
Expand Down
Loading

0 comments on commit dfbfba4

Please sign in to comment.