Skip to content

Commit b1a2c0b

Browse files
committed
refactor: remove all leftover deprecations
1 parent 6ca559f commit b1a2c0b

114 files changed

Lines changed: 1017 additions & 939 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package ai.timefold.solver.core.api.domain.common;
2+
3+
import ai.timefold.solver.core.api.solver.change.ProblemChange;
4+
5+
import org.jspecify.annotations.Nullable;
6+
7+
/**
8+
* Allows to transfer an entity or fact instance (often from another {@link Thread})
9+
* to another working solution.
10+
*/
11+
public interface Lookup {
12+
13+
/**
14+
* Translates an entity or fact instance (often from another {@link Thread})
15+
* to another working solution.
16+
* Useful for move rebasing and in a {@link ProblemChange} and for multi-threaded solving.
17+
* <p>
18+
* Matching uses {@link PlanningId}.
19+
*
20+
* @param problemFactOrPlanningEntity The fact or entity to rebase.
21+
* @return null if problemFactOrPlanningEntity is null
22+
* @throws IllegalArgumentException if there is no working object for the fact or entity,
23+
* if it cannot be looked up,
24+
* or if its class is not supported.
25+
* @throws IllegalStateException if it cannot be looked up
26+
* @param <T> the object type
27+
*/
28+
<T> @Nullable T lookUpWorkingObjectOrFail(@Nullable T problemFactOrPlanningEntity);
29+
30+
/**
31+
* As defined by {@link #lookUpWorkingObjectOrFail(Object)},
32+
* but doesn't fail fast if no workingObject was ever added for the externalObject.
33+
* It's recommended to use {@link #lookUpWorkingObjectOrFail(Object)} instead,
34+
* especially in move rebasing code.
35+
*
36+
* @return null if externalObject is null, or if there is no workingObject for externalObject
37+
* @throws IllegalArgumentException if it cannot be looked up or if the externalObject's class is not supported
38+
* @throws IllegalStateException if it cannot be looked up
39+
* @param <T> the object type
40+
*/
41+
<T> @Nullable T lookUpWorkingObject(@Nullable T externalObject);
42+
43+
}

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
@@ -12,11 +12,10 @@
1212
import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider;
1313
import ai.timefold.solver.core.api.solver.change.ProblemChange;
1414
import ai.timefold.solver.core.preview.api.move.Move;
15-
import ai.timefold.solver.core.preview.api.move.Rebaser;
1615

1716
/**
1817
* Specifies that a bean property (or a field) is the id to match
19-
* when {@link Rebaser#rebase(Object) locating}
18+
* when {@link Lookup#lookUpWorkingObjectOrFail(Object) locating}
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/PlanningEntityProperty.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Specifies that a property (or a field) on a {@link PlanningSolution} class is a planning entity.
1414
* <p>
1515
* The planning entity should have the {@link PlanningEntity} annotation.
16-
* The planning entity will be added registered with the solver.
16+
* The planning entity will be registered with the solver.
1717
*/
1818
@Target({ METHOD, FIELD })
1919
@Retention(RUNTIME)

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

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

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

