Skip to content

Commit 41c117e

Browse files
authored
refactor: ScoreDirector is no longer public (#2129)
1 parent c4e2538 commit 41c117e

File tree

170 files changed

+1576
-1397
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

170 files changed

+1576
-1397
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package ai.timefold.solver.core.api.domain.common;
2+
3+
import ai.timefold.solver.core.api.solver.change.ProblemChange;
4+
import ai.timefold.solver.core.preview.api.move.Move;
5+
6+
import org.jspecify.annotations.Nullable;
7+
8+
/**
9+
* Allows to transfer an entity or fact instance (often from another {@link Thread})
10+
* to another working solution.
11+
*/
12+
public interface Lookup {
13+
14+
/**
15+
* Translates an entity or fact instance (often from another {@link Thread})
16+
* to another working solution.
17+
* Useful for {@link Move#rebase(Lookup) move rebasing}
18+
* and in a {@link ProblemChange} and for multi-threaded solving.
19+
* <p>
20+
* Matching uses {@link PlanningId}.
21+
*
22+
* @param problemFactOrPlanningEntity The fact or entity to rebase.
23+
* @return null if problemFactOrPlanningEntity is null
24+
* @throws IllegalArgumentException if there is no working object for the fact or entity,
25+
* if it cannot be looked up,
26+
* or if its class is not supported.
27+
* @throws IllegalStateException if it cannot be looked up
28+
* @param <T> the object type
29+
*/
30+
<T> @Nullable T lookUpWorkingObject(@Nullable T problemFactOrPlanningEntity);
31+
32+
}

core/src/main/java/ai/timefold/solver/core/api/domain/common/PlanningId.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@
1010
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
1111
import ai.timefold.solver.core.api.domain.solution.ProblemFactCollectionProperty;
1212
import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider;
13-
import ai.timefold.solver.core.api.score.director.ScoreDirector;
1413
import ai.timefold.solver.core.api.solver.change.ProblemChange;
1514
import ai.timefold.solver.core.preview.api.move.Move;
1615

1716
/**
1817
* Specifies that a bean property (or a field) is the id to match
19-
* when {@link ScoreDirector#lookUpWorkingObject(Object) locating}
18+
* when {@link Lookup#lookUpWorkingObject(Object) looking up}
2019
* an externalObject (often from another {@link Thread} or JVM).
2120
* Used during {@link Move} rebasing and in a {@link ProblemChange}.
2221
* <p>

core/src/main/java/ai/timefold/solver/core/api/domain/solution/PlanningEntityCollectionProperty.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@
1212
import java.util.SortedSet;
1313

1414
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
15-
import ai.timefold.solver.core.api.score.director.ScoreDirector;
1615

1716
/**
1817
* Specifies that a property (or a field) on a {@link PlanningSolution} class is a {@link Collection} of planning entities.
1918
* <p>
2019
* Every element in the planning entity collection should have the {@link PlanningEntity} annotation.
21-
* Every element in the planning entity collection will be added to the {@link ScoreDirector}.
20+
* Every element in the planning entity collection will be registered with the solver.
2221
* <p>
2322
* For solver reproducibility, the collection must have a deterministic, stable iteration order.
2423
* It is recommended to use a {@link List}, {@link LinkedHashSet} or {@link SortedSet}.

core/src/main/java/ai/timefold/solver/core/api/domain/solution/PlanningEntityProperty.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@
88
import java.lang.annotation.Target;
99

1010
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
11-
import ai.timefold.solver.core.api.score.director.ScoreDirector;
1211

1312
/**
1413
* Specifies that a property (or a field) on a {@link PlanningSolution} class is a planning entity.
1514
* <p>
1615
* The planning entity should have the {@link PlanningEntity} annotation.
17-
* The planning entity will be added to the {@link ScoreDirector}.
16+
* The planning entity will be registered with the solver.
1817
*/
1918
@Target({ METHOD, FIELD })
2019
@Retention(RUNTIME)

core/src/main/java/ai/timefold/solver/core/api/score/director/ScoreDirector.java

Lines changed: 0 additions & 74 deletions
This file was deleted.

core/src/main/java/ai/timefold/solver/core/api/solver/change/ProblemChangeDirector.java

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
package ai.timefold.solver.core.api.solver.change;
22

3-
import java.util.Optional;
43
import java.util.function.Consumer;
54

6-
import ai.timefold.solver.core.api.domain.common.PlanningId;
5+
import ai.timefold.solver.core.api.domain.common.Lookup;
76
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
87
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
98
import ai.timefold.solver.core.api.domain.variable.PlanningVariable;
109
import ai.timefold.solver.core.api.domain.variable.ShadowVariable;
1110

1211
import org.jspecify.annotations.NullMarked;
13-
import org.jspecify.annotations.Nullable;
1412

1513
/**
1614
* Allows external changes to the {@link PlanningSolution working solution}. If the changes are not applied through
@@ -19,9 +17,12 @@
1917
* never notified about them, resulting to inconsistencies in the {@link PlanningSolution working solution}.
2018
* Should be used only from a {@link ProblemChange} implementation.
2119
* To see an example implementation, please refer to the {@link ProblemChange} Javadoc.
20+
*
21+
* @see Lookup You may need to perform lookups of working objects from external objects.
2222
*/
2323
@NullMarked
24-
public interface ProblemChangeDirector {
24+
public interface ProblemChangeDirector
25+
extends Lookup {
2526

2627
/**
2728
* Add a new {@link PlanningEntity} instance into the {@link PlanningSolution working solution}.
@@ -35,7 +36,7 @@ public interface ProblemChangeDirector {
3536
/**
3637
* Remove an existing {@link PlanningEntity} instance from the {@link PlanningSolution working solution}.
3738
* Translates the entity to a working planning entity by performing a lookup as defined by
38-
* {@link #lookUpWorkingObjectOrFail(Object)}.
39+
* {@link #lookUpWorkingObject(Object)}.
3940
*
4041
* @param entity the {@link PlanningEntity} instance
4142
* @param entityConsumer removes the working entity from the {@link PlanningSolution working solution}
@@ -45,7 +46,7 @@ public interface ProblemChangeDirector {
4546

4647
/**
4748
* Change a {@link PlanningVariable} value of a {@link PlanningEntity}. Translates the entity to a working
48-
* planning entity by performing a lookup as defined by {@link #lookUpWorkingObjectOrFail(Object)}.
49+
* planning entity by performing a lookup as defined by {@link #lookUpWorkingObject(Object)}.
4950
*
5051
* @param entity the {@link PlanningEntity} instance
5152
* @param variableName name of the {@link PlanningVariable}
@@ -66,7 +67,7 @@ public interface ProblemChangeDirector {
6667

6768
/**
6869
* Remove an existing problem fact from the {@link PlanningSolution working solution}. Translates the problem fact
69-
* to a working problem fact by performing a lookup as defined by {@link #lookUpWorkingObjectOrFail(Object)}.
70+
* to a working problem fact by performing a lookup as defined by {@link #lookUpWorkingObject(Object)}.
7071
*
7172
* @param problemFact the problem fact instance
7273
* @param problemFactConsumer removes the working problem fact from the
@@ -78,7 +79,7 @@ public interface ProblemChangeDirector {
7879
/**
7980
* Change a property of either a {@link PlanningEntity} or a problem fact. Translates the entity or the problem fact
8081
* to its {@link PlanningSolution working solution} counterpart by performing a lookup as defined by
81-
* {@link #lookUpWorkingObjectOrFail(Object)}.
82+
* {@link #lookUpWorkingObject(Object)}.
8283
*
8384
* @param problemFactOrEntity the {@link PlanningEntity} or the problem fact instance
8485
* @param problemFactOrEntityConsumer updates the property of the {@link PlanningEntity}
@@ -88,32 +89,6 @@ public interface ProblemChangeDirector {
8889
<EntityOrProblemFact> void changeProblemProperty(EntityOrProblemFact problemFactOrEntity,
8990
Consumer<EntityOrProblemFact> problemFactOrEntityConsumer);
9091

91-
/**
92-
* Translate an entity or fact instance (often from another {@link Thread} or JVM)
93-
* to this {@link ProblemChangeDirector}'s internal working instance.
94-
* <p>
95-
* Matching uses {@link PlanningId}.
96-
*
97-
* @return null if externalObject is null
98-
* @throws IllegalArgumentException if there is no workingObject for externalObject, if it cannot be looked up
99-
* or if the externalObject's class is not supported
100-
* @throws IllegalStateException if it cannot be looked up
101-
* @param <EntityOrProblemFact> the object type
102-
*/
103-
<EntityOrProblemFact> @Nullable EntityOrProblemFact lookUpWorkingObjectOrFail(@Nullable EntityOrProblemFact externalObject);
104-
105-
/**
106-
* As defined by {@link #lookUpWorkingObjectOrFail(Object)},
107-
* but doesn't fail fast if no workingObject was ever added for the externalObject.
108-
* It's recommended to use {@link #lookUpWorkingObjectOrFail(Object)} instead.
109-
*
110-
* @return {@link Optional#empty()} if there is no workingObject for externalObject, or if externalObject is null
111-
* @throws IllegalArgumentException if it cannot be looked up or if the externalObject's class is not supported
112-
* @throws IllegalStateException if it cannot be looked up
113-
* @param <EntityOrProblemFact> the object type
114-
*/
115-
<EntityOrProblemFact> Optional<EntityOrProblemFact> lookUpWorkingObject(@Nullable EntityOrProblemFact externalObject);
116-
11792
/**
11893
* Calls variable listeners on the external changes submitted so far.
11994
*
Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,34 @@
11
package ai.timefold.solver.core.api.solver.phase;
22

3-
import java.util.function.BooleanSupplier;
4-
53
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
6-
import ai.timefold.solver.core.api.score.Score;
7-
import ai.timefold.solver.core.api.score.director.ScoreDirector;
84
import ai.timefold.solver.core.api.solver.Solver;
95
import ai.timefold.solver.core.api.solver.change.ProblemChange;
106
import ai.timefold.solver.core.impl.phase.Phase;
11-
import ai.timefold.solver.core.impl.score.director.InnerScoreDirector;
7+
import ai.timefold.solver.core.preview.api.move.Move;
128

139
import org.jspecify.annotations.NullMarked;
1410

1511
/**
1612
* Runs a custom algorithm as a {@link Phase} of the {@link Solver} that changes the planning variables.
17-
* To change problem facts, use {@link Solver#addProblemChange(ProblemChange)} instead.
18-
* <p>
19-
* To add custom properties, configure custom properties and add public setters for them.
13+
* To change problem facts and to add or remove entities, use {@link Solver#addProblemChange(ProblemChange)} instead.
2014
*
2115
* @param <Solution_> the solution type, the class with the {@link PlanningSolution} annotation
2216
*/
2317
@NullMarked
2418
public interface PhaseCommand<Solution_> {
2519

2620
/**
27-
* Changes {@link PlanningSolution working solution} of {@link ScoreDirector#getWorkingSolution()}.
28-
* When the {@link PlanningSolution working solution} is modified,
29-
* the {@link ScoreDirector} must be correctly notified
30-
* (through {@link ScoreDirector#beforeVariableChanged(Object, String)} and
31-
* {@link ScoreDirector#afterVariableChanged(Object, String)}),
32-
* otherwise calculated {@link Score}s will be corrupted.
21+
* Changes the current {@link PhaseCommandContext#getWorkingSolution() working solution}.
22+
* The solver is notified of the changes through {@link PhaseCommandContext},
23+
* specifically through {@link PhaseCommandContext#executeAndCalculateScore(Move)}.
24+
* Any other modifications to the working solution are strictly forbidden
25+
* and will likely cause the solver to be in an inconsistent state and throw an exception later on.
3326
* <p>
34-
* Don't forget to call {@link ScoreDirector#triggerVariableListeners()} after each set of changes
35-
* (especially before every {@link InnerScoreDirector#calculateScore()} call)
36-
* to ensure all shadow variables are updated.
27+
* Don't forget to check {@link PhaseCommandContext#isPhaseTerminated() termination status} frequently
28+
* to allow the solver to gracefully terminate when necessary.
3729
*
38-
* @param scoreDirector the {@link ScoreDirector} that needs to get notified of the changes.
39-
* @param isPhaseTerminated long-running command implementations should check this periodically
40-
* and terminate early if it returns true.
41-
* Otherwise the terminations configured by the user will have no effect,
42-
* as the solver can only terminate itself when a command has ended.
30+
* @param context the context of the command, providing access to the working solution and allowing move execution
4331
*/
44-
void changeWorkingSolution(ScoreDirector<Solution_> scoreDirector, BooleanSupplier isPhaseTerminated);
32+
void changeWorkingSolution(PhaseCommandContext<Solution_> context);
4533

4634
}

0 commit comments

Comments
 (0)