Skip to content

Commit a26c5d4

Browse files
committed
refactor: remove deprecations from entities and variables
1 parent 38c1f1c commit a26c5d4

56 files changed

Lines changed: 64 additions & 1903 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/entity/PinningFilter.java

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

core/src/main/java/ai/timefold/solver/core/api/domain/entity/PlanningEntity.java

Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import ai.timefold.solver.core.api.domain.common.ComparatorFactory;
1111
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
1212
import ai.timefold.solver.core.api.domain.variable.PlanningVariable;
13-
import ai.timefold.solver.core.impl.heuristic.selector.common.decorator.SelectionSorterWeightFactory;
1413

1514
/**
1615
* Specifies that the class is a planning entity.
@@ -69,80 +68,4 @@ interface NullComparator<T> extends Comparator<T> {
6968
interface NullComparatorFactory<Solution_, T> extends ComparatorFactory<Solution_, T> {
7069
}
7170

72-
/**
73-
* A pinned planning entity is never changed during planning,
74-
* this is useful in repeated planning use cases (such as continuous planning and real-time planning).
75-
* This applies to all the planning variables of this planning entity.
76-
* <p>
77-
* The method {@link PinningFilter#accept(Object, Object)} returns false if the selection entity is pinned
78-
* and it returns true if the selection entity is movable
79-
*
80-
* @return {@link NullPinningFilter} when it is null (workaround for annotation limitation)
81-
* @deprecated Prefer using {@link PlanningPin}.
82-
*/
83-
@Deprecated(forRemoval = true, since = "1.23.0")
84-
Class<? extends PinningFilter> pinningFilter() default NullPinningFilter.class;
85-
86-
/**
87-
* Workaround for annotation limitation in {@link #pinningFilter()}.
88-
*
89-
* @deprecated Prefer using {@link PlanningPin}.
90-
*/
91-
@Deprecated(forRemoval = true, since = "1.23.0")
92-
interface NullPinningFilter extends PinningFilter {
93-
}
94-
95-
/**
96-
* Allows a collection of planning entities to be sorted by difficulty.
97-
* A difficultyWeight estimates how hard is to plan a certain PlanningEntity.
98-
* Some algorithms benefit from planning on more difficult planning entities first/last or from focusing on them.
99-
* <p>
100-
* The {@link Comparator} should sort in ascending difficulty
101-
* (even though many optimization algorithms will reverse it).
102-
* For example: sorting 3 processes on difficultly based on their RAM usage requirement:
103-
* Process B (1GB RAM), Process A (2GB RAM), Process C (7GB RAM),
104-
* <p>
105-
* Do not use together with {@link #difficultyWeightFactoryClass()}.
106-
*
107-
* @deprecated Deprecated in favor of {@link #comparatorClass()}.
108-
*
109-
* @return {@link NullDifficultyComparator} when it is null (workaround for annotation limitation)
110-
* @see #difficultyWeightFactoryClass()
111-
*/
112-
@Deprecated(forRemoval = true, since = "1.28.0")
113-
Class<? extends Comparator> difficultyComparatorClass() default NullDifficultyComparator.class;
114-
115-
/**
116-
* Workaround for annotation limitation in {@link #difficultyComparatorClass()}.
117-
*
118-
* @deprecated Deprecated in favor of {@link NullComparator}.
119-
*/
120-
@Deprecated(forRemoval = true, since = "1.28.0")
121-
interface NullDifficultyComparator<T> extends NullComparator<T> {
122-
}
123-
124-
/**
125-
* The {@link SelectionSorterWeightFactory} alternative for {@link #difficultyComparatorClass()}.
126-
* <p>
127-
* Do not use together with {@link #difficultyComparatorClass()}.
128-
*
129-
* @deprecated Deprecated in favor of {@link #comparatorFactoryClass()}.
130-
*
131-
* @return {@link NullDifficultyWeightFactory} when it is null (workaround for annotation limitation)
132-
* @see #difficultyComparatorClass()
133-
*/
134-
@Deprecated(forRemoval = true, since = "1.28.0")
135-
Class<? extends SelectionSorterWeightFactory> difficultyWeightFactoryClass() default NullDifficultyWeightFactory.class;
136-
137-
/**
138-
* Workaround for annotation limitation in {@link #difficultyWeightFactoryClass()}.
139-
*
140-
* @deprecated Deprecated in favor of {@link NullComparatorFactory}.
141-
*/
142-
@Deprecated(forRemoval = true, since = "1.28.0")
143-
interface NullDifficultyWeightFactory<Solution_, T>
144-
extends SelectionSorterWeightFactory<Solution_, T>,
145-
NullComparatorFactory<Solution_, T> {
146-
}
147-
14871
}

