@@ -0,0 +1,3673 @@
+package org.optaplanner.core.impl.score.stream;%0A%0Aimport static org.assertj.core.api.Assertions.assertThat;%0A%0Aimport java.util.Arrays;%0A%0Aimport org.junit.jupiter.api.Test;%0Aimport org.optaplanner.core.api.domain.entity.PlanningEntity;%0Aimport org.optaplanner.core.api.score.buildin.simple.SimpleScore;%0Aimport org.optaplanner.core.api.score.stream.Constraint;%0Aimport org.optaplanner.core.api.score.stream.ConstraintFactory;%0Aimport org.optaplanner.core.api.score.stream.ConstraintProvider;%0Aimport org.optaplanner.core.api.solver.Solver;%0Aimport org.optaplanner.core.api.solver.SolverFactory;%0Aimport org.optaplanner.core.config.constructionheuristic.ConstructionHeuristicPhaseConfig;%0Aimport org.optaplanner.core.config.solver.SolverConfig;%0Aimport org.optaplanner.core.impl.testdata.domain.chained.shadow.TestdataShadowingChainedAnchor;%0Aimport org.optaplanner.core.impl.testdata.domain.chained.shadow.TestdataShadowingChainedEntity;%0Aimport org.optaplanner.core.impl.testdata.domain.chained.shadow.TestdataShadowingChainedSolution;%0A%0Aclass FactChangePropagationTest %7B%0A%0A    private static final String VALUE_CODE = %22v1%22;%0A    private Solver%3CTestdataShadowingChainedSolution%3E solver = buildSolver();%0A%0A    /**%0A     * Tests if Drools try to modify a %7B@link PlanningEntity%7D before its shadow variables are updated.%0A     */%0A    @Test%0A    void delayedFactChangePropagation() %7B%0A        TestdataShadowingChainedEntity entity = new TestdataShadowingChainedEntity(%22e1%22);%0A        TestdataShadowingChainedAnchor value = new TestdataShadowingChainedAnchor(VALUE_CODE);%0A        TestdataShadowingChainedSolution inputProblem = new TestdataShadowingChainedSolution();%0A        inputProblem.setChainedAnchorList(Arrays.asList(value));%0A        inputProblem.setChainedEntityList(Arrays.asList(entity));%0A%0A        TestdataShadowingChainedSolution solution = solver.solve(inputProblem);%0A        TestdataShadowingChainedEntity solvedEntity = solution.getChainedEntityList().get(0);%0A        assertThat(solvedEntity.getChainedObject()).isNotNull();%0A        assertThat(solvedEntity.getAnchor().getCode()).isEqualTo(VALUE_CODE);%0A        assertThat(solution.getScore().isFeasible()).isTrue();%0A    %7D%0A%0A    private Solver%3CTestdataShadowingChainedSolution%3E buildSolver() %7B%0A        SolverConfig solverConfig = new SolverConfig()%0A                .withEntityClasses(TestdataShadowingChainedEntity.class)%0A                .withSolutionClass(TestdataShadowingChainedSolution.class)%0A                .withConstraintProviderClass(ChainedEntityConstraintProvider.class)%0A                .withPhases(new ConstructionHeuristicPhaseConfig());%0A%0A        SolverFactory%3CTestdataShadowingChainedSolution%3E solverFactory = SolverFactory.create(solverConfig);%0A        return solverFactory.buildSolver();%0A    %7D%0A%0A    public static class ChainedEntityConstraintProvider implements ConstraintProvider %7B%0A%0A        @Override%0A        public Constraint%5B%5D defineConstraints(ConstraintFactory constraintFactory) %7B%0A            return new Constraint%5B%5D %7B%0A                    anchorCannotBeNull(constraintFactory)%0A            %7D;%0A        %7D%0A%0A        private Constraint anchorCannotBeNull(ConstraintFactory constraintFactory) %7B%0A            return constraintFactory.from(TestdataShadowingChainedEntity.class)%0A                    /*%0A                     * The getCode() is here just to trigger NPE if the filter's predicate has been called before%0A                     * the AnchorVariableListener has updated the anchor.%0A                     */%0A                    .filter(testdataShadowingChainedEntity -%3E %22v1%22.equals(testdataShadowingChainedEntity.getAnchor().getCode()))%0A                    .penalize(%22anchorCannotBeNull%22, SimpleScore.ONE);%0A        %7D%0A    %7D%0A%7D%0A

Create FactChangePropagationTest