Skip to content

Commit ba91d53

Browse files
committed
refactor: hide domain lookups
1 parent 69d25fb commit ba91d53

75 files changed

Lines changed: 215 additions & 416 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.

core/src/main/java/ai/timefold/solver/core/api/domain/lookup/PlanningId.java renamed to core/src/main/java/ai/timefold/solver/core/api/domain/entity/PlanningId.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package ai.timefold.solver.core.api.domain.lookup;
1+
package ai.timefold.solver.core.api.domain.entity;
22

33
import static java.lang.annotation.ElementType.FIELD;
44
import static java.lang.annotation.ElementType.METHOD;
@@ -7,7 +7,6 @@
77
import java.lang.annotation.Retention;
88
import java.lang.annotation.Target;
99

10-
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
1110
import ai.timefold.solver.core.api.domain.solution.ProblemFactCollectionProperty;
1211
import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider;
1312
import ai.timefold.solver.core.api.score.director.ScoreDirector;

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
import java.lang.annotation.Target;
88

99
import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType;
10-
import ai.timefold.solver.core.api.domain.lookup.LookUpStrategyType;
11-
import ai.timefold.solver.core.api.domain.lookup.PlanningId;
1210
import ai.timefold.solver.core.api.domain.solution.cloner.SolutionCloner;
1311
import ai.timefold.solver.core.api.score.stream.ConstraintProvider;
1412

@@ -73,11 +71,4 @@
7371
interface NullSolutionCloner extends SolutionCloner {
7472
}
7573

76-
/**
77-
* @deprecated When multi-threaded solving, ensure your domain classes use {@link PlanningId} instead.
78-
*/
79-
@Deprecated(forRemoval = true, since = "1.10.0")
80-
@NonNull
81-
LookUpStrategyType lookUpStrategyType() default LookUpStrategyType.PLANNING_ID_OR_NONE;
82-
8374
}

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

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