core/src/main/java/ai/timefold/solver/core/api/domain/variable/PlanningVariable.java

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
1313
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
1414
import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider;
15-
import ai.timefold.solver.core.impl.heuristic.selector.common.decorator.SelectionSorterWeightFactory;
1615

1716
/**
1817
* Specifies that a bean property (or a field) can be changed and should be optimized by the optimization algorithms.
@@ -84,63 +83,4 @@ interface NullComparator<T> extends Comparator<T> {
8483
interface NullComparatorFactory<Solution_, T> extends ComparatorFactory<Solution_, T> {
8584
}
8685

87-
/**
88-
* As defined by {@link #allowsUnassigned()}.
89-
*
90-
* @deprecated Use {@link #allowsUnassigned()} instead.
91-
* @return true if null is a valid value for this planning variable
92-
*/
93-
@Deprecated(forRemoval = true, since = "1.8.0")
94-
boolean nullable() default false;
95-
96-
/**
97-
* Allows a collection of planning values for this variable to be sorted by strength.
98-
* A strengthWeight estimates how strong a planning value is.
99-
* Some algorithms benefit from planning on weaker planning values first or from focusing on them.
100-
* <p>
101-
* The {@link Comparator} should sort in ascending strength.
102-
* For example: sorting 3 computers on strength based on their RAM capacity:
103-
* Computer B (1GB RAM), Computer A (2GB RAM), Computer C (7GB RAM),
104-
* <p>
105-
* Do not use together with {@link #strengthWeightFactoryClass()}.
106-
*
107-
* @deprecated Deprecated in favor of {@link #comparatorClass()}.
108-
*
109-
* @return {@link NullStrengthComparator} when it is null (workaround for annotation limitation)
110-
* @see #strengthWeightFactoryClass()
111-
*/
112-
@Deprecated(forRemoval = true, since = "1.28.0")
113-
Class<? extends Comparator> strengthComparatorClass() default NullStrengthComparator.class;
114-
115-
/**
116-
* Workaround for annotation limitation in {@link #strengthComparatorClass()}.
117-
*
118-
* @deprecated Deprecated in favor of {@link NullComparator}.
119-
*/
120-
@Deprecated(forRemoval = true, since = "1.28.0")
121-
interface NullStrengthComparator<T> extends NullComparator<T> {
122-
}
123-
124-
/**
125-
* The {@link SelectionSorterWeightFactory} alternative for {@link #strengthComparatorClass()}.
126-
* <p>
127-
* Do not use together with {@link #strengthComparatorClass()}.
128-
*
129-
* @deprecated Deprecated in favor of {@link #comparatorFactoryClass()}.
130-
*
131-
* @return {@link NullStrengthWeightFactory} when it is null (workaround for annotation limitation)
132-
* @see #strengthComparatorClass()
133-
*/
134-
@Deprecated(forRemoval = true, since = "1.28.0")
135-
Class<? extends SelectionSorterWeightFactory> strengthWeightFactoryClass() default NullStrengthWeightFactory.class;
136-
137-
/**
138-
* Workaround for annotation limitation in {@link #strengthWeightFactoryClass()}.
139-
*
140-
* @deprecated Deprecated in favor of {@link NullComparatorFactory}.
141-
*/
142-
@Deprecated(forRemoval = true, since = "1.28.0")
143-
interface NullStrengthWeightFactory<Solution_, T>
144-
extends SelectionSorterWeightFactory<Solution_, T>, NullComparatorFactory<Solution_, T> {
145-
}
14686
}

