Skip to content

Commit f3948c7

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

40 files changed

Lines changed: 184 additions & 518 deletions

File tree

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

Lines changed: 22 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.util.Map;
2222
import java.util.function.BiPredicate;
2323
import java.util.function.Consumer;
24-
import java.util.function.Predicate;
2524

2625
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
2726
import ai.timefold.solver.core.api.domain.entity.PlanningPin;
@@ -64,7 +63,6 @@
6463
import ai.timefold.solver.core.preview.api.domain.metamodel.PlanningEntityMetaModel;
6564
import ai.timefold.solver.core.preview.api.neighborhood.stream.function.UniNeighborhoodsPredicate;
6665

67-
import org.jspecify.annotations.NonNull;
6866
import org.jspecify.annotations.Nullable;
6967
import org.slf4j.Logger;
7068
import org.slf4j.LoggerFactory;
@@ -92,7 +90,6 @@ public class EntityDescriptor<Solution_> {
9290
private final SolutionDescriptor<Solution_> solutionDescriptor;
9391
private final Class<?> entityClass;
9492
private final List<Class<?>> declaredInheritedEntityClassList = new ArrayList<>();
95-
private final Predicate<Object> isInitializedPredicate;
9693
private final List<MemberAccessor> declaredPlanningPinIndexMemberAccessorList = new ArrayList<>();
9794
@Nullable
9895
private ShadowVariablesInconsistentVariableDescriptor<Solution_> shadowVariablesInconsistentDescriptor;
@@ -142,17 +139,11 @@ public EntityDescriptor(int ordinal, SolutionDescriptor<Solution_> solutionDescr
142139
this.solutionDescriptor = solutionDescriptor;
143140
this.entityClass = entityClass;
144141
this.declaredInheritedEntityClassList.addAll(extractInheritedClasses(entityClass));
145-
isInitializedPredicate = this::isInitialized;
146142
if (entityClass.getPackage() == null) {
147-
LOGGER.warn("The entityClass ({}) should be in a proper java package.", entityClass);
143+
LOGGER.warn("The entityClass ({}) is in an unnamed package.", entityClass);
148144
}
149145
}
150146

151-
@SuppressWarnings("unchecked")
152-
public static Collection<Class<? extends Annotation>> getVariableAnnotationClasses() {
153-
return List.of(VARIABLE_ANNOTATION_CLASSES);
154-
}
155-
156147
/**
157148
* A number unique within a {@link SolutionDescriptor}, increasing sequentially from zero.
158149
* Used for indexing in arrays to avoid object hash lookups in maps.
@@ -163,18 +154,6 @@ public int getOrdinal() {
163154
return ordinal;
164155
}
165156

166-
/**
167-
* Using entityDescriptor::isInitialized directly breaks node sharing
168-
* because it creates multiple instances of this {@link Predicate}.
169-
*
170-
* @deprecated Prefer {@link #getEntityForEachFilter()} ()}.
171-
* @return never null, always the same {@link Predicate} instance to {@link #isInitialized(Object)}
172-
*/
173-
@Deprecated(forRemoval = true)
174-
public Predicate<Object> getIsInitializedPredicate() {
175-
return isInitializedPredicate;
176-
}
177-
178157
public EntityForEachFilter getEntityForEachFilter() {
179158
if (entityForEachFilter == null) {
180159
entityForEachFilter = new EntityForEachFilter(this);
@@ -206,7 +185,7 @@ public void processAnnotations(DescriptorPolicy descriptorPolicy) {
206185
&& declaredInheritedEntityClassList.isEmpty()) {
207186
throw new IllegalStateException(
208187
"The entityClass (%s) should have at least 1 getter method or 1 field with a %s annotation or a shadow variable annotation."
209-
.formatted(entityClass, PlanningVariable.class.getSimpleName()));
188+
.formatted(entityClass.getCanonicalName(), PlanningVariable.class.getSimpleName()));
210189
}
211190
processVariableAnnotations(descriptorPolicy);
212191
}
@@ -219,7 +198,7 @@ private void processEntityAnnotations() {
219198
if (entityAnnotation == null && declaredInheritedEntityClassList.isEmpty()) {
220199
throw new IllegalStateException(
221200
"The entityClass (%s) has been specified as a planning entity in the configuration, but does not have a @%s annotation."
222-
.formatted(entityClass, PlanningEntity.class.getSimpleName()));
201+
.formatted(entityClass.getCanonicalName(), PlanningEntity.class.getSimpleName()));
223202
}
224203
// We use the parent class of the entity as the base annotation
225204
if (entityAnnotation == null) {
@@ -250,7 +229,8 @@ private void processSorting(PlanningEntity entityAnnotation) {
250229
if (comparatorClass != null && comparatorFactoryClass != null) {
251230
throw new IllegalStateException(
252231
"The entityClass (%s) cannot have a comparatorClass (%s) and a comparatorFactoryClass (%s) at the same time."
253-
.formatted(entityClass, comparatorClass.getName(), comparatorFactoryClass.getName()));
232+
.formatted(entityClass.getCanonicalName(), comparatorClass.getName(),
233+
comparatorFactoryClass.getName()));
254234
}
255235
if (comparatorClass != null) {
256236
var comparator = ConfigUtils.newInstance(this::toString, "comparatorClass", comparatorClass);
@@ -319,12 +299,13 @@ private void registerVariableAccessor(int nextVariableDescriptorOrdinal,
319299
throw new IllegalStateException("""
320300
The entityClass (%s) has a @%s annotated member (%s), duplicated by member for variableDescriptor (%s).
321301
Maybe the annotation is defined on both the field and its getter."""
322-
.formatted(entityClass, variableAnnotationClass.getSimpleName(), memberAccessor, duplicate));
302+
.formatted(entityClass.getCanonicalName(), variableAnnotationClass.getSimpleName(), memberAccessor,
303+
duplicate));
323304
} else if (variableAnnotationClass.equals(PlanningVariable.class)) {
324305
var type = memberAccessor.getType();
325306
if (type.isArray()) {
326307
throw new IllegalStateException("The entityClass (%s) has a @%s annotated member (%s) that is of an array type."
327-
.formatted(entityClass, PlanningVariable.class.getSimpleName(), memberAccessor));
308+
.formatted(entityClass.getCanonicalName(), PlanningVariable.class.getSimpleName(), memberAccessor));
328309
}
329310
var variableDescriptor = new BasicVariableDescriptor<>(nextVariableDescriptorOrdinal, this, memberAccessor);
330311
declaredGenuineVariableDescriptorMap.put(memberName, variableDescriptor);
@@ -336,7 +317,7 @@ The entityClass (%s) has a @%s annotated member (%s), duplicated by member for v
336317
throw new IllegalStateException("""
337318
The entityClass (%s) has a @%s annotated member (%s) that has an unsupported type (%s).
338319
Maybe use %s."""
339-
.formatted(entityClass, PlanningListVariable.class.getSimpleName(), memberAccessor,
320+
.formatted(entityClass.getCanonicalName(), PlanningListVariable.class.getSimpleName(), memberAccessor,
340321
memberAccessor.getType(), List.class.getCanonicalName()));
341322
}
342323
} else if (variableAnnotationClass.equals(InverseRelationShadowVariable.class)) {
@@ -392,7 +373,7 @@ private void processPlanningPinAnnotation(DescriptorPolicy descriptorPolicy, Mem
392373
if (!Boolean.TYPE.isAssignableFrom(type) && !Boolean.class.isAssignableFrom(type)) {
393374
throw new IllegalStateException(
394375
"The entityClass (%s) has a %s annotated member (%s) that is not a boolean or Boolean."
395-
.formatted(entityClass, PlanningPin.class.getSimpleName(), member));
376+
.formatted(entityClass.getCanonicalName(), PlanningPin.class.getSimpleName(), member));
396377
}
397378
declaredPinEntityFilterList.add(new PinEntityFilter<>(memberAccessor));
398379
}
@@ -404,7 +385,7 @@ private void processPlanningPinIndexAnnotation(DescriptorPolicy descriptorPolicy
404385
if (!hasAnyGenuineListVariables()) {
405386
throw new IllegalStateException(
406387
"The entityClass (%s) has a %s annotated member (%s) but no %s annotated member."
407-
.formatted(entityClass, PlanningPinToIndex.class.getSimpleName(), member,
388+
.formatted(entityClass.getCanonicalName(), PlanningPinToIndex.class.getSimpleName(), member,
408389
PlanningListVariable.class.getSimpleName()));
409390
}
410391
var memberAccessor = descriptorPolicy.getMemberAccessorFactory().buildAndCacheMemberAccessor(member,
@@ -413,7 +394,7 @@ private void processPlanningPinIndexAnnotation(DescriptorPolicy descriptorPolicy
413394
if (!Integer.TYPE.isAssignableFrom(type)) {
414395
throw new IllegalStateException(
415396
"The entityClass (%s) has a %s annotated member (%s) that is not a primitive int."
416-
.formatted(entityClass, PlanningPinToIndex.class.getSimpleName(), member));
397+
.formatted(entityClass.getCanonicalName(), PlanningPinToIndex.class.getSimpleName(), member));
417398
}
418399
declaredPlanningPinIndexMemberAccessorList.add(memberAccessor);
419400
}
@@ -469,20 +450,19 @@ private void createEffectiveVariableDescriptorMaps() {
469450
.toList();
470451
if (!redefinedGenuineVariables.isEmpty()) {
471452
throw new IllegalStateException("""
472-
The class (%s) redefines the genuine variables (%s), which is not permitted.
473-
Maybe remove the variables (%s) from the class (%s).""".formatted(entityClass,
474-
redefinedGenuineVariables, String.join(", ", redefinedGenuineVariables),
475-
entityClass));
453+
The entityClass (%s) redefines the genuine variables (%s), which is not permitted.
454+
Maybe remove the variables (%s) from the class.""".formatted(entityClass.getCanonicalName(),
455+
redefinedGenuineVariables, String.join(", ", redefinedGenuineVariables)));
476456
}
477457
effectiveGenuineVariableDescriptorMap.putAll(declaredGenuineVariableDescriptorMap);
478458
var redefinedShadowVariables = declaredShadowVariableDescriptorMap.keySet().stream()
479459
.filter(key -> effectiveShadowVariableDescriptorMap.containsKey(key))
480460
.toList();
481461
if (!redefinedShadowVariables.isEmpty()) {
482462
throw new IllegalStateException("""
483-
The class (%s) redefines the shadow variables (%s), which is not permitted.
484-
Maybe remove the variables (%s) from the class (%s).""".formatted(entityClass,
485-
redefinedShadowVariables, redefinedShadowVariables, entityClass));
463+
The entityClass (%s) redefines the shadow variables (%s), which is not permitted.
464+
Maybe remove the variables (%s) from the class.""".formatted(entityClass.getCanonicalName(),
465+
redefinedShadowVariables, redefinedShadowVariables));
486466
}
487467
effectiveShadowVariableDescriptorMap.putAll(declaredShadowVariableDescriptorMap);
488468

@@ -536,7 +516,7 @@ private void createEffectivePlanningPinIndexReader() {
536516
}
537517
default -> throw new IllegalStateException(
538518
"The entityClass (%s) has (%d) @%s-annotated members (%s), where it should only have one."
539-
.formatted(entityClass, planningPinIndexMemberAccessorList.size(),
519+
.formatted(entityClass.getCanonicalName(), planningPinIndexMemberAccessorList.size(),
540520
PlanningPinToIndex.class.getSimpleName(), planningPinIndexMemberAccessorList));
541521
}
542522
}
@@ -690,18 +670,6 @@ public boolean hasVariableDescriptor(String variableName) {
690670
return effectiveVariableDescriptorMap.get(variableName);
691671
}
692672

693-
public @NonNull VariableDescriptor<Solution_> getVariableDescriptorOrFail(String variableName) {
694-
var variableDescriptor = effectiveVariableDescriptorMap.get(variableName);
695-
if (variableDescriptor == null) {
696-
throw new IllegalArgumentException("""
697-
Entity class %s does not hava a "%s" genuine or shadow variable.
698-
Maybe you meant one of %s?"""
699-
.formatted(entityClass.getSimpleName(),
700-
variableName, effectiveVariableDescriptorMap.keySet()));
701-
}
702-
return variableDescriptor;
703-
}
704-
705673
public boolean hasAnyDeclaredGenuineVariableDescriptor() {
706674
return !declaredGenuineVariableDescriptorMap.isEmpty();
707675
}
@@ -734,7 +702,7 @@ public String buildInvalidVariableNameExceptionMessage(String variableName) {
734702
"""
735703
The variableName (%s) for entityClass (%s) does not exist as a getter or field on that class.
736704
Check the spelling of the variableName (%s)."""
737-
.formatted(variableName, entityClass, variableName);
705+
.formatted(variableName, entityClass.getCanonicalName(), variableName);
738706
if (variableName.length() >= 2
739707
&& !Character.isUpperCase(variableName.charAt(0))
740708
&& Character.isUpperCase(variableName.charAt(1))) {
@@ -748,7 +716,7 @@ Check the spelling of the variableName (%s)."""
748716
return """
749717
The variableName (%s) for entityClass (%s) exists as a getter or field on that class, but isn't in the planning variables (%s).
750718
%sMaybe your planning entity's getter or field lacks a @%s annotation or a shadow variable annotation."""
751-
.formatted(variableName, entityClass, effectiveVariableDescriptorMap.keySet(),
719+
.formatted(variableName, entityClass.getCanonicalName(), effectiveVariableDescriptorMap.keySet(),
752720
Character.isUpperCase(variableName.charAt(0))
753721
? "Maybe the variableName (%s) should start with a lowercase.%n".formatted(variableName)
754722
: "",
@@ -856,7 +824,7 @@ public boolean isMovable(Solution_ workingSolution, Object entity) {
856824

857825
@Override
858826
public String toString() {
859-
return "%s(%s)".formatted(getClass().getSimpleName(), entityClass.getName());
827+
return "%s(%s)".formatted(getClass().getSimpleName(), entityClass.getCanonicalName());
860828
}
861829

862830
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ protected void processValueRangeRefs(DescriptorPolicy descriptorPolicy, String[]
6060
throw new IllegalArgumentException("""
6161
The entityClass (%s) has a @%s annotated property (%s) that has no valueRangeProviderRefs (%s) \
6262
and no matching anonymous value range providers were found."""
63-
.formatted(entityDescriptor.getEntityClass().getSimpleName(),
63+
.formatted(entityDescriptor.getEntityClass().getCanonicalName(),
6464
PlanningVariable.class.getSimpleName(),
6565
variableMemberAccessor.getName(),
6666
Arrays.toString(valueRangeProviderRefs)));

core/src/main/java/ai/timefold/solver/core/impl/heuristic/selector/common/decorator/SelectionSorterWeightFactory.java

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

core/src/main/java/ai/timefold/solver/core/impl/neighborhood/stream/DefaultMoveStreamFactory.java

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import ai.timefold.solver.core.preview.api.neighborhood.stream.function.BiNeighborhoodsMapper;
2424
import ai.timefold.solver.core.preview.api.neighborhood.stream.function.BiNeighborhoodsPredicate;
2525
import ai.timefold.solver.core.preview.api.neighborhood.stream.function.UniNeighborhoodsPredicate;
26-
import ai.timefold.solver.core.preview.api.neighborhood.stream.joiner.NeighborhoodsJoiners;
2726
import ai.timefold.solver.core.preview.api.neighborhood.stream.sampling.UniSamplingStream;
2827

2928
import org.jspecify.annotations.NullMarked;
@@ -164,28 +163,6 @@ public SolutionDescriptor<Solution_> getSolutionDescriptor() {
164163
return enumeratingStreamFactory.getSolutionDescriptor();
165164
}
166165

167-
@Override
168-
public <Entity_, Value_> UniEnumeratingStream<Solution_, ElementPosition>
169-
forEachAssignablePosition(PlanningListVariableMetaModel<Solution_, Entity_, Value_> variableMetaModel) {
170-
// Stream with unpinned entities;
171-
// includes null if the variable allows unassigned values.
172-
var unpinnedEntities =
173-
forEach(variableMetaModel.entity().type(), variableMetaModel.allowsUnassignedValues());
174-
// Stream with unpinned values, which are assigned to any list variable;
175-
// always includes null so that we can later create a position at the end of the list,
176-
// i.e. with no value after it.
177-
var nodeSharingSupportFunctions = getNodeSharingSupportFunctions(variableMetaModel);
178-
var unpinnedValues = forEach(variableMetaModel.type(), true)
179-
.filter(nodeSharingSupportFunctions.assignedValueOrNullFilter);
180-
// Joins the two previous streams to create pairs of (entity, value),
181-
// eliminating values which do not match that entity's value range.
182-
// It maps these pairs to expected target positions in that entity's list variable.
183-
return unpinnedEntities.join(unpinnedValues,
184-
NeighborhoodsJoiners.filtering(nodeSharingSupportFunctions.valueInRangeFilter))
185-
.map(nodeSharingSupportFunctions.toElementPositionMapper)
186-
.distinct();
187-
}
188-
189166
public record NodeSharingSupportFunctions<Solution_, Entity_, Value_>(
190167
PlanningVariableMetaModel<Solution_, Entity_, Value_> variableMetaModel,
191168
BiNeighborhoodsPredicate<Solution_, Entity_, Value_> differentValueFilter,

core/src/main/java/ai/timefold/solver/core/impl/score/director/InnerScoreDirector.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -401,13 +401,6 @@ default ScoreAnalysis<Score_> buildScoreAnalysis(ScoreAnalysisFetchPolicy scoreA
401401
return new ScoreAnalysis<>(state.raw(), constraintAnalysisMap, state.isFullyAssigned());
402402
}
403403

404-
/*
405-
* The following methods are copied here from ScoreDirector because they are deprecated there for removal.
406-
* They will only be supported on this type, which serves for internal use only,
407-
* as opposed to ScoreDirector, which is a public type.
408-
* This way, we can ensure that these methods are used correctly and in a safe manner.
409-
*/
410-
411404
default void beforeEntityAdded(Object entity) {
412405
beforeEntityAdded(getSolutionDescriptor().findEntityDescriptorOrFail(entity.getClass()), entity);
413406
}

0 commit comments

Comments
 (0)