5+
import ai.timefold.solver.core.api.domain.common.Lookup;
66
import ai.timefold.solver.core.api.domain.common.PlanningId;
77
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
88
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
@@ -21,7 +21,8 @@
2121
* To see an example implementation, please refer to the {@link ProblemChange} Javadoc.
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}.
@@ -100,19 +101,21 @@ <EntityOrProblemFact> void changeProblemProperty(EntityOrProblemFact problemFact
100101
* @throws IllegalStateException if it cannot be looked up
101102
* @param <EntityOrProblemFact> the object type
102103
*/
104+
@Override
103105
<EntityOrProblemFact> @Nullable EntityOrProblemFact lookUpWorkingObjectOrFail(@Nullable EntityOrProblemFact externalObject);
104106

105107
/**
106108
* As defined by {@link #lookUpWorkingObjectOrFail(Object)},
107109
* but doesn't fail fast if no workingObject was ever added for the externalObject.
108110
* It's recommended to use {@link #lookUpWorkingObjectOrFail(Object)} instead.
109111
*
110-
* @return {@link Optional#empty()} if there is no workingObject for externalObject, or if externalObject is null
112+
* @param <EntityOrProblemFact> the object type
113+
* @return null if there is no workingObject for externalObject, or if externalObject is null
111114
* @throws IllegalArgumentException if it cannot be looked up or if the externalObject's class is not supported
112115
* @throws IllegalStateException if it cannot be looked up
113-
* @param <EntityOrProblemFact> the object type
114116
*/
115-
<EntityOrProblemFact> Optional<EntityOrProblemFact> lookUpWorkingObject(@Nullable EntityOrProblemFact externalObject);
117+
@Override
118+
<EntityOrProblemFact> @Nullable EntityOrProblemFact lookUpWorkingObject(@Nullable EntityOrProblemFact externalObject);
116119

117120
/**
118121
* Calls variable listeners on the external changes submitted so far.

core/src/main/java/ai/timefold/solver/core/api/solver/phase/PhaseCommandContext.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
import java.util.function.Function;
44

5+
import ai.timefold.solver.core.api.domain.common.Lookup;
56
import ai.timefold.solver.core.preview.api.domain.metamodel.PlanningSolutionMetaModel;
67
import ai.timefold.solver.core.preview.api.move.Move;
7-
import ai.timefold.solver.core.preview.api.move.Rebaser;
88

99
import org.jspecify.annotations.NullMarked;
1010
import org.jspecify.annotations.Nullable;
@@ -17,7 +17,8 @@
1717
* @see PhaseCommand
1818
*/
1919
@NullMarked
20-
public interface PhaseCommandContext<Solution_> {
20+
public interface PhaseCommandContext<Solution_>
21+
extends Lookup {
2122

2223
/**
2324
* Returns the meta-model of the {@link #getWorkingSolution() working solution}.
@@ -90,9 +91,10 @@ default void execute(Move<Solution_> move) {
9091
<Result_> @Nullable Result_ executeTemporarily(Move<Solution_> move,
9192
Function<Solution_, @Nullable Result_> temporarySolutionConsumer, boolean guaranteeFreshScore);
9293

93-
/**
94-
* As defined by {@link Rebaser#rebase(Object)}, but for the working solution of this context.
95-
*/
96-
<T> @Nullable T lookupWorkingObject(@Nullable T original);
94+
@Override
95+
<T> @Nullable T lookUpWorkingObject(@Nullable T problemFactOrPlanningEntity);
96+
97+
@Override
98+
<T> @Nullable T lookUpWorkingObjectOrFail(@Nullable T problemFactOrPlanningEntity);
9799

98100
}

core/src/main/java/ai/timefold/solver/core/impl/domain/lookup/ImmutableLookUpStrategy.java renamed to core/src/main/java/ai/timefold/solver/core/impl/domain/common/ImmutableLookupStrategy.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
package ai.timefold.solver.core.impl.domain.lookup;
1+
package ai.timefold.solver.core.impl.domain.common;
22

33
import java.util.Map;
44

55
import org.jspecify.annotations.NullMarked;
66

77
@NullMarked
8-
final class ImmutableLookUpStrategy implements LookUpStrategy {
8+
final class ImmutableLookupStrategy implements LookupStrategy {
99

1010
@Override
1111
public void addWorkingObject(Map<Object, Object> idToWorkingObjectMap, Object workingObject) {

core/src/main/java/ai/timefold/solver/core/impl/domain/lookup/LookUpStrategyType.java renamed to core/src/main/java/ai/timefold/solver/core/impl/domain/common/LookUpStrategyType.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
package ai.timefold.solver.core.impl.domain.lookup;
1+
package ai.timefold.solver.core.impl.domain.common;
22

33
import ai.timefold.solver.core.api.domain.common.PlanningId;
44
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
55
import ai.timefold.solver.core.api.domain.solution.ProblemFactCollectionProperty;
66
import ai.timefold.solver.core.impl.score.director.ScoreDirector;
77

88
/**
9-
* Determines how {@link ScoreDirector#lookUpWorkingObject(Object)} maps
9+
* Determines how {@link ScoreDirector#lookUpWorkingObjectOrFail(Object)} maps
1010
* a {@link ProblemFactCollectionProperty problem fact} or a {@link PlanningEntity planning entity}
1111
* from an external copy to the internal one.
1212
*/
@@ -15,7 +15,7 @@ enum LookUpStrategyType {
1515
/**
1616
* Map by the same {@link PlanningId} field or method.
1717
* If there is no such field or method,
18-
* there is no mapping and {@link ScoreDirector#lookUpWorkingObject(Object)} must not be used.
18+
* there is no mapping and {@link ScoreDirector#lookUpWorkingObjectOrFail(Object)} must not be used.
1919
* If there is such a field or method, but it returns null, it fails fast.
2020
* <p>
2121
* This is the default.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package ai.timefold.solver.core.impl.domain.common;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
import ai.timefold.solver.core.api.domain.common.Lookup;
7+
import ai.timefold.solver.core.api.domain.common.PlanningId;
8+
9+
import org.jspecify.annotations.NullMarked;
10+
import org.jspecify.annotations.Nullable;
11+
12+
/**
13+
* @see PlanningId
14+
* @see Lookup
15+
*/
16+
@NullMarked
17+
public final class LookupManager
18+
implements Lookup {
19+
20+
private final LookupStrategyResolver lookupStrategyResolver;
21+
private final Map<Object, Object> idToWorkingObjectMap = new HashMap<>();
22+
23+
public LookupManager(LookupStrategyResolver lookupStrategyResolver) {
24+
this.lookupStrategyResolver = lookupStrategyResolver;
25+
}
26+
27+
public void reset() {
28+
idToWorkingObjectMap.clear();
29+
}
30+
31+
public void addWorkingObject(Object workingObject) {
32+
var lookupStrategy = lookupStrategyResolver.determineLookUpStrategy(workingObject);
33+
lookupStrategy.addWorkingObject(idToWorkingObjectMap, workingObject);
34+
}
35+
36+
public void removeWorkingObject(Object workingObject) {
37+
var lookupStrategy = lookupStrategyResolver.determineLookUpStrategy(workingObject);
38+
lookupStrategy.removeWorkingObject(idToWorkingObjectMap, workingObject);
39+
}
40+
41+
@Override
42+
public <E> @Nullable E lookUpWorkingObjectOrFail(@Nullable E externalObject) {
43+
if (externalObject == null) {
44+
return null;
45+
}
46+
var lookupStrategy = lookupStrategyResolver.determineLookUpStrategy(externalObject);
47+
return lookupStrategy.lookUpWorkingObject(idToWorkingObjectMap, externalObject);
48+
}
49+
50+
@Override
51+
public <E> @Nullable E lookUpWorkingObject(@Nullable E externalObject) {
52+
if (externalObject == null) {
53+
return null;
54+
}
55+
var lookupStrategy = lookupStrategyResolver.determineLookUpStrategy(externalObject);
56+
return lookupStrategy.lookUpWorkingObjectIfExists(idToWorkingObjectMap, externalObject);
57+
}
58+
59+
}

core/src/main/java/ai/timefold/solver/core/impl/domain/lookup/LookUpStrategy.java renamed to core/src/main/java/ai/timefold/solver/core/impl/domain/common/LookupStrategy.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
package ai.timefold.solver.core.impl.domain.lookup;
1+
package ai.timefold.solver.core.impl.domain.common;
22

33
import java.util.Map;
44

55
import org.jspecify.annotations.NullMarked;
66
import org.jspecify.annotations.Nullable;
77

88
@NullMarked
9-
public sealed interface LookUpStrategy
10-
permits ImmutableLookUpStrategy, NoneLookUpStrategy, PlanningIdLookUpStrategy {
9+
public sealed interface LookupStrategy
10+
permits ImmutableLookupStrategy, NoneLookupStrategy, PlanningIdLookupStrategy {
1111

1212
void addWorkingObject(Map<Object, Object> idToWorkingObjectMap, Object workingObject);
1313

core/src/main/java/ai/timefold/solver/core/impl/domain/lookup/LookUpStrategyResolver.java renamed to core/src/main/java/ai/timefold/solver/core/impl/domain/common/LookupStrategyResolver.java

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
package ai.timefold.solver.core.impl.domain.lookup;
1+
package ai.timefold.solver.core.impl.domain.common;
22

33
import java.util.Map;
44
import java.util.concurrent.ConcurrentHashMap;
55

66
import ai.timefold.solver.core.api.domain.common.PlanningId;
77
import ai.timefold.solver.core.config.util.ConfigUtils;
8-
import ai.timefold.solver.core.impl.domain.common.DomainAccessType;
98
import ai.timefold.solver.core.impl.domain.common.accessor.MemberAccessorFactory;
109
import ai.timefold.solver.core.impl.domain.policy.DescriptorPolicy;
1110
import ai.timefold.solver.core.impl.domain.solution.cloner.DeepCloningUtils;
@@ -16,18 +15,18 @@
1615
* This class is thread-safe.
1716
*/
1817
@NullMarked
19-
public final class LookUpStrategyResolver {
18+
public final class LookupStrategyResolver {
2019

2120
private final LookUpStrategyType lookUpStrategyType;
2221
private final DomainAccessType domainAccessType;
2322
private final MemberAccessorFactory memberAccessorFactory;
24-
private final Map<Class<?>, LookUpStrategy> decisionCache = new ConcurrentHashMap<>();
23+
private final Map<Class<?>, LookupStrategy> decisionCache = new ConcurrentHashMap<>();
2524

26-
public LookUpStrategyResolver(DescriptorPolicy descriptorPolicy) {
25+
public LookupStrategyResolver(DescriptorPolicy descriptorPolicy) {
2726
this(descriptorPolicy, LookUpStrategyType.PLANNING_ID_OR_NONE);
2827
}
2928

30-
LookUpStrategyResolver(DescriptorPolicy descriptorPolicy, LookUpStrategyType lookUpStrategyType) {
29+
LookupStrategyResolver(DescriptorPolicy descriptorPolicy, LookUpStrategyType lookUpStrategyType) {
3130
this.lookUpStrategyType = lookUpStrategyType;
3231
this.domainAccessType = descriptorPolicy.getDomainAccessType();
3332
this.memberAccessorFactory = descriptorPolicy.getMemberAccessorFactory();
@@ -41,22 +40,22 @@ public LookUpStrategyResolver(DescriptorPolicy descriptorPolicy) {
4140
* @param object never null
4241
* @return never null
4342
*/
44-
public LookUpStrategy determineLookUpStrategy(Object object) {
43+
public LookupStrategy determineLookUpStrategy(Object object) {
4544
var objectClass = object.getClass();
4645
var decision = decisionCache.get(objectClass);
4746
if (decision == null) { // Simulate computeIfAbsent, avoiding creating a lambda on the hot path.
4847
if (DeepCloningUtils.isImmutable(objectClass)) {
49-
decision = new ImmutableLookUpStrategy();
48+
decision = new ImmutableLookupStrategy();
5049
} else {
5150
decision = switch (lookUpStrategyType) {
52-
case NONE -> new NoneLookUpStrategy();
51+
case NONE -> new NoneLookupStrategy();
5352
case PLANNING_ID_OR_NONE -> {
5453
var memberAccessor =
5554
ConfigUtils.findPlanningIdMemberAccessor(objectClass, memberAccessorFactory, domainAccessType);
5655
if (memberAccessor == null) {
57-
yield new NoneLookUpStrategy();
56+
yield new NoneLookupStrategy();
5857
}
59-
yield new PlanningIdLookUpStrategy(memberAccessor);
58+
yield new PlanningIdLookupStrategy(memberAccessor);
6059
}
6160
case PLANNING_ID_OR_FAIL_FAST -> {
6261
var memberAccessor =
@@ -68,7 +67,7 @@ The class (%s) does not have a @%s annotation, but the lookUpStrategyType (%s) r
6867
.formatted(objectClass, PlanningId.class.getSimpleName(), lookUpStrategyType,
6968
PlanningId.class.getSimpleName()));
7069
}
71-
yield new PlanningIdLookUpStrategy(memberAccessor);
70+
yield new PlanningIdLookupStrategy(memberAccessor);
7271
}
7372
};
7473
decisionCache.put(objectClass, decision);

0 commit comments

Comments
 (0)