core/src/main/java/ai/timefold/solver/core/impl/domain/entity/descriptor/EntityDescriptor.java

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import java.util.function.Consumer;
2424
import java.util.function.Predicate;
2525

26-
import ai.timefold.solver.core.api.domain.entity.PinningFilter;
2726
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
2827
import ai.timefold.solver.core.api.domain.entity.PlanningPin;
2928
import ai.timefold.solver.core.api.domain.entity.PlanningPinToIndex;
@@ -100,7 +99,6 @@ public class EntityDescriptor<Solution_> {
10099
private ShadowVariablesInconsistentVariableDescriptor<Solution_> shadowVariablesInconsistentDescriptor;
101100

102101
// Only declared movable filter, excludes inherited and descending movable filters
103-
private MovableFilter<Solution_> declaredMovableEntityFilter;
104102
private SelectionSorter<Solution_, Object> descendingSorter;
105103

106104
// Only declared variable descriptors, excludes inherited variable descriptors
@@ -232,76 +230,28 @@ private void processEntityAnnotations() {
232230
.orElseThrow(
233231
() -> new IllegalStateException("Impossible state as the previous if block would fail first."));
234232
}
235-
processMovable(entityAnnotation);
236233
processSorting(entityAnnotation);
237234
}
238235

239-
/**
240-
* @deprecated Remove in the next major version of Timefold Solver.
241-
*/
242-
@Deprecated(forRemoval = true, since = "1.23.0")
243-
private void processMovable(PlanningEntity entityAnnotation) {
244-
if (entityAnnotation == null) {
245-
return;
246-
}
247-
var pinningFilterClass = entityAnnotation.pinningFilter();
248-
var hasPinningFilter = pinningFilterClass != PlanningEntity.NullPinningFilter.class;
249-
if (hasPinningFilter) {
250-
var pinningFilter = ConfigUtils.newInstance(this::toString, "pinningFilterClass",
251-
(Class<? extends PinningFilter<Solution_, Object>>) pinningFilterClass);
252-
declaredMovableEntityFilter = (solution, selection) -> !pinningFilter.accept(solution, selection);
253-
}
254-
}
255-
256236
private void processSorting(PlanningEntity entityAnnotation) {
257237
if (entityAnnotation == null) {
258238
return;
259239
}
260-
var difficultyComparatorClass = entityAnnotation.difficultyComparatorClass();
261-
if (difficultyComparatorClass != null
262-
&& PlanningEntity.NullComparator.class.isAssignableFrom(difficultyComparatorClass)) {
263-
difficultyComparatorClass = null;
264-
}
265240
var comparatorClass = entityAnnotation.comparatorClass();
266241
if (comparatorClass != null
267242
&& PlanningEntity.NullComparator.class.isAssignableFrom(comparatorClass)) {
268243
comparatorClass = null;
269244
}
270-
if (difficultyComparatorClass != null && comparatorClass != null) {
271-
throw new IllegalStateException(
272-
"The entityClass (%s) cannot have a %s (%s) and a %s (%s) at the same time.".formatted(getEntityClass(),
273-
"difficultyComparatorClass", difficultyComparatorClass.getName(), "comparatorClass",
274-
comparatorClass.getName()));
275-
}
276-
var difficultyWeightFactoryClass = entityAnnotation.difficultyWeightFactoryClass();
277-
if (difficultyWeightFactoryClass != null
278-
&& PlanningEntity.NullComparatorFactory.class.isAssignableFrom(difficultyWeightFactoryClass)) {
279-
difficultyWeightFactoryClass = null;
280-
}
281245
var comparatorFactoryClass = entityAnnotation.comparatorFactoryClass();
282246
if (comparatorFactoryClass != null
283247
&& PlanningEntity.NullComparatorFactory.class.isAssignableFrom(comparatorFactoryClass)) {
284248
comparatorFactoryClass = null;
285249
}
286-
if (difficultyWeightFactoryClass != null && comparatorFactoryClass != null) {
287-
throw new IllegalStateException(
288-
"The entityClass (%s) cannot have a %s (%s) and a %s (%s) at the same time.".formatted(getEntityClass(),
289-
"difficultyWeightFactoryClass", difficultyWeightFactoryClass.getName(), "comparatorFactoryClass",
290-
comparatorFactoryClass.getName()));
291-
}
292250
// Selected settings
293251
var selectedComparatorPropertyName = "comparatorClass";
294252
var selectedComparatorClass = comparatorClass;
295253
var selectedComparatorFactoryPropertyName = "comparatorFactoryClass";
296254
var selectedComparatorFactoryClass = comparatorFactoryClass;
297-
if (difficultyComparatorClass != null) {
298-
selectedComparatorPropertyName = "difficultyComparatorClass";
299-
selectedComparatorClass = difficultyComparatorClass;
300-
}
301-
if (difficultyWeightFactoryClass != null) {
302-
selectedComparatorFactoryPropertyName = "difficultyWeightFactoryClass";
303-
selectedComparatorFactoryClass = difficultyWeightFactoryClass;
304-
}
305255
if (selectedComparatorClass != null && selectedComparatorFactoryClass != null) {
306256
throw new IllegalStateException("The entityClass (%s) cannot have a %s (%s) and a %s (%s) at the same time."
307257
.formatted(entityClass, selectedComparatorPropertyName, selectedComparatorClass.getName(),
@@ -552,11 +502,6 @@ Maybe remove the variables (%s) from the class (%s).""".formatted(entityClass,
552502
}
553503

554504
private void createEffectiveMovableEntitySelectionFilter() {
555-
if (declaredMovableEntityFilter != null && !hasAnyDeclaredGenuineVariableDescriptor()) {
556-
throw new IllegalStateException(
557-
"The entityClass (%s) has a movableEntitySelectionFilterClass (%s), but it has no declared genuine variables, only shadow variables."
558-
.formatted(entityClass, declaredMovableEntityFilter.getClass()));
559-
}
560505
var movableFilterList = new ArrayList<MovableFilter<Solution_>>();
561506
// TODO Also add in child entity selectors
562507
for (var inheritedEntityDescriptor : effectiveInheritedEntityDescriptorList) {
@@ -565,9 +510,6 @@ private void createEffectiveMovableEntitySelectionFilter() {
565510
movableFilterList.add(inheritedEntityDescriptor.effectiveMovableEntityFilter);
566511
}
567512
}
568-
if (declaredMovableEntityFilter != null) {
569-
movableFilterList.add(declaredMovableEntityFilter);
570-
}
571513
movableFilterList.addAll(declaredPinEntityFilterList);
572514
if (movableFilterList.isEmpty()) {
573515
effectiveMovableEntityFilter = null;
@@ -637,10 +579,6 @@ public boolean matchesEntity(Object entity) {
637579
return entityClass.isAssignableFrom(entity.getClass());
638580
}
639581

640-
public boolean hasPinningFilter() {
641-
return declaredMovableEntityFilter != null;
642-
}
643-
644582
public boolean hasEffectiveMovableEntityFilter() {
645583
return effectiveMovableEntityFilter != null;
646584
}

core/src/main/java/ai/timefold/solver/core/impl/domain/variable/descriptor/BasicVariableDescriptor.java

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -42,76 +42,34 @@ protected void processPropertyAnnotations(DescriptorPolicy descriptorPolicy) {
4242

4343
private SortingProperties assertSortingProperties(PlanningVariable planningVariableAnnotation) {
4444
// Comparator property
45-
var strengthComparatorClass = planningVariableAnnotation.strengthComparatorClass();
4645
var comparatorClass = planningVariableAnnotation.comparatorClass();
47-
if (strengthComparatorClass != null
48-
&& PlanningVariable.NullComparator.class.isAssignableFrom(strengthComparatorClass)) {
49-
strengthComparatorClass = null;
50-
}
5146
if (comparatorClass != null && PlanningVariable.NullComparator.class.isAssignableFrom(comparatorClass)) {
5247
comparatorClass = null;
5348
}
54-
if (strengthComparatorClass != null && comparatorClass != null) {
55-
throw new IllegalStateException(
56-
"The entityClass (%s) property (%s) cannot have a %s (%s) and a %s (%s) at the same time.".formatted(
57-
entityDescriptor.getEntityClass(), variableMemberAccessor.getName(), "strengthComparatorClass",
58-
strengthComparatorClass.getName(), "comparatorClass", comparatorClass.getName()));
59-
}
6049
// Comparator factory property
61-
var strengthWeightFactoryClass = planningVariableAnnotation.strengthWeightFactoryClass();
6250
var comparatorFactoryClass = planningVariableAnnotation.comparatorFactoryClass();
63-
if (strengthWeightFactoryClass != null
64-
&& PlanningVariable.NullComparatorFactory.class.isAssignableFrom(strengthWeightFactoryClass)) {
65-
strengthWeightFactoryClass = null;
66-
}
6751
if (comparatorFactoryClass != null
6852
&& PlanningVariable.NullComparatorFactory.class.isAssignableFrom(comparatorFactoryClass)) {
6953
comparatorFactoryClass = null;
7054
}
71-
if (strengthWeightFactoryClass != null && comparatorFactoryClass != null) {
72-
throw new IllegalStateException(
73-
"The entityClass (%s) property (%s) cannot have a %s (%s) and a %s (%s) at the same time.".formatted(
74-
entityDescriptor.getEntityClass(), variableMemberAccessor.getName(), "strengthWeightFactoryClass",
75-
strengthWeightFactoryClass.getName(), "comparatorFactoryClass", comparatorFactoryClass.getName()));
76-
}
7755
// Selected settings
7856
var selectedComparatorPropertyName = "comparatorClass";
7957
var selectedComparatorClass = comparatorClass;
8058
var selectedComparatorFactoryPropertyName = "comparatorFactoryClass";
8159
var selectedComparatorFactoryClass = comparatorFactoryClass;
82-
if (strengthComparatorClass != null) {
83-
selectedComparatorPropertyName = "strengthComparatorClass";
84-
selectedComparatorClass = strengthComparatorClass;
85-
}
86-
if (strengthWeightFactoryClass != null) {
87-
selectedComparatorFactoryPropertyName = "strengthWeightFactoryClass";
88-
selectedComparatorFactoryClass = strengthWeightFactoryClass;
89-
}
9060
return new SortingProperties(selectedComparatorPropertyName, selectedComparatorClass,
9161
selectedComparatorFactoryPropertyName, selectedComparatorFactoryClass);
9262
}
9363

9464
private void processAllowsUnassigned(PlanningVariable planningVariableAnnotation) {
95-
var deprecatedNullable = planningVariableAnnotation.nullable();
96-
if (planningVariableAnnotation.allowsUnassigned()) {
97-
// If the user has specified allowsUnassigned = true, it takes precedence.
98-
if (deprecatedNullable) {
99-
throw new IllegalArgumentException(
100-
"The entityClass (%s) has a @%s-annotated property (%s) with allowsUnassigned (%s) and nullable (%s) which are mutually exclusive."
101-
.formatted(entityDescriptor.getEntityClass(), PlanningVariable.class.getSimpleName(),
102-
variableMemberAccessor.getName(), true, true));
103-
}
104-
this.allowsUnassigned = true;
105-
} else { // If the user has not specified allowsUnassigned = true, nullable is taken.
106-
this.allowsUnassigned = deprecatedNullable;
107-
}
108-
if (this.allowsUnassigned && variableMemberAccessor.getType().isPrimitive()) {
65+
allowsUnassigned = planningVariableAnnotation.allowsUnassigned();
66+
if (allowsUnassigned && variableMemberAccessor.getType().isPrimitive()) {
10967
throw new IllegalArgumentException(
11068
"The entityClass (%s) has a @%s-annotated property (%s) with allowsUnassigned (%s) which is not compatible with the primitive propertyType (%s)."
11169
.formatted(entityDescriptor.getEntityClass(),
11270
PlanningVariable.class.getSimpleName(),
11371
variableMemberAccessor.getName(),
114-
this.allowsUnassigned,
72+
allowsUnassigned,
11573
variableMemberAccessor.getType()));
11674
}
11775
}

0 commit comments

Comments
 (0)