3-
import ai.timefold.solver.core.api.domain.lookup.LookUpStrategyType;
4-
import ai.timefold.solver.core.api.domain.lookup.PlanningId;
3+
import ai.timefold.solver.core.api.domain.entity.PlanningId;
54
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
65
import ai.timefold.solver.core.api.score.Score;
76
import ai.timefold.solver.core.api.solver.change.ProblemChange;
@@ -139,8 +138,7 @@ default void afterProblemFactRemoved(Object problemFact) {
139138
* to this {@link ScoreDirector}'s internal working instance.
140139
* Useful for move rebasing and in a {@link ProblemChange}.
141140
* <p>
142-
* Matching is determined by the {@link LookUpStrategyType} on {@link PlanningSolution}.
143-
* Matching uses a {@link PlanningId} by default.
141+
* Matching uses {@link PlanningId}.
144142
*
145143
* @return null if externalObject is null
146144
* @throws IllegalArgumentException if there is no workingObject for externalObject, if it cannot be looked up
@@ -156,7 +154,7 @@ default void afterProblemFactRemoved(Object problemFact) {
156154
* It's recommended to use {@link #lookUpWorkingObject(Object)} instead,
157155
* especially in move rebasing code.
158156
*
159-
* @return null if externalObject is null or if there is no workingObject for externalObject
157+
* @return null if externalObject is null, or if there is no workingObject for externalObject
160158
* @throws IllegalArgumentException if it cannot be looked up or if the externalObject's class is not supported
161159
* @throws IllegalStateException if it cannot be looked up
162160
* @param <E> the object type

core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import java.util.function.Predicate;
66

77
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
8-
import ai.timefold.solver.core.api.domain.lookup.PlanningId;
8+
import ai.timefold.solver.core.api.domain.entity.PlanningId;
99
import ai.timefold.solver.core.api.domain.solution.ProblemFactCollectionProperty;
1010
import ai.timefold.solver.core.api.domain.variable.InverseRelationShadowVariable;
1111
import ai.timefold.solver.core.api.domain.variable.PlanningListVariable;

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

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@
44
import java.util.function.Consumer;
55

66
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
7-
import ai.timefold.solver.core.api.domain.lookup.LookUpStrategyType;
8-
import ai.timefold.solver.core.api.domain.lookup.PlanningId;
7+
import ai.timefold.solver.core.api.domain.entity.PlanningId;
98
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
109
import ai.timefold.solver.core.api.domain.variable.PlanningVariable;
1110
import ai.timefold.solver.core.api.domain.variable.ShadowVariable;
1211

13-
import org.jspecify.annotations.NonNull;
12+
import org.jspecify.annotations.NullMarked;
1413
import org.jspecify.annotations.Nullable;
1514

1615
/**
@@ -21,6 +20,7 @@
2120
* Should be used only from a {@link ProblemChange} implementation.
2221
* To see an example implementation, please refer to the {@link ProblemChange} Javadoc.
2322
*/
23+
@NullMarked
2424
public interface ProblemChangeDirector {
2525

2626
/**
@@ -30,7 +30,7 @@ public interface ProblemChangeDirector {
3030
* @param entityConsumer adds the entity to the {@link PlanningSolution working solution}
3131
* @param <Entity> the planning entity object type
3232
*/
33-
<Entity> void addEntity(@NonNull Entity entity, @NonNull Consumer<Entity> entityConsumer);
33+
<Entity> void addEntity(Entity entity, Consumer<Entity> entityConsumer);
3434

3535
/**
3636
* Remove an existing {@link PlanningEntity} instance from the {@link PlanningSolution working solution}.
@@ -41,7 +41,7 @@ public interface ProblemChangeDirector {
4141
* @param entityConsumer removes the working entity from the {@link PlanningSolution working solution}
4242
* @param <Entity> the planning entity object type
4343
*/
44-
<Entity> void removeEntity(@NonNull Entity entity, @NonNull Consumer<Entity> entityConsumer);
44+
<Entity> void removeEntity(Entity entity, Consumer<Entity> entityConsumer);
4545

4646
/**
4747
* Change a {@link PlanningVariable} value of a {@link PlanningEntity}. Translates the entity to a working
@@ -52,8 +52,7 @@ public interface ProblemChangeDirector {
5252
* @param entityConsumer updates the value of the {@link PlanningVariable} inside the {@link PlanningEntity}
5353
* @param <Entity> the planning entity object type
5454
*/
55-
<Entity> void changeVariable(@NonNull Entity entity, @NonNull String variableName,
56-
@NonNull Consumer<Entity> entityConsumer);
55+
<Entity> void changeVariable(Entity entity, String variableName, Consumer<Entity> entityConsumer);
5756

5857
/**
5958
* Add a new problem fact into the {@link PlanningSolution working solution}.
@@ -63,7 +62,7 @@ <Entity> void changeVariable(@NonNull Entity entity, @NonNull String variableNam
6362
* {@link PlanningSolution working solution}
6463
* @param <ProblemFact> the problem fact object type
6564
*/
66-
<ProblemFact> void addProblemFact(@NonNull ProblemFact problemFact, @NonNull Consumer<ProblemFact> problemFactConsumer);
65+
<ProblemFact> void addProblemFact(ProblemFact problemFact, Consumer<ProblemFact> problemFactConsumer);
6766

6867
/**
6968
* Remove an existing problem fact from the {@link PlanningSolution working solution}. Translates the problem fact
@@ -74,7 +73,7 @@ <Entity> void changeVariable(@NonNull Entity entity, @NonNull String variableNam
7473
* {@link PlanningSolution working solution}
7574
* @param <ProblemFact> the problem fact object type
7675
*/
77-
<ProblemFact> void removeProblemFact(@NonNull ProblemFact problemFact, @NonNull Consumer<ProblemFact> problemFactConsumer);
76+
<ProblemFact> void removeProblemFact(ProblemFact problemFact, Consumer<ProblemFact> problemFactConsumer);
7877

7978
/**
8079
* Change a property of either a {@link PlanningEntity} or a problem fact. Translates the entity or the problem fact
@@ -86,15 +85,14 @@ <Entity> void changeVariable(@NonNull Entity entity, @NonNull String variableNam
8685
* or the problem fact
8786
* @param <EntityOrProblemFact> the planning entity or problem fact object type
8887
*/
89-
<EntityOrProblemFact> void changeProblemProperty(@NonNull EntityOrProblemFact problemFactOrEntity,
90-
@NonNull Consumer<EntityOrProblemFact> problemFactOrEntityConsumer);
88+
<EntityOrProblemFact> void changeProblemProperty(EntityOrProblemFact problemFactOrEntity,
89+
Consumer<EntityOrProblemFact> problemFactOrEntityConsumer);
9190

9291
/**
9392
* Translate an entity or fact instance (often from another {@link Thread} or JVM)
9493
* to this {@link ProblemChangeDirector}'s internal working instance.
9594
* <p>
96-
* Matching is determined by the {@link LookUpStrategyType} on {@link PlanningSolution}.
97-
* Matching uses a {@link PlanningId} by default.
95+
* Matching uses {@link PlanningId}.
9896
*
9997
* @return null if externalObject is null
10098
* @throws IllegalArgumentException if there is no workingObject for externalObject, if it cannot be looked up
@@ -109,7 +107,7 @@ <EntityOrProblemFact> void changeProblemProperty(@NonNull EntityOrProblemFact pr
109107
* but doesn't fail fast if no workingObject was ever added for the externalObject.
110108
* It's recommended to use {@link #lookUpWorkingObjectOrFail(Object)} instead.
111109
*
112-
* @return {@link Optional#empty()} if externalObject is null or if there is no workingObject for externalObject
110+
* @return {@link Optional#empty()} if there is no workingObject for externalObject, or if externalObject is null
113111
* @throws IllegalArgumentException if it cannot be looked up or if the externalObject's class is not supported
114112
* @throws IllegalStateException if it cannot be looked up
115113
* @param <EntityOrProblemFact> the object type

core/src/main/java/ai/timefold/solver/core/config/util/ConfigUtils.java

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package ai.timefold.solver.core.config.util;
22

33
import static ai.timefold.solver.core.impl.domain.common.accessor.MemberAccessorFactory.MemberAccessorType.FIELD_OR_READ_METHOD;
4-
import static ai.timefold.solver.core.impl.domain.solution.cloner.DeepCloningUtils.IMMUTABLE_CLASSES;
54

65
import java.lang.annotation.Annotation;
76
import java.lang.reflect.AnnotatedElement;
@@ -32,7 +31,7 @@
3231
import java.util.stream.Stream;
3332

3433
import ai.timefold.solver.core.api.domain.common.DomainAccessType;
35-
import ai.timefold.solver.core.api.domain.lookup.PlanningId;
34+
import ai.timefold.solver.core.api.domain.entity.PlanningId;
3635
import ai.timefold.solver.core.config.AbstractConfig;
3736
import ai.timefold.solver.core.impl.domain.common.AlphabeticMemberComparator;
3837
import ai.timefold.solver.core.impl.domain.common.ReflectionHelper;
@@ -451,17 +450,6 @@ Maybe the member (%s) should return a parameterized %s."""
451450
memberName, type, memberName, type.getSimpleName())));
452451
}
453452

454-
/**
455-
* @param type the class type
456-
* @return true if it is immutable; otherwise false
457-
*/
458-
public static boolean isGenericTypeImmutable(Class<?> type) {
459-
if (type == null) {
460-
return false;
461-
}
462-
return type.isRecord() || IMMUTABLE_CLASSES.contains(type);
463-
}
464-
465453
public static Optional<Class<?>> extractGenericTypeParameter(@NonNull String parentClassConcept,
466454
@NonNull Class<?> parentClass, @NonNull Class<?> type, @NonNull Type genericType,
467455
@Nullable Class<? extends Annotation> annotationClass, @NonNull String memberName) {

core/src/main/java/ai/timefold/solver/core/impl/domain/lookup/EqualsLookUpStrategy.java

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

core/src/main/java/ai/timefold/solver/core/impl/domain/lookup/ImmutableLookUpStrategy.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
import java.util.Map;
44

5-
public final class ImmutableLookUpStrategy implements LookUpStrategy {
5+
import org.jspecify.annotations.NullMarked;
6+
7+
@NullMarked
8+
final class ImmutableLookUpStrategy implements LookUpStrategy {
69

710
@Override
811
public void addWorkingObject(Map<Object, Object> idToWorkingObjectMap, Object workingObject) {

core/src/main/java/ai/timefold/solver/core/impl/domain/lookup/LookUpManager.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,18 @@
33
import java.util.HashMap;
44
import java.util.Map;
55

6-
import ai.timefold.solver.core.api.domain.lookup.PlanningId;
6+
import ai.timefold.solver.core.api.domain.entity.PlanningId;
77
import ai.timefold.solver.core.api.score.director.ScoreDirector;
88

9+
import org.jspecify.annotations.NullMarked;
10+
import org.jspecify.annotations.Nullable;
11+
912
/**
1013
* @see PlanningId
1114
* @see ScoreDirector#lookUpWorkingObject(Object)
1215
*/
13-
public class LookUpManager {
16+
@NullMarked
17+
public final class LookUpManager {
1418

1519
private final LookUpStrategyResolver lookUpStrategyResolver;
1620

@@ -26,47 +30,45 @@ public void reset() {
2630
}
2731

2832
public void addWorkingObject(Object workingObject) {
29-
LookUpStrategy lookUpStrategy = lookUpStrategyResolver.determineLookUpStrategy(workingObject);
33+
var lookUpStrategy = lookUpStrategyResolver.determineLookUpStrategy(workingObject);
3034
lookUpStrategy.addWorkingObject(idToWorkingObjectMap, workingObject);
3135
}
3236

3337
public void removeWorkingObject(Object workingObject) {
34-
LookUpStrategy lookUpStrategy = lookUpStrategyResolver.determineLookUpStrategy(workingObject);
38+
var lookUpStrategy = lookUpStrategyResolver.determineLookUpStrategy(workingObject);
3539
lookUpStrategy.removeWorkingObject(idToWorkingObjectMap, workingObject);
3640
}
3741

3842
/**
3943
* As defined by {@link ScoreDirector#lookUpWorkingObject(Object)}.
4044
*
41-
* @param externalObject sometimes null
42-
* @return null if externalObject is null
45+
* @return null if there is no workingObject for externalObject
4346
* @throws IllegalArgumentException if there is no workingObject for externalObject, if it cannot be looked up
4447
* or if the externalObject's class is not supported
4548
* @throws IllegalStateException if it cannot be looked up
4649
* @param <E> the object type
4750
*/
48-
public <E> E lookUpWorkingObject(E externalObject) {
51+
public <E> @Nullable E lookUpWorkingObject(@Nullable E externalObject) {
4952
if (externalObject == null) {
5053
return null;
5154
}
52-
LookUpStrategy lookUpStrategy = lookUpStrategyResolver.determineLookUpStrategy(externalObject);
55+
var lookUpStrategy = lookUpStrategyResolver.determineLookUpStrategy(externalObject);
5356
return lookUpStrategy.lookUpWorkingObject(idToWorkingObjectMap, externalObject);
5457
}
5558

5659
/**
5760
* As defined by {@link ScoreDirector#lookUpWorkingObjectOrReturnNull(Object)}.
5861
*
59-
* @param externalObject sometimes null
60-
* @return null if externalObject is null or if there is no workingObject for externalObject
62+
* @return null if externalObject is null, or if there is no workingObject for externalObject
6163
* @throws IllegalArgumentException if it cannot be looked up or if the externalObject's class is not supported
6264
* @throws IllegalStateException if it cannot be looked up
6365
* @param <E> the object type
6466
*/
65-
public <E> E lookUpWorkingObjectOrReturnNull(E externalObject) {
67+
public <E> @Nullable E lookUpWorkingObjectOrReturnNull(@Nullable E externalObject) {
6668
if (externalObject == null) {
6769
return null;
6870
}
69-
LookUpStrategy lookUpStrategy = lookUpStrategyResolver.determineLookUpStrategy(externalObject);
71+
var lookUpStrategy = lookUpStrategyResolver.determineLookUpStrategy(externalObject);
7072
return lookUpStrategy.lookUpWorkingObjectIfExists(idToWorkingObjectMap, externalObject);
7173
}
7274

core/src/main/java/ai/timefold/solver/core/impl/domain/lookup/LookUpStrategy.java

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

33
import java.util.Map;
44

5+
import org.jspecify.annotations.NullMarked;
6+
import org.jspecify.annotations.Nullable;
7+
8+
@NullMarked
59
public sealed interface LookUpStrategy
6-
permits EqualsLookUpStrategy, ImmutableLookUpStrategy, NoneLookUpStrategy, PlanningIdLookUpStrategy {
10+
permits ImmutableLookUpStrategy, NoneLookUpStrategy, PlanningIdLookUpStrategy {
711

812
void addWorkingObject(Map<Object, Object> idToWorkingObjectMap, Object workingObject);
913

1014
void removeWorkingObject(Map<Object, Object> idToWorkingObjectMap, Object workingObject);
1115

1216
<E> E lookUpWorkingObject(Map<Object, Object> idToWorkingObjectMap, E externalObject);
1317

14-
<E> E lookUpWorkingObjectIfExists(Map<Object, Object> idToWorkingObjectMap, E externalObject);
18+
<E> @Nullable E lookUpWorkingObjectIfExists(Map<Object, Object> idToWorkingObjectMap, E externalObject);
1519

1620
}

0 commit comments

Comments
 (0)