Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added checkpointevents for subrecipes in compiler. #1767

Merged
merged 8 commits into from
Oct 1, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,14 @@ object RecipeCompiler {
isReprovider = i.isReprovider,
oldName = Option(i.originalName)
)
recipe.interactions.map(copyInteraction).toSet ++ recipe.sieves.map(convertSieveToInteraction) ++ recipe.subRecipes.flatMap(flattenSubRecipesToInteraction)
recipe.interactions.map(copyInteraction).toSet ++
recipe.sieves.map(convertSieveToInteraction) ++
recipe.subRecipes.flatMap(flattenSubRecipesToInteraction) ++
jwalgemoed marked this conversation as resolved.
Show resolved Hide resolved
recipe.checkpointEvents.map(convertCheckpointEventToInteraction)
}

def flattenSensoryEvents(recipe: Recipe): Set[com.ing.baker.recipe.common.Event] = {
recipe.sensoryEvents ++ recipe.subRecipes.flatMap(flattenSensoryEvents)
}

val precompileErrors: Seq[String] = Assertions.preCompileAssertions(recipe)
Expand All @@ -236,9 +243,12 @@ object RecipeCompiler {
recipe.subRecipes.flatMap(flattenSubRecipesToInteraction) ++
recipe.sieves.map(convertSieveToInteraction)

// Flatten all sensory events from sub recipes
val sensoryEvents = flattenSensoryEvents(recipe)

//All ingredient names provided by sensory events or by interactions
val allIngredientNames: Set[String] =
(recipe.sensoryEvents ++ recipe.subRecipes.flatMap(_.sensoryEvents)).flatMap(e => e.providedIngredients.map(i => i.name)) ++
(sensoryEvents).flatMap(e => e.providedIngredients.map(i => i.name)) ++
jwalgemoed marked this conversation as resolved.
Show resolved Hide resolved
actionDescriptors.flatMap(i => i.output.flatMap { e =>
// check if the event was renamed (check if there is a transformer for this event)
i.eventOutputTransformers.get(e) match {
Expand All @@ -255,7 +265,7 @@ object RecipeCompiler {
val allInteractionTransitions: Seq[InteractionTransition] = interactionTransitions

// events provided from outside
val sensoryEventTransitions: Seq[EventTransition] = (recipe.sensoryEvents ++ recipe.subRecipes.flatMap(_.sensoryEvents)).map {
val sensoryEventTransitions: Seq[EventTransition] = (sensoryEvents).map {
jwalgemoed marked this conversation as resolved.
Show resolved Hide resolved
event => EventTransition(eventToCompiledEvent(event), isSensoryEvent = true, event.maxFiringLimit)
}.toIndexedSeq

Expand Down
54 changes: 39 additions & 15 deletions core/recipe-compiler/src/test/java/RecipeCompilerTests.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import com.ing.baker.compiler.RecipeCompiler;
import com.ing.baker.il.CompiledRecipe;
import com.ing.baker.il.RecipeVisualStyle;
import com.ing.baker.il.RecipeVisualStyle$;
import com.ing.baker.il.RecipeVisualizer;
import com.ing.baker.il.EventDescriptor;
import com.ing.baker.il.petrinet.InteractionTransition;
import com.ing.baker.recipe.annotations.FiresEvent;
import com.ing.baker.recipe.annotations.RequiresIngredient;
import com.ing.baker.recipe.javadsl.CheckPointEvent;
import com.ing.baker.recipe.javadsl.Interaction;
import com.ing.baker.recipe.javadsl.InteractionDescriptor;
import com.ing.baker.il.petrinet.InteractionTransition;
import com.ing.baker.recipe.javadsl.Recipe;

import com.ing.baker.recipe.javadsl.CheckPointEvent;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class RecipeCompilerTests {
Expand Down Expand Up @@ -58,7 +55,7 @@ public ItemsReserved(List<String> reservedItems) {
}
}

@FiresEvent(oneOf = { ItemsReserved.class, OrderHadUnavailableItems.class })
@FiresEvent(oneOf = {ItemsReserved.class, OrderHadUnavailableItems.class})
ReserveItemsOutcome apply(
@RequiresIngredient("orderId") String id,
@RequiresIngredient("items") List<String> items
Expand Down Expand Up @@ -88,7 +85,7 @@ public ItemsReserved(List<String> reservedItems) {
}
}

@FiresEvent(oneOf = { ItemsReserved.class, OrderHadUnavailableItems.class })
@FiresEvent(oneOf = {ItemsReserved.class, OrderHadUnavailableItems.class})
ReserveItemsOutcome apply(
@RequiresIngredient("orderId") String id,
@RequiresIngredient("items") List<String> items
Expand All @@ -99,7 +96,7 @@ interface ReserveItemsOutcome {
}

@Test
public void shouldCompileSimpleRecipe(){
public void shouldCompileSimpleRecipe() {
Recipe recipe = new Recipe("recipe")
.withSensoryEvents(EventA.class);
CompiledRecipe compiled = RecipeCompiler.compileRecipe(recipe);
Expand All @@ -109,7 +106,7 @@ public void shouldCompileSimpleRecipe(){
}

@Test
public void shouldCompileSimpleRecipeWithInteraction(){
public void shouldCompileSimpleRecipeWithInteraction() {

Recipe recipe = new Recipe("recipe")
.withSensoryEvents(EventA.class)
Expand Down Expand Up @@ -163,31 +160,58 @@ public void shouldAddInteractionsForCheckpointEvents() {

}

class SubSubSubEvent {
}

class SubSubEvent {
}

class SubEvent {
}

class Event {
}

@Test
public void shouldAddSubRecipe() {
// Several layers deep to verify if everything propagates correctly
Recipe subSubSubRecipe = new Recipe("subSubSubRecipe")
.withSensoryEvent(SubSubSubEvent.class)
.withCheckpointEvent(new CheckPointEvent("subSubSubCheckpointEvent"))
.withInteraction(InteractionDescriptor.of(InteractionA.class));

Recipe subSubRecipe = new Recipe("SubSubRecipe")
.withSensoryEvent(SubSubEvent.class)
.withSubRecipe(subSubSubRecipe)
.withCheckpointEvent(new CheckPointEvent("subSubCheckpointEvent"))
.withInteraction(InteractionDescriptor.of(InteractionB.class));

Recipe subRecipe = new Recipe("SubRecipe")
.withSensoryEvent(SubEvent.class)
.withSubRecipe(subSubRecipe)
.withCheckpointEvent(new CheckPointEvent("subCheckpointEvent"))
.withInteraction(InteractionDescriptor.of(InteractionA.class));


Recipe recipe = new Recipe("recipe")
.withSensoryEvents(EventB.class, EventC.class)
.withSubRecipe(subRecipe);
.withSensoryEvent(Event.class)
.withSubRecipe(subRecipe)
.withCheckpointEvent(new CheckPointEvent("checkpointEvent"));


CompiledRecipe compiled = RecipeCompiler.compileRecipe(recipe);

Object actualSensoryEvents = convertList(compiled.sensoryEvents()).stream().map(i -> ((EventDescriptor) i).name()).collect(Collectors.toUnmodifiableList());
List<String> expectedSensoryEvents = java.util.List.of("SubSubEvent", "SubEvent", "SubSubSubEvent", "Event");

Assertions.assertEquals(expectedSensoryEvents, actualSensoryEvents);

Object actual = convertList(compiled.petriNet().transitions())
.stream()
.filter(InteractionTransition.class::isInstance)
.map(i -> ((InteractionTransition) i).interactionName())
.collect(Collectors.toUnmodifiableList());

List<String> expected = java.util.List.of("$SubRecipe$SubRecipe$InteractionA", "$SubRecipe$SubSubRecipe$InteractionB");
List<String> expected = java.util.List.of("$CheckpointEventInteraction$subSubSubCheckpointEvent", "$SubRecipe$SubRecipe$InteractionA", "$CheckpointEventInteraction$subSubCheckpointEvent", "$CheckpointEventInteraction$subCheckpointEvent", "$CheckpointEventInteraction$checkpointEvent", "$SubRecipe$subSubSubRecipe$InteractionA", "$SubRecipe$SubSubRecipe$InteractionB");

Assertions.assertEquals(expected, actual);
}
Expand Down