diff --git a/benchmark/pom.xml b/benchmark/pom.xml index a6a301eaa1..e905cb8fe9 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -144,6 +144,12 @@ mockito-core test + + + org.jspecify + jspecify + test + diff --git a/benchmark/src/test/java/ai/timefold/solver/benchmark/api/PlannerBenchmarkFactoryTest.java b/benchmark/src/test/java/ai/timefold/solver/benchmark/api/PlannerBenchmarkFactoryTest.java index 0757a321fa..fc43ddf4bd 100644 --- a/benchmark/src/test/java/ai/timefold/solver/benchmark/api/PlannerBenchmarkFactoryTest.java +++ b/benchmark/src/test/java/ai/timefold/solver/benchmark/api/PlannerBenchmarkFactoryTest.java @@ -26,6 +26,7 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; import ai.timefold.solver.core.impl.testdata.util.PlannerTestUtils; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -321,7 +322,7 @@ void buildPlannerBenchmark() { public static class TestdataConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[0]; } } diff --git a/build/build-parent/pom.xml b/build/build-parent/pom.xml index 3dd93a6580..bb97be94b9 100644 --- a/build/build-parent/pom.xml +++ b/build/build-parent/pom.xml @@ -38,6 +38,7 @@ 0.52 5.2.3 3.6.4 + 1.0.0 @@ -134,6 +135,11 @@ jfreechart ${version.org.jfree.jfreechart} + + org.jspecify + jspecify + ${version.org.jspecify} + @@ -184,6 +190,8 @@ ${version.org.webjars.jquery} runtime + + diff --git a/core/pom.xml b/core/pom.xml index 99ec6e057e..dceb63c96b 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -114,6 +114,11 @@ mockito-junit-jupiter test + + + org.jspecify + jspecify + diff --git a/core/src/build/revapi-differences.json b/core/src/build/revapi-differences.json index 87255f0389..d348497b80 100644 --- a/core/src/build/revapi-differences.json +++ b/core/src/build/revapi-differences.json @@ -57,6 +57,29 @@ "oldValue": "{\"terminationClass\", \"terminationCompositionStyle\", \"spentLimit\", \"millisecondsSpentLimit\", \"secondsSpentLimit\", \"minutesSpentLimit\", \"hoursSpentLimit\", \"daysSpentLimit\", \"unimprovedSpentLimit\", \"unimprovedMillisecondsSpentLimit\", \"unimprovedSecondsSpentLimit\", \"unimprovedMinutesSpentLimit\", \"unimprovedHoursSpentLimit\", \"unimprovedDaysSpentLimit\", \"unimprovedScoreDifferenceThreshold\", \"bestScoreLimit\", \"bestScoreFeasible\", \"stepCountLimit\", \"unimprovedStepCountLimit\", \"scoreCalculationCountLimit\", \"terminationConfigList\"}", "newValue": "{\"terminationClass\", \"terminationCompositionStyle\", \"spentLimit\", \"millisecondsSpentLimit\", \"secondsSpentLimit\", \"minutesSpentLimit\", \"hoursSpentLimit\", \"daysSpentLimit\", \"unimprovedSpentLimit\", \"unimprovedMillisecondsSpentLimit\", \"unimprovedSecondsSpentLimit\", \"unimprovedMinutesSpentLimit\", \"unimprovedHoursSpentLimit\", \"unimprovedDaysSpentLimit\", \"unimprovedScoreDifferenceThreshold\", \"bestScoreLimit\", \"bestScoreFeasible\", \"stepCountLimit\", \"unimprovedStepCountLimit\", \"scoreCalculationCountLimit\", \"moveCountLimit\", \"terminationConfigList\"}", "justification": "Add new termination configuration" + }, + { + "ignore": true, + "code": "java.method.parameterTypeParameterChanged", + "old": "parameter > ai.timefold.solver.core.api.domain.valuerange.CountableValueRange ai.timefold.solver.core.api.domain.valuerange.ValueRangeFactory::createTemporalValueRange(===Temporal_===, Temporal_, long, java.time.temporal.TemporalUnit)", + "new": "parameter > ai.timefold.solver.core.api.domain.valuerange.CountableValueRange ai.timefold.solver.core.api.domain.valuerange.ValueRangeFactory::createTemporalValueRange(===Temporal_===, Temporal_, long, java.time.temporal.TemporalUnit)", + "parameterIndex": "0", + "justification": "False positive after addition of @NonNull annotation" + }, + { + "ignore": true, + "code": "java.method.parameterTypeParameterChanged", + "old": "parameter > ai.timefold.solver.core.api.domain.valuerange.CountableValueRange ai.timefold.solver.core.api.domain.valuerange.ValueRangeFactory::createTemporalValueRange(Temporal_, ===Temporal_===, long, java.time.temporal.TemporalUnit)", + "new": "parameter > ai.timefold.solver.core.api.domain.valuerange.CountableValueRange ai.timefold.solver.core.api.domain.valuerange.ValueRangeFactory::createTemporalValueRange(Temporal_, ===Temporal_===, long, java.time.temporal.TemporalUnit)", + "parameterIndex": "1", + "justification": "False positive after addition of @NonNull annotation" + }, + { + "ignore": true, + "code": "java.method.returnTypeTypeParametersChanged", + "old": "method Score_ ai.timefold.solver.core.api.score.constraint.ConstraintMatch>::getScore()", + "new": "method Score_ ai.timefold.solver.core.api.score.constraint.ConstraintMatch>::getScore()", + "justification": "False positive after addition of @NonNull annotation" } ] } diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/entity/PinningFilter.java b/core/src/main/java/ai/timefold/solver/core/api/domain/entity/PinningFilter.java index 206cf08eb9..ff7f297df6 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/entity/PinningFilter.java +++ b/core/src/main/java/ai/timefold/solver/core/api/domain/entity/PinningFilter.java @@ -2,6 +2,8 @@ import ai.timefold.solver.core.api.domain.solution.PlanningSolution; +import org.jspecify.annotations.NonNull; + /** * Decides on accepting or discarding a {@link PlanningEntity}. * A pinned {@link PlanningEntity}'s planning variables are never changed. @@ -13,9 +15,9 @@ public interface PinningFilter { /** * @param solution working solution to which the entity belongs - * @param entity never null, a {@link PlanningEntity} + * @param entity a {@link PlanningEntity} * @return true if the entity it is pinned, false if the entity is movable. */ - boolean accept(Solution_ solution, Entity_ entity); + boolean accept(@NonNull Solution_ solution, @NonNull Entity_ entity); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/solution/ConstraintWeightOverrides.java b/core/src/main/java/ai/timefold/solver/core/api/domain/solution/ConstraintWeightOverrides.java index 0cead4b40f..414b8442ea 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/solution/ConstraintWeightOverrides.java +++ b/core/src/main/java/ai/timefold/solver/core/api/domain/solution/ConstraintWeightOverrides.java @@ -11,6 +11,9 @@ import ai.timefold.solver.core.api.solver.change.ProblemChange; import ai.timefold.solver.core.impl.domain.solution.DefaultConstraintWeightOverrides; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Used to override constraint weights defined in Constraint Streams, * e.g., in {@link UniConstraintStream#penalize(Score)}. @@ -46,16 +49,17 @@ static > ConstraintWeightOverrides of(Map getKnownConstraintNames(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/solution/PlanningSolution.java b/core/src/main/java/ai/timefold/solver/core/api/domain/solution/PlanningSolution.java index 76bba0b2b1..e413c0cc1a 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/solution/PlanningSolution.java +++ b/core/src/main/java/ai/timefold/solver/core/api/domain/solution/PlanningSolution.java @@ -12,6 +12,8 @@ import ai.timefold.solver.core.api.domain.solution.cloner.SolutionCloner; import ai.timefold.solver.core.api.score.stream.ConstraintProvider; +import org.jspecify.annotations.NonNull; + /** * Specifies that the class is a planning solution. * A solution represents a problem and a possible solution of that problem. @@ -53,9 +55,8 @@ * This feature is not supported under Quarkus. * When using Quarkus, * setting this to anything other than {@link AutoDiscoverMemberType#NONE} will result in a build-time exception. - * - * @return never null */ + @NonNull AutoDiscoverMemberType autoDiscoverMemberType() default AutoDiscoverMemberType.NONE; /** @@ -74,9 +75,9 @@ interface NullSolutionCloner extends SolutionCloner { /** * @deprecated When multi-threaded solving, ensure your domain classes use @{@link PlanningId} instead. - * @return never null */ @Deprecated(forRemoval = true, since = "1.10.0") + @NonNull LookUpStrategyType lookUpStrategyType() default LookUpStrategyType.PLANNING_ID_OR_NONE; } diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/solution/cloner/SolutionCloner.java b/core/src/main/java/ai/timefold/solver/core/api/domain/solution/cloner/SolutionCloner.java index e6e6793f66..3419154d01 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/solution/cloner/SolutionCloner.java +++ b/core/src/main/java/ai/timefold/solver/core/api/domain/solution/cloner/SolutionCloner.java @@ -2,6 +2,8 @@ import ai.timefold.solver.core.api.domain.solution.PlanningSolution; +import org.jspecify.annotations.NonNull; + /** * Clones a {@link PlanningSolution} during planning. * Used to remember the state of a good {@link PlanningSolution} so it can be recalled at a later time @@ -34,9 +36,10 @@ public interface SolutionCloner { *

* This method is thread-safe. * - * @param original never null, the original {@link PlanningSolution} - * @return never null, the cloned {@link PlanningSolution} + * @param original the original {@link PlanningSolution} + * @return the cloned {@link PlanningSolution} */ - Solution_ cloneSolution(Solution_ original); + @NonNull + Solution_ cloneSolution(@NonNull Solution_ original); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/CountableValueRange.java b/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/CountableValueRange.java index e29c399d40..7732c1041e 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/CountableValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/CountableValueRange.java @@ -4,6 +4,9 @@ import ai.timefold.solver.core.api.domain.variable.PlanningVariable; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * A {@link ValueRange} that is ending. Therefore, it has a discrete (as in non-continuous) range. * @@ -27,13 +30,13 @@ public interface CountableValueRange extends ValueRange { * @param index always {@code <} {@link #getSize()} * @return sometimes null (if {@link PlanningVariable#allowsUnassigned()} is true) */ + @Nullable T get(long index); /** * Select the elements in original (natural) order. - * - * @return never null */ + @NonNull Iterator createOriginalIterator(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRange.java b/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRange.java index fa88719bab..59ae6c1ddb 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRange.java @@ -8,6 +8,9 @@ import ai.timefold.solver.core.api.domain.variable.PlanningVariable; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * A ValueRange is a set of a values for a {@link PlanningVariable}. * These values might be stored in memory as a {@link Collection} (usually a {@link List} or {@link Set}), @@ -34,17 +37,17 @@ public interface ValueRange { * @param value sometimes null * @return true if the ValueRange contains that value */ - boolean contains(T value); + boolean contains(@Nullable T value); /** * Select in random order, but without shuffling the elements. * Each element might be selected multiple times. * Scales well because it does not require caching. * - * @param workingRandom never null, the {@link Random} to use when any random number is needed, + * @param workingRandom the {@link Random} to use when any random number is needed, * so runs are reproducible. - * @return never null */ - Iterator createRandomIterator(Random workingRandom); + @NonNull + Iterator createRandomIterator(@NonNull Random workingRandom); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRangeFactory.java b/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRangeFactory.java index fd5c958acc..90a4bd0386 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRangeFactory.java +++ b/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRangeFactory.java @@ -16,6 +16,8 @@ import ai.timefold.solver.core.impl.domain.valuerange.buildin.primlong.LongValueRange; import ai.timefold.solver.core.impl.domain.valuerange.buildin.temporal.TemporalValueRange; +import org.jspecify.annotations.NonNull; + /** * Factory for {@link ValueRange}. */ @@ -23,10 +25,8 @@ public final class ValueRangeFactory { /** * Build a {@link CountableValueRange} of both {@code boolean} values. - * - * @return never null */ - public static CountableValueRange createBooleanValueRange() { + public static @NonNull CountableValueRange createBooleanValueRange() { return new BooleanValueRange(); } @@ -35,9 +35,8 @@ public static CountableValueRange createBooleanValueRange() { * * @param from inclusive minimum * @param to exclusive maximum, {@code >= from} - * @return never null */ - public static CountableValueRange createIntValueRange(int from, int to) { + public static @NonNull CountableValueRange createIntValueRange(int from, int to) { return new IntValueRange(from, to); } @@ -47,9 +46,8 @@ public static CountableValueRange createIntValueRange(int from, int to) * @param from inclusive minimum * @param to exclusive maximum, {@code >= from} * @param incrementUnit {@code > 0} - * @return never null */ - public static CountableValueRange createIntValueRange(int from, int to, int incrementUnit) { + public static @NonNull CountableValueRange createIntValueRange(int from, int to, int incrementUnit) { return new IntValueRange(from, to, incrementUnit); } @@ -58,9 +56,8 @@ public static CountableValueRange createIntValueRange(int from, int to, * * @param from inclusive minimum * @param to exclusive maximum, {@code >= from} - * @return never null */ - public static CountableValueRange createLongValueRange(long from, long to) { + public static @NonNull CountableValueRange createLongValueRange(long from, long to) { return new LongValueRange(from, to); } @@ -70,9 +67,8 @@ public static CountableValueRange createLongValueRange(long from, long to) * @param from inclusive minimum * @param to exclusive maximum, {@code >= from} * @param incrementUnit {@code > 0} - * @return never null */ - public static CountableValueRange createLongValueRange(long from, long to, long incrementUnit) { + public static @NonNull CountableValueRange createLongValueRange(long from, long to, long incrementUnit) { return new LongValueRange(from, to, incrementUnit); } @@ -81,11 +77,10 @@ public static CountableValueRange createLongValueRange(long from, long to, * * @param from inclusive minimum * @param to exclusive maximum, {@code >= from} - * @return never null * @deprecated Prefer {@link #createBigDecimalValueRange(BigDecimal, BigDecimal)}. */ @Deprecated(forRemoval = true, since = "1.1.0") - public static ValueRange createDoubleValueRange(double from, double to) { + public static @NonNull ValueRange createDoubleValueRange(double from, double to) { return new DoubleValueRange(from, to); } @@ -94,9 +89,9 @@ public static ValueRange createDoubleValueRange(double from, double to) * * @param from inclusive minimum * @param to exclusive maximum, {@code >= from} - * @return never null */ - public static CountableValueRange createBigIntegerValueRange(BigInteger from, BigInteger to) { + public static @NonNull CountableValueRange createBigIntegerValueRange(@NonNull BigInteger from, + @NonNull BigInteger to) { return new BigIntegerValueRange(from, to); } @@ -106,10 +101,10 @@ public static CountableValueRange createBigIntegerValueRange(BigInte * @param from inclusive minimum * @param to exclusive maximum, {@code >= from} * @param incrementUnit {@code > 0} - * @return never null */ - public static CountableValueRange createBigIntegerValueRange(BigInteger from, BigInteger to, - BigInteger incrementUnit) { + public static @NonNull CountableValueRange createBigIntegerValueRange(@NonNull BigInteger from, + @NonNull BigInteger to, + @NonNull BigInteger incrementUnit) { return new BigIntegerValueRange(from, to, incrementUnit); } @@ -119,9 +114,9 @@ public static CountableValueRange createBigIntegerValueRange(BigInte * * @param from inclusive minimum * @param to exclusive maximum, {@code >= from} - * @return never null */ - public static CountableValueRange createBigDecimalValueRange(BigDecimal from, BigDecimal to) { + public static @NonNull CountableValueRange createBigDecimalValueRange(@NonNull BigDecimal from, + @NonNull BigDecimal to) { return new BigDecimalValueRange(from, to); } @@ -132,10 +127,10 @@ public static CountableValueRange createBigDecimalValueRange(BigDeci * @param from inclusive minimum * @param to exclusive maximum, {@code >= from} * @param incrementUnit {@code > 0} - * @return never null */ - public static CountableValueRange createBigDecimalValueRange(BigDecimal from, BigDecimal to, - BigDecimal incrementUnit) { + public static @NonNull CountableValueRange createBigDecimalValueRange(@NonNull BigDecimal from, + @NonNull BigDecimal to, + @NonNull BigDecimal incrementUnit) { return new BigDecimalValueRange(from, to, incrementUnit); } @@ -144,13 +139,13 @@ public static CountableValueRange createBigDecimalValueRange(BigDeci *

* Facade for {@link #createTemporalValueRange(Temporal, Temporal, long, TemporalUnit)}. * - * @param from never null, inclusive minimum - * @param to never null, exclusive maximum, {@code >= from} + * @param from inclusive minimum + * @param to exclusive maximum, {@code >= from} * @param incrementUnitAmount {@code > 0} - * @param incrementUnitType never null, must be {@link LocalDate#isSupported(TemporalUnit) supported} + * @param incrementUnitType must be {@link LocalDate#isSupported(TemporalUnit) supported} */ - public static CountableValueRange createLocalDateValueRange( - LocalDate from, LocalDate to, long incrementUnitAmount, TemporalUnit incrementUnitType) { + public static @NonNull CountableValueRange createLocalDateValueRange( + @NonNull LocalDate from, @NonNull LocalDate to, long incrementUnitAmount, @NonNull TemporalUnit incrementUnitType) { return createTemporalValueRange(from, to, incrementUnitAmount, incrementUnitType); } @@ -159,13 +154,13 @@ public static CountableValueRange createLocalDateValueRange( *

* Facade for {@link #createTemporalValueRange(Temporal, Temporal, long, TemporalUnit)}. * - * @param from never null, inclusive minimum - * @param to never null, exclusive maximum, {@code >= from} + * @param from inclusive minimum + * @param to exclusive maximum, {@code >= from} * @param incrementUnitAmount {@code > 0} - * @param incrementUnitType never null, must be {@link LocalTime#isSupported(TemporalUnit) supported} + * @param incrementUnitType must be {@link LocalTime#isSupported(TemporalUnit) supported} */ public static CountableValueRange createLocalTimeValueRange( - LocalTime from, LocalTime to, long incrementUnitAmount, TemporalUnit incrementUnitType) { + @NonNull LocalTime from, @NonNull LocalTime to, long incrementUnitAmount, @NonNull TemporalUnit incrementUnitType) { return createTemporalValueRange(from, to, incrementUnitAmount, incrementUnitType); } @@ -174,13 +169,14 @@ public static CountableValueRange createLocalTimeValueRange( *

* Facade for {@link #createTemporalValueRange(Temporal, Temporal, long, TemporalUnit)}. * - * @param from never null, inclusive minimum - * @param to never null, exclusive maximum, {@code >= from} + * @param from inclusive minimum + * @param to exclusive maximum, {@code >= from} * @param incrementUnitAmount {@code > 0} - * @param incrementUnitType never null, must be {@link LocalDateTime#isSupported(TemporalUnit) supported} + * @param incrementUnitType must be {@link LocalDateTime#isSupported(TemporalUnit) supported} */ public static CountableValueRange createLocalDateTimeValueRange( - LocalDateTime from, LocalDateTime to, long incrementUnitAmount, TemporalUnit incrementUnitType) { + @NonNull LocalDateTime from, @NonNull LocalDateTime to, long incrementUnitAmount, + @NonNull TemporalUnit incrementUnitType) { return createTemporalValueRange(from, to, incrementUnitAmount, incrementUnitType); } @@ -189,14 +185,15 @@ public static CountableValueRange createLocalDateTimeValueRange( * {@link LocalDateTime}) between 2 bounds. * All parameters must have the same {@link TemporalUnit}. * - * @param from never null, inclusive minimum - * @param to never null, exclusive maximum, {@code >= from} + * @param from inclusive minimum + * @param to exclusive maximum, {@code >= from} * @param incrementUnitAmount {@code > 0} - * @param incrementUnitType never null, must be {@link Temporal#isSupported(TemporalUnit) supported} by {@code from} and + * @param incrementUnitType must be {@link Temporal#isSupported(TemporalUnit) supported} by {@code from} and * {@code to} */ - public static > CountableValueRange - createTemporalValueRange(Temporal_ from, Temporal_ to, long incrementUnitAmount, TemporalUnit incrementUnitType) { + public static > @NonNull CountableValueRange + createTemporalValueRange(@NonNull Temporal_ from, @NonNull Temporal_ to, long incrementUnitAmount, + @NonNull TemporalUnit incrementUnitType) { return new TemporalValueRange<>(from, to, incrementUnitAmount, incrementUnitType); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRangeProvider.java b/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRangeProvider.java index b2936cba25..4ab61e1a62 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRangeProvider.java +++ b/core/src/main/java/ai/timefold/solver/core/api/domain/valuerange/ValueRangeProvider.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.api.domain.variable.PlanningVariable; import ai.timefold.solver.core.api.solver.SolverFactory; +import org.jspecify.annotations.NonNull; + /** * Provides the planning values that can be used for a {@link PlanningVariable}. *

@@ -29,6 +31,7 @@ * * @return if provided, must be unique across a {@link SolverFactory} */ + @NonNull String id() default ""; } diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/variable/AbstractVariableListener.java b/core/src/main/java/ai/timefold/solver/core/api/domain/variable/AbstractVariableListener.java index a96c6d5770..c5db7f26cd 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/variable/AbstractVariableListener.java +++ b/core/src/main/java/ai/timefold/solver/core/api/domain/variable/AbstractVariableListener.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.api.domain.solution.PlanningSolution; import ai.timefold.solver.core.api.score.director.ScoreDirector; +import org.jspecify.annotations.NonNull; + /** * Common ancestor for specialized planning variable listeners. *

@@ -20,38 +22,20 @@ */ public interface AbstractVariableListener extends Closeable { - /** - * @param scoreDirector never null - * @param entity never null - */ - void beforeEntityAdded(ScoreDirector scoreDirector, Entity_ entity); + void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity); - /** - * @param scoreDirector never null - * @param entity never null - */ - void afterEntityAdded(ScoreDirector scoreDirector, Entity_ entity); + void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity); - /** - * @param scoreDirector never null - * @param entity never null - */ - void beforeEntityRemoved(ScoreDirector scoreDirector, Entity_ entity); + void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity); - /** - * @param scoreDirector never null - * @param entity never null - */ - void afterEntityRemoved(ScoreDirector scoreDirector, Entity_ entity); + void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity); /** * Called when the entire working solution changes. In this event, the other before..()/after...() methods will not * be called. * At this point, implementations should clear state, if any. - * - * @param scoreDirector never null */ - default void resetWorkingSolution(ScoreDirector scoreDirector) { + default void resetWorkingSolution(@NonNull ScoreDirector scoreDirector) { // No need to do anything for stateless implementations. } diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/variable/ListVariableListener.java b/core/src/main/java/ai/timefold/solver/core/api/domain/variable/ListVariableListener.java index a9eb78f407..590d009d82 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/variable/ListVariableListener.java +++ b/core/src/main/java/ai/timefold/solver/core/api/domain/variable/ListVariableListener.java @@ -4,6 +4,8 @@ import ai.timefold.solver.core.api.domain.solution.PlanningSolution; import ai.timefold.solver.core.api.score.director.ScoreDirector; +import org.jspecify.annotations.NonNull; + /** * A listener sourced on a {@link PlanningListVariable}. *

@@ -33,7 +35,7 @@ public interface ListVariableListener extends Abst * @param scoreDirector score director * @param element the unassigned element */ - void afterListVariableElementUnassigned(ScoreDirector scoreDirector, Element_ element); + void afterListVariableElementUnassigned(@NonNull ScoreDirector scoreDirector, @NonNull Element_ element); /** * Tells the listener that some elements within the range starting at {@code fromIndex} (inclusive) and ending at @@ -67,7 +69,8 @@ public interface ListVariableListener extends Abst * @param fromIndex low endpoint (inclusive) of the changed range * @param toIndex high endpoint (exclusive) of the changed range */ - void beforeListVariableChanged(ScoreDirector scoreDirector, Entity_ entity, int fromIndex, int toIndex); + void beforeListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity, int fromIndex, + int toIndex); /** * Tells the listener that some elements within the range starting at {@code fromIndex} (inclusive) and ending at @@ -98,5 +101,6 @@ public interface ListVariableListener extends Abst * @param fromIndex low endpoint (inclusive) of the changed range * @param toIndex high endpoint (exclusive) of the changed range */ - void afterListVariableChanged(ScoreDirector scoreDirector, Entity_ entity, int fromIndex, int toIndex); + void afterListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity, int fromIndex, + int toIndex); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/variable/VariableListener.java b/core/src/main/java/ai/timefold/solver/core/api/domain/variable/VariableListener.java index 89151a9cd5..503fa89431 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/variable/VariableListener.java +++ b/core/src/main/java/ai/timefold/solver/core/api/domain/variable/VariableListener.java @@ -4,6 +4,8 @@ import ai.timefold.solver.core.api.domain.solution.PlanningSolution; import ai.timefold.solver.core.api.score.director.ScoreDirector; +import org.jspecify.annotations.NonNull; + /** * A listener sourced on a basic {@link PlanningVariable}. *

@@ -35,15 +37,7 @@ default boolean requiresUniqueEntityEvents() { return false; } - /** - * @param scoreDirector never null - * @param entity never null - */ - void beforeVariableChanged(ScoreDirector scoreDirector, Entity_ entity); + void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity); - /** - * @param scoreDirector never null - * @param entity never null - */ - void afterVariableChanged(ScoreDirector scoreDirector, Entity_ entity); + void afterVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/function/PentaPredicate.java b/core/src/main/java/ai/timefold/solver/core/api/function/PentaPredicate.java index d6bba488a1..5916f3eb33 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/function/PentaPredicate.java +++ b/core/src/main/java/ai/timefold/solver/core/api/function/PentaPredicate.java @@ -3,6 +3,8 @@ import java.util.Objects; import java.util.function.Predicate; +import org.jspecify.annotations.NonNull; + /** * Represents a predicate (boolean-valued function) of five arguments. * This is the five-arity specialization of {@link Predicate}. @@ -51,8 +53,8 @@ public interface PentaPredicate { * AND of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ - default PentaPredicate and( - PentaPredicate other) { + default @NonNull PentaPredicate and( + @NonNull PentaPredicate other) { Objects.requireNonNull(other); return (A a, B b, C c, D d, E e) -> test(a, b, c, d, e) && other.test(a, b, c, d, e); } @@ -64,7 +66,7 @@ default PentaPredicate and( * @return a predicate that represents the logical negation of this * predicate */ - default PentaPredicate negate() { + default @NonNull PentaPredicate negate() { return (A a, B b, C c, D d, E e) -> !test(a, b, c, d, e); } @@ -84,8 +86,8 @@ default PentaPredicate negate() { * OR of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ - default PentaPredicate or( - PentaPredicate other) { + default @NonNull PentaPredicate or( + @NonNull PentaPredicate other) { Objects.requireNonNull(other); return (A a, B b, C c, D d, E e) -> test(a, b, c, d, e) || other.test(a, b, c, d, e); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/function/QuadPredicate.java b/core/src/main/java/ai/timefold/solver/core/api/function/QuadPredicate.java index e95bed713f..7b0ab2004d 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/function/QuadPredicate.java +++ b/core/src/main/java/ai/timefold/solver/core/api/function/QuadPredicate.java @@ -3,6 +3,8 @@ import java.util.Objects; import java.util.function.Predicate; +import org.jspecify.annotations.NonNull; + /** * Represents a predicate (boolean-valued function) of four arguments. * This is the four-arity specialization of {@link Predicate}. @@ -49,7 +51,7 @@ public interface QuadPredicate { * AND of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ - default QuadPredicate and(QuadPredicate other) { + default @NonNull QuadPredicate and(@NonNull QuadPredicate other) { Objects.requireNonNull(other); return (A a, B b, C c, D d) -> test(a, b, c, d) && other.test(a, b, c, d); } @@ -81,7 +83,7 @@ default QuadPredicate negate() { * OR of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ - default QuadPredicate or(QuadPredicate other) { + default @NonNull QuadPredicate or(@NonNull QuadPredicate other) { Objects.requireNonNull(other); return (A a, B b, C c, D d) -> test(a, b, c, d) || other.test(a, b, c, d); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/function/TriConsumer.java b/core/src/main/java/ai/timefold/solver/core/api/function/TriConsumer.java index 998f4a8cb9..424c1abc11 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/function/TriConsumer.java +++ b/core/src/main/java/ai/timefold/solver/core/api/function/TriConsumer.java @@ -4,6 +4,8 @@ import java.util.function.Consumer; import java.util.function.Function; +import org.jspecify.annotations.NonNull; + /** * Represents a function that accepts three arguments and returns no result. * This is the three-arity specialization of {@link Consumer}. @@ -30,7 +32,7 @@ public interface TriConsumer { */ void accept(A a, B b, C c); - default TriConsumer andThen(TriConsumer after) { + default @NonNull TriConsumer andThen(@NonNull TriConsumer after) { Objects.requireNonNull(after); return (a, b, c) -> { accept(a, b, c); diff --git a/core/src/main/java/ai/timefold/solver/core/api/function/TriPredicate.java b/core/src/main/java/ai/timefold/solver/core/api/function/TriPredicate.java index ec1bbb4ed0..856998c90b 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/function/TriPredicate.java +++ b/core/src/main/java/ai/timefold/solver/core/api/function/TriPredicate.java @@ -3,6 +3,8 @@ import java.util.Objects; import java.util.function.Predicate; +import org.jspecify.annotations.NonNull; + /** * Represents a predicate (boolean-valued function) of three arguments. * This is the three-arity specialization of {@link Predicate}. @@ -47,7 +49,7 @@ public interface TriPredicate { * AND of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ - default TriPredicate and(TriPredicate other) { + default @NonNull TriPredicate and(@NonNull TriPredicate other) { Objects.requireNonNull(other); return (A a, B b, C c) -> test(a, b, c) && other.test(a, b, c); } @@ -79,7 +81,7 @@ default TriPredicate negate() { * OR of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ - default TriPredicate or(TriPredicate other) { + default @NonNull TriPredicate or(@NonNull TriPredicate other) { Objects.requireNonNull(other); return (A a, B b, C c) -> test(a, b, c) || other.test(a, b, c); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/Score.java b/core/src/main/java/ai/timefold/solver/core/api/score/Score.java index 2b54827925..10c62c8cbf 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/Score.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/Score.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.buildin.simplebigdecimal.SimpleBigDecimalScore; import ai.timefold.solver.core.api.score.buildin.simplelong.SimpleLongScore; +import org.jspecify.annotations.NonNull; + /** * A Score is result of the score function (AKA fitness function) on a single possible solution. * @@ -59,6 +61,7 @@ default int getInitScore() { * @param newInitScore always negative (except in statistical calculations), 0 if all planning variables are initialized * @return equals score except that {@link #initScore()} is set to {@code newInitScore} */ + @NonNull Score_ withInitScore(int newInitScore); /** @@ -67,7 +70,8 @@ default int getInitScore() { * @param addend value to be added to this Score * @return this + addend */ - Score_ add(Score_ addend); + @NonNull + Score_ add(@NonNull Score_ addend); /** * Returns a Score whose value is (this - subtrahend). @@ -75,7 +79,8 @@ default int getInitScore() { * @param subtrahend value to be subtracted from this Score * @return this - subtrahend, rounded as necessary */ - Score_ subtract(Score_ subtrahend); + @NonNull + Score_ subtract(@NonNull Score_ subtrahend); /** * Returns a Score whose value is (this * multiplicand). @@ -87,6 +92,7 @@ default int getInitScore() { * @param multiplicand value to be multiplied by this Score. * @return this * multiplicand */ + @NonNull Score_ multiply(double multiplicand); /** @@ -99,6 +105,7 @@ default int getInitScore() { * @param divisor value by which this Score is to be divided * @return this / divisor */ + @NonNull Score_ divide(double divisor); /** @@ -111,6 +118,7 @@ default int getInitScore() { * @param exponent value by which this Score is to be powered * @return this ^ exponent */ + @NonNull Score_ power(double exponent); /** @@ -118,7 +126,7 @@ default int getInitScore() { * * @return - this */ - default Score_ negate() { + default @NonNull Score_ negate() { Score_ zero = zero(); Score_ current = (Score_) this; if (zero.equals(current)) { @@ -129,16 +137,14 @@ default Score_ negate() { /** * Returns a Score whose value is the absolute value of the score, i.e. |this|. - * - * @return never null */ + @NonNull Score_ abs(); /** * Returns a Score, all levels of which are zero. - * - * @return never null */ + @NonNull Score_ zero(); /** @@ -161,16 +167,14 @@ default boolean isZero() { * The level numbers do not contain the {@link #initScore()}. * For example: {@code -3init/-0hard/-7soft} also returns {@code new int{-0, -7}} * - * @return never null */ - Number[] toLevelNumbers(); + @NonNull + Number @NonNull [] toLevelNumbers(); /** * As defined by {@link #toLevelNumbers()}, only returns double[] instead of Number[]. - * - * @return never null */ - default double[] toLevelDoubles() { + default double @NonNull [] toLevelDoubles() { Number[] levelNumbers = toLevelNumbers(); double[] levelDoubles = new double[levelNumbers.length]; for (int i = 0; i < levelNumbers.length; i++) { @@ -205,9 +209,8 @@ default boolean isSolutionInitialized() { *

* Do not use this format to persist information as text, use {@link Object#toString()} instead, * so it can be parsed reliably. - * - * @return never null */ + @NonNull String toShortString(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/ScoreExplanation.java b/core/src/main/java/ai/timefold/solver/core/api/score/ScoreExplanation.java index 79ace01a7a..28091328e6 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/ScoreExplanation.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/ScoreExplanation.java @@ -18,6 +18,8 @@ import ai.timefold.solver.core.api.score.stream.DefaultConstraintJustification; import ai.timefold.solver.core.api.solver.SolutionManager; +import org.jspecify.annotations.NonNull; + /** * Build by {@link SolutionManager#explain(Object)} to hold {@link ConstraintMatchTotal}s and {@link Indictment}s * necessary to explain the quality of a particular {@link Score}. @@ -31,18 +33,16 @@ public interface ScoreExplanation> { /** * Retrieve the {@link PlanningSolution} that the score being explained comes from. - * - * @return never null */ + @NonNull Solution_ getSolution(); /** * Return the {@link Score} being explained. * If the specific {@link Score} type used by the {@link PlanningSolution} is required, * call {@link #getSolution()} and retrieve it from there. - * - * @return never null */ + @NonNull Score_ getScore(); /** @@ -56,9 +56,8 @@ public interface ScoreExplanation> { * Instead, to provide this information in a UI or a service, * use {@link ScoreExplanation#getConstraintMatchTotalMap()} and {@link ScoreExplanation#getIndictmentMap()} * and convert those into a domain-specific API. - * - * @return never null */ + @NonNull String getSummary(); /** @@ -66,10 +65,11 @@ public interface ScoreExplanation> { *

* The sum of {@link ConstraintMatchTotal#getScore()} equals {@link #getScore()}. * - * @return never null, the key is the constraintId + * @return the key is the constraintId * (to create one, use {@link ConstraintRef#composeConstraintId(String, String)}). * @see #getIndictmentMap() */ + @NonNull Map> getConstraintMatchTotalMap(); /** @@ -90,9 +90,10 @@ public interface ScoreExplanation> { * * * - * @return never null, all constraint matches + * @return all constraint matches * @see #getIndictmentMap() */ + @NonNull List getJustificationList(); /** @@ -100,12 +101,11 @@ public interface ScoreExplanation> { * justified with a given {@link ConstraintJustification} type. * Otherwise, as defined by {@link #getJustificationList()}. * - * @param constraintJustificationClass never null - * @return never null, all constraint matches associated with the given justification class + * @return all constraint matches associated with the given justification class * @see #getIndictmentMap() */ - default List - getJustificationList(Class constraintJustificationClass) { + default @NonNull List + getJustificationList(@NonNull Class constraintJustificationClass) { return getJustificationList() .stream() .filter(constraintJustification -> constraintJustificationClass @@ -123,10 +123,11 @@ public interface ScoreExplanation> { * because each {@link ConstraintMatch#getScore()} is counted * for each of the {@link ConstraintMatch#getIndictedObjectList() indicted objects}. * - * @return never null, the key is a {@link ProblemFactCollectionProperty problem fact} or a + * @return the key is a {@link ProblemFactCollectionProperty problem fact} or a * {@link PlanningEntity planning entity} * @see #getConstraintMatchTotalMap() */ + @NonNull Map> getIndictmentMap(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/analysis/ConstraintAnalysis.java b/core/src/main/java/ai/timefold/solver/core/api/score/analysis/ConstraintAnalysis.java index 05621ae14c..93710351a2 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/analysis/ConstraintAnalysis.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/analysis/ConstraintAnalysis.java @@ -18,31 +18,33 @@ import ai.timefold.solver.core.impl.score.constraint.DefaultConstraintMatchTotal; import ai.timefold.solver.core.impl.util.CollectionUtils; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Note: Users should never create instances of this type directly. * It is available transitively via {@link SolutionManager#analyze(Object)}. * * @param - * @param constraintRef never null - * @param weight never null - * @param score never null * @param matches null if analysis not available; * empty if constraint has no matches, but still non-zero constraint weight; * non-empty if constraint has matches. * This is a {@link List} to simplify access to individual elements, * but it contains no duplicates just like {@link HashSet} wouldn't. */ -public record ConstraintAnalysis>(ConstraintRef constraintRef, Score_ weight, - Score_ score, List> matches) { +public record ConstraintAnalysis>(@NonNull ConstraintRef constraintRef, @NonNull Score_ weight, + @NonNull Score_ score, @Nullable List> matches) { - static > ConstraintAnalysis of(ConstraintRef constraintRef, Score_ constraintWeight, - Score_ score) { + static > @NonNull ConstraintAnalysis of( + @NonNull ConstraintRef constraintRef, + @NonNull Score_ constraintWeight, + @NonNull Score_ score) { return new ConstraintAnalysis<>(constraintRef, constraintWeight, score, null); } public ConstraintAnalysis { Objects.requireNonNull(constraintRef); - if (weight == null) { + if (weight == null) { // TODO: clarify - why illegal arg exception vs NPE from requireNonNull? /* * Only possible in ConstraintMatchAwareIncrementalScoreCalculator and/or tests. * Easy doesn't support constraint analysis at all. @@ -172,18 +174,16 @@ public String constraintPackage() { * * @return equal to {@code constraintRef.constraintName()} */ - public String constraintName() { + public @NonNull String constraintName() { return constraintRef.constraintName(); } /** * Returns a diagnostic text that explains part of the score quality through the {@link ConstraintAnalysis} API. * The string is built fresh every time the method is called. - * - * @return never null */ @SuppressWarnings("java:S3457") - public String summarize() { + public @NonNull String summarize() { var summary = new StringBuilder(); summary.append(""" Explanation of score (%s): diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/analysis/MatchAnalysis.java b/core/src/main/java/ai/timefold/solver/core/api/score/analysis/MatchAnalysis.java index 1729bf04b2..7f9acdfe4f 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/analysis/MatchAnalysis.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/analysis/MatchAnalysis.java @@ -8,17 +8,16 @@ import ai.timefold.solver.core.api.score.stream.ConstraintProvider; import ai.timefold.solver.core.api.solver.SolutionManager; +import org.jspecify.annotations.NonNull; + /** * Note: Users should never create instances of this type directly. * It is available transitively via {@link SolutionManager#analyze(Object)}. * * @param - * @param constraintRef never null - * @param score never null - * @param justification never null */ -public record MatchAnalysis>(ConstraintRef constraintRef, Score_ score, - ConstraintJustification justification) implements Comparable> { +public record MatchAnalysis>(@NonNull ConstraintRef constraintRef, @NonNull Score_ score, + @NonNull ConstraintJustification justification) implements Comparable> { public MatchAnalysis { Objects.requireNonNull(constraintRef); diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/analysis/ScoreAnalysis.java b/core/src/main/java/ai/timefold/solver/core/api/score/analysis/ScoreAnalysis.java index 0454a36adc..413d0acbec 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/analysis/ScoreAnalysis.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/analysis/ScoreAnalysis.java @@ -20,6 +20,9 @@ import ai.timefold.solver.core.api.score.stream.ConstraintJustification; import ai.timefold.solver.core.api.solver.SolutionManager; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Represents the breakdown of a {@link Score} into individual {@link ConstraintAnalysis} instances, * one for each constraint. @@ -41,9 +44,7 @@ * Note: the constructors of this record are off-limits. * We ask users to use exclusively {@link SolutionManager#analyze(Object)} to obtain instances of this record. * - * @param score never null - * @param constraintMap never null; - * for each constraint identified by its {@link Constraint#getConstraintRef()}, + * @param constraintMap for each constraint identified by its {@link Constraint#getConstraintRef()}, * the {@link ConstraintAnalysis} that describes the impact of that constraint on the overall score. * Constraints are present even if they have no matches, unless their weight is zero; * zero-weight constraints are not present. @@ -52,8 +53,8 @@ * * @param */ -public record ScoreAnalysis>(Score_ score, - Map> constraintMap) { +public record ScoreAnalysis>(@NonNull Score_ score, + @NonNull Map> constraintMap) { static final int DEFAULT_SUMMARY_CONSTRAINT_MATCH_LIMIT = 3; @@ -78,10 +79,9 @@ public record ScoreAnalysis>(Score_ score, * Performs a lookup on {@link #constraintMap()}. * Equivalent to {@code constraintMap().get(constraintRef)}. * - * @param constraintRef never null * @return null if no constraint matches of such constraint are present */ - public ConstraintAnalysis getConstraintAnalysis(ConstraintRef constraintRef) { + public @Nullable ConstraintAnalysis getConstraintAnalysis(@NonNull ConstraintRef constraintRef) { return constraintMap.get(constraintRef); } @@ -89,20 +89,18 @@ public ConstraintAnalysis getConstraintAnalysis(ConstraintRef constraint * As defined by {@link #getConstraintAnalysis(ConstraintRef)} * where the arguments are first composed into a singular constraint ID. * - * @param constraintPackage never null - * @param constraintName never null * @return null if no constraint matches of such constraint are present * @deprecated Use {@link #getConstraintAnalysis(String)} instead. */ @Deprecated(forRemoval = true, since = "1.13.0") - public ConstraintAnalysis getConstraintAnalysis(String constraintPackage, String constraintName) { + public @Nullable ConstraintAnalysis getConstraintAnalysis(@NonNull String constraintPackage, + @NonNull String constraintName) { return getConstraintAnalysis(ConstraintRef.of(constraintPackage, constraintName)); } /** * As defined by {@link #getConstraintAnalysis(ConstraintRef)}. * - * @param constraintName never null * @return null if no constraint matches of such constraint are present * @throws IllegalStateException if multiple constraints with the same name are present, * which is possible if they are in different constraint packages. @@ -110,7 +108,7 @@ public ConstraintAnalysis getConstraintAnalysis(String constraintPackage * If you must use constraint packages, see {@link #getConstraintAnalysis(String, String)} * (also deprecated) and reach out to us to discuss your use case. */ - public ConstraintAnalysis getConstraintAnalysis(String constraintName) { + public @Nullable ConstraintAnalysis getConstraintAnalysis(@NonNull String constraintName) { var constraintAnalysisList = constraintMap.entrySet() .stream() .filter(entry -> entry.getKey().constraintName().equals(constraintName)) @@ -146,11 +144,8 @@ Multiple constraints with the same name (%s) are present in the score analysis. *

* If one {@link ScoreAnalysis} provides {@link MatchAnalysis} and the other doesn't, exception is thrown. * Such {@link ScoreAnalysis} instances are mutually incompatible. - * - * @param other never null - * @return never null */ - public ScoreAnalysis diff(ScoreAnalysis other) { + public @NonNull ScoreAnalysis diff(@NonNull ScoreAnalysis other) { var result = Stream.concat(constraintMap.keySet().stream(), other.constraintMap.keySet().stream()) .distinct() @@ -187,11 +182,9 @@ public Collection> constraintAnalyses() { * Instead, provide this information in a UI or a service, * use {@link ScoreAnalysis#constraintAnalyses()} * and convert those into a domain-specific API. - * - * @return never null */ @SuppressWarnings("java:S3457") - public String summarize() { + public @NonNull String summarize() { StringBuilder summary = new StringBuilder(); summary.append(""" Explanation of score (%s): diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/bendable/BendableScore.java b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/bendable/BendableScore.java index 0d6d74051f..4ae5b3f53b 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/bendable/BendableScore.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/bendable/BendableScore.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.score.ScoreUtil; import ai.timefold.solver.core.impl.score.buildin.BendableScoreDefinition; +import org.jspecify.annotations.NonNull; + /** * This {@link Score} is based on n levels of int constraints. * The number of levels is bendable at configuration time. @@ -21,11 +23,7 @@ */ public final class BendableScore implements IBendableScore { - /** - * @param scoreString never null - * @return never null - */ - public static BendableScore parseScore(String scoreString) { + public static @NonNull BendableScore parseScore(@NonNull String scoreString) { String[][] scoreTokens = ScoreUtil.parseBendableScoreTokens(BendableScore.class, scoreString); int initScore = ScoreUtil.parseInitScore(BendableScore.class, scoreString, scoreTokens[0][0]); int[] hardScores = new int[scoreTokens[1].length]; @@ -43,22 +41,21 @@ public static BendableScore parseScore(String scoreString) { * Creates a new {@link BendableScore}. * * @param initScore see {@link Score#initScore()} - * @param hardScores never null, never change that array afterwards: it must be immutable - * @param softScores never null, never change that array afterwards: it must be immutable - * @return never null + * @param hardScores never change that array afterwards: it must be immutable + * @param softScores never change that array afterwards: it must be immutable */ - public static BendableScore ofUninitialized(int initScore, int[] hardScores, int[] softScores) { + public static @NonNull BendableScore ofUninitialized(int initScore, int @NonNull [] hardScores, + int @NonNull [] softScores) { return new BendableScore(initScore, hardScores, softScores); } /** * Creates a new {@link BendableScore}. * - * @param hardScores never null, never change that array afterwards: it must be immutable - * @param softScores never null, never change that array afterwards: it must be immutable - * @return never null + * @param hardScores never change that array afterwards: it must be immutable + * @param softScores never change that array afterwards: it must be immutable */ - public static BendableScore of(int[] hardScores, int[] softScores) { + public static @NonNull BendableScore of(int @NonNull [] hardScores, int @NonNull [] softScores) { return new BendableScore(0, hardScores, softScores); } @@ -67,9 +64,8 @@ public static BendableScore of(int[] hardScores, int[] softScores) { * * @param hardLevelsSize at least 0 * @param softLevelsSize at least 0 - * @return never null */ - public static BendableScore zero(int hardLevelsSize, int softLevelsSize) { + public static @NonNull BendableScore zero(int hardLevelsSize, int softLevelsSize) { return new BendableScore(0, new int[hardLevelsSize], new int[softLevelsSize]); } @@ -80,9 +76,8 @@ public static BendableScore zero(int hardLevelsSize, int softLevelsSize) { * @param softLevelsSize at least 0 * @param hardLevel at least 0, less than hardLevelsSize * @param hardScore any - * @return never null */ - public static BendableScore ofHard(int hardLevelsSize, int softLevelsSize, int hardLevel, int hardScore) { + public static @NonNull BendableScore ofHard(int hardLevelsSize, int softLevelsSize, int hardLevel, int hardScore) { int[] hardScores = new int[hardLevelsSize]; hardScores[hardLevel] = hardScore; return new BendableScore(0, hardScores, new int[softLevelsSize]); @@ -95,9 +90,8 @@ public static BendableScore ofHard(int hardLevelsSize, int softLevelsSize, int h * @param softLevelsSize at least 0 * @param softLevel at least 0, less than softLevelsSize * @param softScore any - * @return never null */ - public static BendableScore ofSoft(int hardLevelsSize, int softLevelsSize, int softLevel, int softScore) { + public static @NonNull BendableScore ofSoft(int hardLevelsSize, int softLevelsSize, int softLevel, int softScore) { int[] softScores = new int[softLevelsSize]; softScores[softLevel] = softScore; return new BendableScore(0, new int[hardLevelsSize], softScores); @@ -118,15 +112,13 @@ public static BendableScore ofSoft(int hardLevelsSize, int softLevelsSize, int s */ @SuppressWarnings("unused") private BendableScore() { - this(Integer.MIN_VALUE, null, null); + this(Integer.MIN_VALUE, new int[] {}, new int[] {}); } /** * @param initScore see {@link Score#initScore()} - * @param hardScores never null - * @param softScores never null */ - private BendableScore(int initScore, int[] hardScores, int[] softScores) { + private BendableScore(int initScore, int @NonNull [] hardScores, int @NonNull [] softScores) { this.initScore = initScore; this.hardScores = hardScores; this.softScores = softScores; @@ -138,9 +130,9 @@ public int initScore() { } /** - * @return not null, array copy because this class is immutable + * @return array copy because this class is immutable */ - public int[] hardScores() { + public int @NonNull [] hardScores() { return Arrays.copyOf(hardScores, hardScores.length); } @@ -150,14 +142,14 @@ public int[] hardScores() { * @deprecated Use {@link #hardScores()} instead. */ @Deprecated(forRemoval = true) - public int[] getHardScores() { + public int @NonNull [] getHardScores() { return hardScores(); } /** - * @return not null, array copy because this class is immutable + * @return array copy because this class is immutable */ - public int[] softScores() { + public int @NonNull [] softScores() { return Arrays.copyOf(softScores, softScores.length); } @@ -167,7 +159,7 @@ public int[] softScores() { * @deprecated Use {@link #softScores()} instead. */ @Deprecated(forRemoval = true) - public int[] getSoftScores() { + public int @NonNull [] getSoftScores() { return softScores(); } @@ -224,7 +216,7 @@ public int getSoftScore(int hardLevel) { // ************************************************************************ @Override - public BendableScore withInitScore(int newInitScore) { + public @NonNull BendableScore withInitScore(int newInitScore) { return new BendableScore(newInitScore, hardScores, softScores); } @@ -264,7 +256,7 @@ public boolean isFeasible() { } @Override - public BendableScore add(BendableScore addend) { + public @NonNull BendableScore add(@NonNull BendableScore addend) { validateCompatible(addend); int[] newHardScores = new int[hardScores.length]; int[] newSoftScores = new int[softScores.length]; @@ -280,7 +272,7 @@ public BendableScore add(BendableScore addend) { } @Override - public BendableScore subtract(BendableScore subtrahend) { + public @NonNull BendableScore subtract(@NonNull BendableScore subtrahend) { validateCompatible(subtrahend); int[] newHardScores = new int[hardScores.length]; int[] newSoftScores = new int[softScores.length]; @@ -296,7 +288,7 @@ public BendableScore subtract(BendableScore subtrahend) { } @Override - public BendableScore multiply(double multiplicand) { + public @NonNull BendableScore multiply(double multiplicand) { int[] newHardScores = new int[hardScores.length]; int[] newSoftScores = new int[softScores.length]; for (int i = 0; i < newHardScores.length; i++) { @@ -311,7 +303,7 @@ public BendableScore multiply(double multiplicand) { } @Override - public BendableScore divide(double divisor) { + public @NonNull BendableScore divide(double divisor) { int[] newHardScores = new int[hardScores.length]; int[] newSoftScores = new int[softScores.length]; for (int i = 0; i < newHardScores.length; i++) { @@ -326,7 +318,7 @@ public BendableScore divide(double divisor) { } @Override - public BendableScore power(double exponent) { + public @NonNull BendableScore power(double exponent) { int[] newHardScores = new int[hardScores.length]; int[] newSoftScores = new int[softScores.length]; for (int i = 0; i < newHardScores.length; i++) { @@ -341,7 +333,7 @@ public BendableScore power(double exponent) { } @Override - public BendableScore negate() { // Overridden as the default impl would create zero() all the time. + public @NonNull BendableScore negate() { // Overridden as the default impl would create zero() all the time. int[] newHardScores = new int[hardScores.length]; int[] newSoftScores = new int[softScores.length]; for (int i = 0; i < newHardScores.length; i++) { @@ -354,7 +346,7 @@ public BendableScore negate() { // Overridden as the default impl would create z } @Override - public BendableScore abs() { + public @NonNull BendableScore abs() { int[] newHardScores = new int[hardScores.length]; int[] newSoftScores = new int[softScores.length]; for (int i = 0; i < newHardScores.length; i++) { @@ -367,12 +359,12 @@ public BendableScore abs() { } @Override - public BendableScore zero() { + public @NonNull BendableScore zero() { return BendableScore.zero(hardLevelsSize(), softLevelsSize()); } @Override - public Number[] toLevelNumbers() { + public Number @NonNull [] toLevelNumbers() { Number[] levelNumbers = new Number[hardScores.length + softScores.length]; for (int i = 0; i < hardScores.length; i++) { levelNumbers[i] = hardScores[i]; @@ -414,7 +406,7 @@ public int hashCode() { } @Override - public int compareTo(BendableScore other) { + public int compareTo(@NonNull BendableScore other) { validateCompatible(other); if (initScore != other.initScore()) { return Integer.compare(initScore, other.initScore()); @@ -433,7 +425,7 @@ public int compareTo(BendableScore other) { } @Override - public String toShortString() { + public @NonNull String toShortString() { return ScoreUtil.buildBendableShortString(this, n -> n.intValue() != 0); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/bendablebigdecimal/BendableBigDecimalScore.java b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/bendablebigdecimal/BendableBigDecimalScore.java index 3b746639de..2b5ba346b7 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/bendablebigdecimal/BendableBigDecimalScore.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/bendablebigdecimal/BendableBigDecimalScore.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.impl.score.ScoreUtil; import ai.timefold.solver.core.impl.score.buildin.BendableScoreDefinition; +import org.jspecify.annotations.NonNull; + /** * This {@link Score} is based on n levels of {@link BigDecimal} constraints. * The number of levels is bendable at configuration time. @@ -24,11 +26,7 @@ */ public final class BendableBigDecimalScore implements IBendableScore { - /** - * @param scoreString never null - * @return never null - */ - public static BendableBigDecimalScore parseScore(String scoreString) { + public static @NonNull BendableBigDecimalScore parseScore(@NonNull String scoreString) { String[][] scoreTokens = ScoreUtil.parseBendableScoreTokens(BendableBigDecimalScore.class, scoreString); int initScore = ScoreUtil.parseInitScore(BendableBigDecimalScore.class, scoreString, scoreTokens[0][0]); BigDecimal[] hardScores = new BigDecimal[scoreTokens[1].length]; @@ -46,22 +44,21 @@ public static BendableBigDecimalScore parseScore(String scoreString) { * Creates a new {@link BendableBigDecimalScore}. * * @param initScore see {@link Score#initScore()} - * @param hardScores never null, never change that array afterwards: it must be immutable - * @param softScores never null, never change that array afterwards: it must be immutable - * @return never null + * @param hardScores never change that array afterwards: it must be immutable + * @param softScores never change that array afterwards: it must be immutable */ - public static BendableBigDecimalScore ofUninitialized(int initScore, BigDecimal[] hardScores, BigDecimal[] softScores) { + public static @NonNull BendableBigDecimalScore ofUninitialized(int initScore, @NonNull BigDecimal @NonNull [] hardScores, + @NonNull BigDecimal @NonNull [] softScores) { return new BendableBigDecimalScore(initScore, hardScores, softScores); } /** * Creates a new {@link BendableBigDecimalScore}. * - * @param hardScores never null, never change that array afterwards: it must be immutable - * @param softScores never null, never change that array afterwards: it must be immutable - * @return never null + * @param hardScores never change that array afterwards: it must be immutable + * @param softScores never change that array afterwards: it must be immutable */ - public static BendableBigDecimalScore of(BigDecimal[] hardScores, BigDecimal[] softScores) { + public static @NonNull BendableBigDecimalScore of(BigDecimal @NonNull [] hardScores, BigDecimal @NonNull [] softScores) { return new BendableBigDecimalScore(0, hardScores, softScores); } @@ -70,9 +67,8 @@ public static BendableBigDecimalScore of(BigDecimal[] hardScores, BigDecimal[] s * * @param hardLevelsSize at least 0 * @param softLevelsSize at least 0 - * @return never null */ - public static BendableBigDecimalScore zero(int hardLevelsSize, int softLevelsSize) { + public static @NonNull BendableBigDecimalScore zero(int hardLevelsSize, int softLevelsSize) { BigDecimal[] hardScores = new BigDecimal[hardLevelsSize]; Arrays.fill(hardScores, BigDecimal.ZERO); BigDecimal[] softScores = new BigDecimal[softLevelsSize]; @@ -86,10 +82,9 @@ public static BendableBigDecimalScore zero(int hardLevelsSize, int softLevelsSiz * @param hardLevelsSize at least 0 * @param softLevelsSize at least 0 * @param hardLevel at least 0, less than hardLevelsSize - * @param hardScore never null - * @return never null */ - public static BendableBigDecimalScore ofHard(int hardLevelsSize, int softLevelsSize, int hardLevel, BigDecimal hardScore) { + public static @NonNull BendableBigDecimalScore ofHard(int hardLevelsSize, int softLevelsSize, int hardLevel, + @NonNull BigDecimal hardScore) { BigDecimal[] hardScores = new BigDecimal[hardLevelsSize]; Arrays.fill(hardScores, BigDecimal.ZERO); BigDecimal[] softScores = new BigDecimal[softLevelsSize]; @@ -104,10 +99,9 @@ public static BendableBigDecimalScore ofHard(int hardLevelsSize, int softLevelsS * @param hardLevelsSize at least 0 * @param softLevelsSize at least 0 * @param softLevel at least 0, less than softLevelsSize - * @param softScore never null - * @return never null */ - public static BendableBigDecimalScore ofSoft(int hardLevelsSize, int softLevelsSize, int softLevel, BigDecimal softScore) { + public static @NonNull BendableBigDecimalScore ofSoft(int hardLevelsSize, int softLevelsSize, int softLevel, + @NonNull BigDecimal softScore) { BigDecimal[] hardScores = new BigDecimal[hardLevelsSize]; Arrays.fill(hardScores, BigDecimal.ZERO); BigDecimal[] softScores = new BigDecimal[softLevelsSize]; @@ -121,8 +115,8 @@ public static BendableBigDecimalScore ofSoft(int hardLevelsSize, int softLevelsS // ************************************************************************ private final int initScore; - private final BigDecimal[] hardScores; - private final BigDecimal[] softScores; + private final @NonNull BigDecimal @NonNull [] hardScores; + private final @NonNull BigDecimal @NonNull [] softScores; /** * Private default constructor for default marshalling/unmarshalling of unknown frameworks that use reflection. @@ -131,15 +125,14 @@ public static BendableBigDecimalScore ofSoft(int hardLevelsSize, int softLevelsS */ @SuppressWarnings("unused") private BendableBigDecimalScore() { - this(Integer.MIN_VALUE, null, null); + this(Integer.MIN_VALUE, new BigDecimal[] {}, new BigDecimal[] {}); } /** * @param initScore see {@link Score#initScore()} - * @param hardScores never null - * @param softScores never null */ - private BendableBigDecimalScore(int initScore, BigDecimal[] hardScores, BigDecimal[] softScores) { + private BendableBigDecimalScore(int initScore, @NonNull BigDecimal @NonNull [] hardScores, + @NonNull BigDecimal @NonNull [] softScores) { this.initScore = initScore; this.hardScores = hardScores; this.softScores = softScores; @@ -151,9 +144,9 @@ public int initScore() { } /** - * @return not null, array copy because this class is immutable + * @return array copy because this class is immutable */ - public BigDecimal[] hardScores() { + public @NonNull BigDecimal @NonNull [] hardScores() { return Arrays.copyOf(hardScores, hardScores.length); } @@ -163,14 +156,14 @@ public BigDecimal[] hardScores() { * @deprecated Use {@link #hardScores()} instead. */ @Deprecated(forRemoval = true) - public BigDecimal[] getHardScores() { + public @NonNull BigDecimal @NonNull [] getHardScores() { return hardScores(); } /** - * @return not null, array copy because this class is immutable + * @return array copy because this class is immutable */ - public BigDecimal[] softScores() { + public @NonNull BigDecimal @NonNull [] softScores() { return Arrays.copyOf(softScores, softScores.length); } @@ -180,7 +173,7 @@ public BigDecimal[] softScores() { * @deprecated Use {@link #softScores()} instead. */ @Deprecated(forRemoval = true) - public BigDecimal[] getSoftScores() { + public @NonNull BigDecimal @NonNull [] getSoftScores() { return softScores(); } @@ -193,7 +186,7 @@ public int hardLevelsSize() { * @param index {@code 0 <= index <} {@link #hardLevelsSize()} * @return higher is better */ - public BigDecimal hardScore(int index) { + public @NonNull BigDecimal hardScore(int index) { return hardScores[index]; } @@ -203,7 +196,7 @@ public BigDecimal hardScore(int index) { * @deprecated Use {@link #hardScore(int)} instead. */ @Deprecated(forRemoval = true) - public BigDecimal getHardScore(int index) { + public @NonNull BigDecimal getHardScore(int index) { return hardScore(index); } @@ -216,7 +209,7 @@ public int softLevelsSize() { * @param index {@code 0 <= index <} {@link #softLevelsSize()} * @return higher is better */ - public BigDecimal softScore(int index) { + public @NonNull BigDecimal softScore(int index) { return softScores[index]; } @@ -226,7 +219,7 @@ public BigDecimal softScore(int index) { * @deprecated Use {@link #softScore(int)} instead. */ @Deprecated(forRemoval = true) - public BigDecimal getSoftScore(int index) { + public @NonNull BigDecimal getSoftScore(int index) { return softScore(index); } @@ -235,7 +228,7 @@ public BigDecimal getSoftScore(int index) { // ************************************************************************ @Override - public BendableBigDecimalScore withInitScore(int newInitScore) { + public @NonNull BendableBigDecimalScore withInitScore(int newInitScore) { return new BendableBigDecimalScore(newInitScore, hardScores, softScores); } @@ -243,7 +236,7 @@ public BendableBigDecimalScore withInitScore(int newInitScore) { * @param index {@code 0 <= index <} {@link #levelsSize()} * @return higher is better */ - public BigDecimal hardOrSoftScore(int index) { + public @NonNull BigDecimal hardOrSoftScore(int index) { if (index < hardScores.length) { return hardScores[index]; } else { @@ -257,7 +250,7 @@ public BigDecimal hardOrSoftScore(int index) { * @deprecated Use {@link #hardOrSoftScore(int)} instead. */ @Deprecated(forRemoval = true) - public BigDecimal getHardOrSoftScore(int index) { + public @NonNull BigDecimal getHardOrSoftScore(int index) { return hardOrSoftScore(index); } @@ -275,7 +268,7 @@ public boolean isFeasible() { } @Override - public BendableBigDecimalScore add(BendableBigDecimalScore addend) { + public @NonNull BendableBigDecimalScore add(@NonNull BendableBigDecimalScore addend) { validateCompatible(addend); BigDecimal[] newHardScores = new BigDecimal[hardScores.length]; BigDecimal[] newSoftScores = new BigDecimal[softScores.length]; @@ -291,7 +284,7 @@ public BendableBigDecimalScore add(BendableBigDecimalScore addend) { } @Override - public BendableBigDecimalScore subtract(BendableBigDecimalScore subtrahend) { + public @NonNull BendableBigDecimalScore subtract(@NonNull BendableBigDecimalScore subtrahend) { validateCompatible(subtrahend); BigDecimal[] newHardScores = new BigDecimal[hardScores.length]; BigDecimal[] newSoftScores = new BigDecimal[softScores.length]; @@ -307,7 +300,7 @@ public BendableBigDecimalScore subtract(BendableBigDecimalScore subtrahend) { } @Override - public BendableBigDecimalScore multiply(double multiplicand) { + public @NonNull BendableBigDecimalScore multiply(double multiplicand) { BigDecimal[] newHardScores = new BigDecimal[hardScores.length]; BigDecimal[] newSoftScores = new BigDecimal[softScores.length]; BigDecimal bigDecimalMultiplicand = BigDecimal.valueOf(multiplicand); @@ -327,7 +320,7 @@ public BendableBigDecimalScore multiply(double multiplicand) { } @Override - public BendableBigDecimalScore divide(double divisor) { + public @NonNull BendableBigDecimalScore divide(double divisor) { BigDecimal[] newHardScores = new BigDecimal[hardScores.length]; BigDecimal[] newSoftScores = new BigDecimal[softScores.length]; BigDecimal bigDecimalDivisor = BigDecimal.valueOf(divisor); @@ -345,7 +338,7 @@ public BendableBigDecimalScore divide(double divisor) { } @Override - public BendableBigDecimalScore power(double exponent) { + public @NonNull BendableBigDecimalScore power(double exponent) { BigDecimal[] newHardScores = new BigDecimal[hardScores.length]; BigDecimal[] newSoftScores = new BigDecimal[softScores.length]; BigDecimal actualExponent = BigDecimal.valueOf(exponent); @@ -366,7 +359,7 @@ public BendableBigDecimalScore power(double exponent) { } @Override - public BendableBigDecimalScore negate() { // Overridden as the default impl would create zero() all the time. + public @NonNull BendableBigDecimalScore negate() { // Overridden as the default impl would create zero() all the time. BigDecimal[] newHardScores = new BigDecimal[hardScores.length]; BigDecimal[] newSoftScores = new BigDecimal[softScores.length]; for (int i = 0; i < newHardScores.length; i++) { @@ -379,7 +372,7 @@ public BendableBigDecimalScore negate() { // Overridden as the default impl woul } @Override - public BendableBigDecimalScore abs() { + public @NonNull BendableBigDecimalScore abs() { BigDecimal[] newHardScores = new BigDecimal[hardScores.length]; BigDecimal[] newSoftScores = new BigDecimal[softScores.length]; for (int i = 0; i < newHardScores.length; i++) { @@ -392,12 +385,12 @@ public BendableBigDecimalScore abs() { } @Override - public BendableBigDecimalScore zero() { + public @NonNull BendableBigDecimalScore zero() { return BendableBigDecimalScore.zero(hardLevelsSize(), softLevelsSize()); } @Override - public Number[] toLevelNumbers() { + public @NonNull Number @NonNull [] toLevelNumbers() { Number[] levelNumbers = new Number[hardScores.length + softScores.length]; for (int i = 0; i < hardScores.length; i++) { levelNumbers[i] = hardScores[i]; @@ -443,7 +436,7 @@ public int hashCode() { } @Override - public int compareTo(BendableBigDecimalScore other) { + public int compareTo(@NonNull BendableBigDecimalScore other) { validateCompatible(other); if (initScore != other.initScore()) { return Integer.compare(initScore, other.initScore()); @@ -464,7 +457,7 @@ public int compareTo(BendableBigDecimalScore other) { } @Override - public String toShortString() { + public @NonNull String toShortString() { return ScoreUtil.buildBendableShortString(this, n -> ((BigDecimal) n).compareTo(BigDecimal.ZERO) != 0); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/bendablelong/BendableLongScore.java b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/bendablelong/BendableLongScore.java index d73dd6482d..f26b2398c9 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/bendablelong/BendableLongScore.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/bendablelong/BendableLongScore.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.score.ScoreUtil; import ai.timefold.solver.core.impl.score.buildin.BendableLongScoreDefinition; +import org.jspecify.annotations.NonNull; + /** * This {@link Score} is based on n levels of long constraints. * The number of levels is bendable at configuration time. @@ -21,11 +23,7 @@ */ public final class BendableLongScore implements IBendableScore { - /** - * @param scoreString never null - * @return never null - */ - public static BendableLongScore parseScore(String scoreString) { + public static @NonNull BendableLongScore parseScore(@NonNull String scoreString) { String[][] scoreTokens = ScoreUtil.parseBendableScoreTokens(BendableLongScore.class, scoreString); int initScore = ScoreUtil.parseInitScore(BendableLongScore.class, scoreString, scoreTokens[0][0]); long[] hardScores = new long[scoreTokens[1].length]; @@ -43,22 +41,21 @@ public static BendableLongScore parseScore(String scoreString) { * Creates a new {@link BendableLongScore}. * * @param initScore see {@link Score#initScore()} - * @param hardScores never null, never change that array afterwards: it must be immutable - * @param softScores never null, never change that array afterwards: it must be immutable - * @return never null + * @param hardScores never change that array afterwards: it must be immutable + * @param softScores never change that array afterwards: it must be immutable */ - public static BendableLongScore ofUninitialized(int initScore, long[] hardScores, long[] softScores) { + public static @NonNull BendableLongScore ofUninitialized(int initScore, long @NonNull [] hardScores, + long @NonNull [] softScores) { return new BendableLongScore(initScore, hardScores, softScores); } /** * Creates a new {@link BendableLongScore}. * - * @param hardScores never null, never change that array afterwards: it must be immutable - * @param softScores never null, never change that array afterwards: it must be immutable - * @return never null + * @param hardScores never change that array afterwards: it must be immutable + * @param softScores never change that array afterwards: it must be immutable */ - public static BendableLongScore of(long[] hardScores, long[] softScores) { + public static @NonNull BendableLongScore of(long @NonNull [] hardScores, long @NonNull [] softScores) { return new BendableLongScore(0, hardScores, softScores); } @@ -67,9 +64,8 @@ public static BendableLongScore of(long[] hardScores, long[] softScores) { * * @param hardLevelsSize at least 0 * @param softLevelsSize at least 0 - * @return never null */ - public static BendableLongScore zero(int hardLevelsSize, int softLevelsSize) { + public static @NonNull BendableLongScore zero(int hardLevelsSize, int softLevelsSize) { return new BendableLongScore(0, new long[hardLevelsSize], new long[softLevelsSize]); } @@ -80,9 +76,8 @@ public static BendableLongScore zero(int hardLevelsSize, int softLevelsSize) { * @param softLevelsSize at least 0 * @param hardLevel at least 0, less than hardLevelsSize * @param hardScore any - * @return never null */ - public static BendableLongScore ofHard(int hardLevelsSize, int softLevelsSize, int hardLevel, long hardScore) { + public static @NonNull BendableLongScore ofHard(int hardLevelsSize, int softLevelsSize, int hardLevel, long hardScore) { long[] hardScores = new long[hardLevelsSize]; hardScores[hardLevel] = hardScore; return new BendableLongScore(0, hardScores, new long[softLevelsSize]); @@ -95,9 +90,8 @@ public static BendableLongScore ofHard(int hardLevelsSize, int softLevelsSize, i * @param softLevelsSize at least 0 * @param softLevel at least 0, less than softLevelsSize * @param softScore any - * @return never null */ - public static BendableLongScore ofSoft(int hardLevelsSize, int softLevelsSize, int softLevel, long softScore) { + public static @NonNull BendableLongScore ofSoft(int hardLevelsSize, int softLevelsSize, int softLevel, long softScore) { long[] softScores = new long[softLevelsSize]; softScores[softLevel] = softScore; return new BendableLongScore(0, new long[hardLevelsSize], softScores); @@ -118,15 +112,13 @@ public static BendableLongScore ofSoft(int hardLevelsSize, int softLevelsSize, i */ @SuppressWarnings("unused") private BendableLongScore() { - this(Integer.MIN_VALUE, null, null); + this(Integer.MIN_VALUE, new long[] {}, new long[] {}); } /** * @param initScore see {@link Score#initScore()} - * @param hardScores never null - * @param softScores never null */ - private BendableLongScore(int initScore, long[] hardScores, long[] softScores) { + private BendableLongScore(int initScore, long @NonNull [] hardScores, long @NonNull [] softScores) { this.initScore = initScore; this.hardScores = hardScores; this.softScores = softScores; @@ -138,9 +130,9 @@ public int initScore() { } /** - * @return not null, array copy because this class is immutable + * @return array copy because this class is immutable */ - public long[] hardScores() { + public long @NonNull [] hardScores() { return Arrays.copyOf(hardScores, hardScores.length); } @@ -150,14 +142,14 @@ public long[] hardScores() { * @deprecated Use {@link #hardScores()} instead. */ @Deprecated(forRemoval = true) - public long[] getHardScores() { + public long @NonNull [] getHardScores() { return hardScores(); } /** - * @return not null, array copy because this class is immutable + * @return array copy because this class is immutable */ - public long[] softScores() { + public long @NonNull [] softScores() { return Arrays.copyOf(softScores, softScores.length); } @@ -167,7 +159,7 @@ public long[] softScores() { * @deprecated Use {@link #softScores()} instead. */ @Deprecated(forRemoval = true) - public long[] getSoftScores() { + public long @NonNull [] getSoftScores() { return softScores(); } @@ -222,7 +214,7 @@ public long getSoftScore(int index) { // ************************************************************************ @Override - public BendableLongScore withInitScore(int newInitScore) { + public @NonNull BendableLongScore withInitScore(int newInitScore) { return new BendableLongScore(newInitScore, hardScores, softScores); } @@ -262,7 +254,7 @@ public boolean isFeasible() { } @Override - public BendableLongScore add(BendableLongScore addend) { + public @NonNull BendableLongScore add(@NonNull BendableLongScore addend) { validateCompatible(addend); long[] newHardScores = new long[hardScores.length]; long[] newSoftScores = new long[softScores.length]; @@ -278,7 +270,7 @@ public BendableLongScore add(BendableLongScore addend) { } @Override - public BendableLongScore subtract(BendableLongScore subtrahend) { + public @NonNull BendableLongScore subtract(@NonNull BendableLongScore subtrahend) { validateCompatible(subtrahend); long[] newHardScores = new long[hardScores.length]; long[] newSoftScores = new long[softScores.length]; @@ -294,7 +286,7 @@ public BendableLongScore subtract(BendableLongScore subtrahend) { } @Override - public BendableLongScore multiply(double multiplicand) { + public @NonNull BendableLongScore multiply(double multiplicand) { long[] newHardScores = new long[hardScores.length]; long[] newSoftScores = new long[softScores.length]; for (int i = 0; i < newHardScores.length; i++) { @@ -309,7 +301,7 @@ public BendableLongScore multiply(double multiplicand) { } @Override - public BendableLongScore divide(double divisor) { + public @NonNull BendableLongScore divide(double divisor) { long[] newHardScores = new long[hardScores.length]; long[] newSoftScores = new long[softScores.length]; for (int i = 0; i < newHardScores.length; i++) { @@ -324,7 +316,7 @@ public BendableLongScore divide(double divisor) { } @Override - public BendableLongScore power(double exponent) { + public @NonNull BendableLongScore power(double exponent) { long[] newHardScores = new long[hardScores.length]; long[] newSoftScores = new long[softScores.length]; for (int i = 0; i < newHardScores.length; i++) { @@ -339,7 +331,7 @@ public BendableLongScore power(double exponent) { } @Override - public BendableLongScore negate() { // Overridden as the default impl would create zero() all the time. + public @NonNull BendableLongScore negate() { // Overridden as the default impl would create zero() all the time. long[] newHardScores = new long[hardScores.length]; long[] newSoftScores = new long[softScores.length]; for (int i = 0; i < newHardScores.length; i++) { @@ -352,7 +344,7 @@ public BendableLongScore negate() { // Overridden as the default impl would crea } @Override - public BendableLongScore abs() { + public @NonNull BendableLongScore abs() { long[] newHardScores = new long[hardScores.length]; long[] newSoftScores = new long[softScores.length]; for (int i = 0; i < newHardScores.length; i++) { @@ -365,12 +357,12 @@ public BendableLongScore abs() { } @Override - public BendableLongScore zero() { + public @NonNull BendableLongScore zero() { return BendableLongScore.zero(hardLevelsSize(), softLevelsSize()); } @Override - public Number[] toLevelNumbers() { + public Number @NonNull [] toLevelNumbers() { Number[] levelNumbers = new Number[hardScores.length + softScores.length]; for (int i = 0; i < hardScores.length; i++) { levelNumbers[i] = hardScores[i]; @@ -412,7 +404,7 @@ public int hashCode() { } @Override - public int compareTo(BendableLongScore other) { + public int compareTo(@NonNull BendableLongScore other) { validateCompatible(other); if (initScore != other.initScore()) { return Integer.compare(initScore, other.initScore()); @@ -431,7 +423,7 @@ public int compareTo(BendableLongScore other) { } @Override - public String toShortString() { + public @NonNull String toShortString() { return ScoreUtil.buildBendableShortString(this, n -> n.longValue() != 0L); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardmediumsoft/HardMediumSoftScore.java b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardmediumsoft/HardMediumSoftScore.java index fa7b255d9e..08a704b0b7 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardmediumsoft/HardMediumSoftScore.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardmediumsoft/HardMediumSoftScore.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.impl.score.ScoreUtil; +import org.jspecify.annotations.NonNull; + /** * This {@link Score} is based on 3 levels of int constraints: hard, medium and soft. * Hard constraints have priority over medium constraints. @@ -22,15 +24,15 @@ */ public final class HardMediumSoftScore implements Score { - public static final HardMediumSoftScore ZERO = new HardMediumSoftScore(0, 0, 0, 0); - public static final HardMediumSoftScore ONE_HARD = new HardMediumSoftScore(0, 1, 0, 0); - private static final HardMediumSoftScore MINUS_ONE_HARD = new HardMediumSoftScore(0, -1, 0, 0); - public static final HardMediumSoftScore ONE_MEDIUM = new HardMediumSoftScore(0, 0, 1, 0); - private static final HardMediumSoftScore MINUS_ONE_MEDIUM = new HardMediumSoftScore(0, 0, -1, 0); - public static final HardMediumSoftScore ONE_SOFT = new HardMediumSoftScore(0, 0, 0, 1); - private static final HardMediumSoftScore MINUS_ONE_SOFT = new HardMediumSoftScore(0, 0, 0, -1); + public static final @NonNull HardMediumSoftScore ZERO = new HardMediumSoftScore(0, 0, 0, 0); + public static final @NonNull HardMediumSoftScore ONE_HARD = new HardMediumSoftScore(0, 1, 0, 0); + private static final @NonNull HardMediumSoftScore MINUS_ONE_HARD = new HardMediumSoftScore(0, -1, 0, 0); + public static final @NonNull HardMediumSoftScore ONE_MEDIUM = new HardMediumSoftScore(0, 0, 1, 0); + private static final @NonNull HardMediumSoftScore MINUS_ONE_MEDIUM = new HardMediumSoftScore(0, 0, -1, 0); + public static final @NonNull HardMediumSoftScore ONE_SOFT = new HardMediumSoftScore(0, 0, 0, 1); + private static final @NonNull HardMediumSoftScore MINUS_ONE_SOFT = new HardMediumSoftScore(0, 0, 0, -1); - public static HardMediumSoftScore parseScore(String scoreString) { + public static @NonNull HardMediumSoftScore parseScore(@NonNull String scoreString) { String[] scoreTokens = ScoreUtil.parseScoreTokens(HardMediumSoftScore.class, scoreString, HARD_LABEL, MEDIUM_LABEL, SOFT_LABEL); int initScore = ScoreUtil.parseInitScore(HardMediumSoftScore.class, scoreString, scoreTokens[0]); @@ -40,14 +42,14 @@ public static HardMediumSoftScore parseScore(String scoreString) { return ofUninitialized(initScore, hardScore, mediumScore, softScore); } - public static HardMediumSoftScore ofUninitialized(int initScore, int hardScore, int mediumScore, int softScore) { + public static @NonNull HardMediumSoftScore ofUninitialized(int initScore, int hardScore, int mediumScore, int softScore) { if (initScore == 0) { return of(hardScore, mediumScore, softScore); } return new HardMediumSoftScore(initScore, hardScore, mediumScore, softScore); } - public static HardMediumSoftScore of(int hardScore, int mediumScore, int softScore) { + public static @NonNull HardMediumSoftScore of(int hardScore, int mediumScore, int softScore) { if (hardScore == -1 && mediumScore == 0 && softScore == 0) { return MINUS_ONE_HARD; } else if (hardScore == 0) { @@ -70,7 +72,7 @@ public static HardMediumSoftScore of(int hardScore, int mediumScore, int softSco return new HardMediumSoftScore(0, hardScore, mediumScore, softScore); } - public static HardMediumSoftScore ofHard(int hardScore) { + public static @NonNull HardMediumSoftScore ofHard(int hardScore) { return switch (hardScore) { case -1 -> MINUS_ONE_HARD; case 0 -> ZERO; @@ -79,7 +81,7 @@ public static HardMediumSoftScore ofHard(int hardScore) { }; } - public static HardMediumSoftScore ofMedium(int mediumScore) { + public static @NonNull HardMediumSoftScore ofMedium(int mediumScore) { return switch (mediumScore) { case -1 -> MINUS_ONE_MEDIUM; case 0 -> ZERO; @@ -88,7 +90,7 @@ public static HardMediumSoftScore ofMedium(int mediumScore) { }; } - public static HardMediumSoftScore ofSoft(int softScore) { + public static @NonNull HardMediumSoftScore ofSoft(int softScore) { return switch (softScore) { case -1 -> MINUS_ONE_SOFT; case 0 -> ZERO; @@ -200,7 +202,7 @@ public int getSoftScore() { // ************************************************************************ @Override - public HardMediumSoftScore withInitScore(int newInitScore) { + public @NonNull HardMediumSoftScore withInitScore(int newInitScore) { return ofUninitialized(newInitScore, hardScore, mediumScore, softScore); } @@ -215,7 +217,7 @@ public boolean isFeasible() { } @Override - public HardMediumSoftScore add(HardMediumSoftScore addend) { + public @NonNull HardMediumSoftScore add(@NonNull HardMediumSoftScore addend) { return ofUninitialized( initScore + addend.initScore(), hardScore + addend.hardScore(), @@ -224,7 +226,7 @@ public HardMediumSoftScore add(HardMediumSoftScore addend) { } @Override - public HardMediumSoftScore subtract(HardMediumSoftScore subtrahend) { + public @NonNull HardMediumSoftScore subtract(@NonNull HardMediumSoftScore subtrahend) { return ofUninitialized( initScore - subtrahend.initScore(), hardScore - subtrahend.hardScore(), @@ -233,7 +235,7 @@ public HardMediumSoftScore subtract(HardMediumSoftScore subtrahend) { } @Override - public HardMediumSoftScore multiply(double multiplicand) { + public @NonNull HardMediumSoftScore multiply(double multiplicand) { return ofUninitialized( (int) Math.floor(initScore * multiplicand), (int) Math.floor(hardScore * multiplicand), @@ -242,7 +244,7 @@ public HardMediumSoftScore multiply(double multiplicand) { } @Override - public HardMediumSoftScore divide(double divisor) { + public @NonNull HardMediumSoftScore divide(double divisor) { return ofUninitialized( (int) Math.floor(initScore / divisor), (int) Math.floor(hardScore / divisor), @@ -251,7 +253,7 @@ public HardMediumSoftScore divide(double divisor) { } @Override - public HardMediumSoftScore power(double exponent) { + public @NonNull HardMediumSoftScore power(double exponent) { return ofUninitialized( (int) Math.floor(Math.pow(initScore, exponent)), (int) Math.floor(Math.pow(hardScore, exponent)), @@ -260,17 +262,17 @@ public HardMediumSoftScore power(double exponent) { } @Override - public HardMediumSoftScore abs() { + public @NonNull HardMediumSoftScore abs() { return ofUninitialized(Math.abs(initScore), Math.abs(hardScore), Math.abs(mediumScore), Math.abs(softScore)); } @Override - public HardMediumSoftScore zero() { + public @NonNull HardMediumSoftScore zero() { return HardMediumSoftScore.ZERO; } @Override - public Number[] toLevelNumbers() { + public Number @NonNull [] toLevelNumbers() { return new Number[] { hardScore, mediumScore, softScore }; } @@ -291,7 +293,7 @@ public int hashCode() { } @Override - public int compareTo(HardMediumSoftScore other) { + public int compareTo(@NonNull HardMediumSoftScore other) { if (initScore != other.initScore()) { return Integer.compare(initScore, other.initScore()); } else if (hardScore != other.hardScore()) { @@ -304,7 +306,7 @@ public int compareTo(HardMediumSoftScore other) { } @Override - public String toShortString() { + public @NonNull String toShortString() { return ScoreUtil.buildShortString(this, n -> n.intValue() != 0, HARD_LABEL, MEDIUM_LABEL, SOFT_LABEL); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardmediumsoftbigdecimal/HardMediumSoftBigDecimalScore.java b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardmediumsoftbigdecimal/HardMediumSoftBigDecimalScore.java index 51d63db2a4..977491beb8 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardmediumsoftbigdecimal/HardMediumSoftBigDecimalScore.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardmediumsoftbigdecimal/HardMediumSoftBigDecimalScore.java @@ -12,6 +12,8 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.impl.score.ScoreUtil; +import org.jspecify.annotations.NonNull; + /** * This {@link Score} is based on 3 levels of {@link BigDecimal} constraints: hard, medium and soft. * Hard constraints have priority over medium constraints. @@ -24,23 +26,25 @@ */ public final class HardMediumSoftBigDecimalScore implements Score { - public static final HardMediumSoftBigDecimalScore ZERO = new HardMediumSoftBigDecimalScore(0, BigDecimal.ZERO, + public static final @NonNull HardMediumSoftBigDecimalScore ZERO = new HardMediumSoftBigDecimalScore(0, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO); - public static final HardMediumSoftBigDecimalScore ONE_HARD = new HardMediumSoftBigDecimalScore(0, BigDecimal.ONE, + public static final @NonNull HardMediumSoftBigDecimalScore ONE_HARD = new HardMediumSoftBigDecimalScore(0, BigDecimal.ONE, BigDecimal.ZERO, BigDecimal.ZERO); - private static final HardMediumSoftBigDecimalScore MINUS_ONE_HARD = + private static final @NonNull HardMediumSoftBigDecimalScore MINUS_ONE_HARD = new HardMediumSoftBigDecimalScore(0, BigDecimal.ONE.negate(), BigDecimal.ZERO, BigDecimal.ZERO); - public static final HardMediumSoftBigDecimalScore ONE_MEDIUM = new HardMediumSoftBigDecimalScore(0, BigDecimal.ZERO, - BigDecimal.ONE, BigDecimal.ZERO); - private static final HardMediumSoftBigDecimalScore MINUS_ONE_MEDIUM = new HardMediumSoftBigDecimalScore(0, BigDecimal.ZERO, - BigDecimal.ONE.negate(), BigDecimal.ZERO); - public static final HardMediumSoftBigDecimalScore ONE_SOFT = new HardMediumSoftBigDecimalScore(0, BigDecimal.ZERO, + public static final @NonNull HardMediumSoftBigDecimalScore ONE_MEDIUM = + new HardMediumSoftBigDecimalScore(0, BigDecimal.ZERO, + BigDecimal.ONE, BigDecimal.ZERO); + private static final @NonNull HardMediumSoftBigDecimalScore MINUS_ONE_MEDIUM = + new HardMediumSoftBigDecimalScore(0, BigDecimal.ZERO, + BigDecimal.ONE.negate(), BigDecimal.ZERO); + public static final @NonNull HardMediumSoftBigDecimalScore ONE_SOFT = new HardMediumSoftBigDecimalScore(0, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ONE); - private static final HardMediumSoftBigDecimalScore MINUS_ONE_SOFT = + private static final @NonNull HardMediumSoftBigDecimalScore MINUS_ONE_SOFT = new HardMediumSoftBigDecimalScore(0, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ONE.negate()); - public static HardMediumSoftBigDecimalScore parseScore(String scoreString) { + public static @NonNull HardMediumSoftBigDecimalScore parseScore(@NonNull String scoreString) { String[] scoreTokens = ScoreUtil.parseScoreTokens(HardMediumSoftBigDecimalScore.class, scoreString, HARD_LABEL, MEDIUM_LABEL, SOFT_LABEL); int initScore = ScoreUtil.parseInitScore(HardMediumSoftBigDecimalScore.class, scoreString, scoreTokens[0]); @@ -53,15 +57,17 @@ public static HardMediumSoftBigDecimalScore parseScore(String scoreString) { return ofUninitialized(initScore, hardScore, mediumScore, softScore); } - public static HardMediumSoftBigDecimalScore ofUninitialized(int initScore, BigDecimal hardScore, BigDecimal mediumScore, - BigDecimal softScore) { + public static @NonNull HardMediumSoftBigDecimalScore ofUninitialized(int initScore, @NonNull BigDecimal hardScore, + @NonNull BigDecimal mediumScore, + @NonNull BigDecimal softScore) { if (initScore == 0) { return of(hardScore, mediumScore, softScore); } return new HardMediumSoftBigDecimalScore(initScore, hardScore, mediumScore, softScore); } - public static HardMediumSoftBigDecimalScore of(BigDecimal hardScore, BigDecimal mediumScore, BigDecimal softScore) { + public static @NonNull HardMediumSoftBigDecimalScore of(@NonNull BigDecimal hardScore, @NonNull BigDecimal mediumScore, + @NonNull BigDecimal softScore) { if (Objects.equals(hardScore, BigDecimal.ONE.negate()) && mediumScore.signum() == 0 && softScore.signum() == 0) { return MINUS_ONE_HARD; } else if (hardScore.signum() == 0) { @@ -84,7 +90,7 @@ public static HardMediumSoftBigDecimalScore of(BigDecimal hardScore, BigDecimal return new HardMediumSoftBigDecimalScore(0, hardScore, mediumScore, softScore); } - public static HardMediumSoftBigDecimalScore ofHard(BigDecimal hardScore) { + public static @NonNull HardMediumSoftBigDecimalScore ofHard(@NonNull BigDecimal hardScore) { if (Objects.equals(hardScore, BigDecimal.ONE.negate())) { return MINUS_ONE_HARD; } else if (hardScore.signum() == 0) { @@ -95,7 +101,7 @@ public static HardMediumSoftBigDecimalScore ofHard(BigDecimal hardScore) { return new HardMediumSoftBigDecimalScore(0, hardScore, BigDecimal.ZERO, BigDecimal.ZERO); } - public static HardMediumSoftBigDecimalScore ofMedium(BigDecimal mediumScore) { + public static @NonNull HardMediumSoftBigDecimalScore ofMedium(@NonNull BigDecimal mediumScore) { if (Objects.equals(mediumScore, BigDecimal.ONE.negate())) { return MINUS_ONE_MEDIUM; } else if (mediumScore.signum() == 0) { @@ -106,7 +112,7 @@ public static HardMediumSoftBigDecimalScore ofMedium(BigDecimal mediumScore) { return new HardMediumSoftBigDecimalScore(0, BigDecimal.ZERO, mediumScore, BigDecimal.ZERO); } - public static HardMediumSoftBigDecimalScore ofSoft(BigDecimal softScore) { + public static @NonNull HardMediumSoftBigDecimalScore ofSoft(@NonNull BigDecimal softScore) { if (Objects.equals(softScore, BigDecimal.ONE.negate())) { return MINUS_ONE_SOFT; } else if (softScore.signum() == 0) { @@ -122,9 +128,9 @@ public static HardMediumSoftBigDecimalScore ofSoft(BigDecimal softScore) { // ************************************************************************ private final int initScore; - private final BigDecimal hardScore; - private final BigDecimal mediumScore; - private final BigDecimal softScore; + private final @NonNull BigDecimal hardScore; + private final @NonNull BigDecimal mediumScore; + private final @NonNull BigDecimal softScore; /** * Private default constructor for default marshalling/unmarshalling of unknown frameworks that use reflection. @@ -133,10 +139,11 @@ public static HardMediumSoftBigDecimalScore ofSoft(BigDecimal softScore) { */ @SuppressWarnings("unused") private HardMediumSoftBigDecimalScore() { - this(Integer.MIN_VALUE, null, null, null); + this(Integer.MIN_VALUE, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO); } - private HardMediumSoftBigDecimalScore(int initScore, BigDecimal hardScore, BigDecimal mediumScore, BigDecimal softScore) { + private HardMediumSoftBigDecimalScore(int initScore, @NonNull BigDecimal hardScore, @NonNull BigDecimal mediumScore, + @NonNull BigDecimal softScore) { this.initScore = initScore; this.hardScore = hardScore; this.mediumScore = mediumScore; @@ -155,7 +162,7 @@ public int initScore() { * * @return higher is better, usually negative, 0 if no hard constraints are broken/fulfilled */ - public BigDecimal hardScore() { + public @NonNull BigDecimal hardScore() { return hardScore; } @@ -165,7 +172,7 @@ public BigDecimal hardScore() { * @deprecated Use {@link #hardScore()} instead. */ @Deprecated(forRemoval = true) - public BigDecimal getHardScore() { + public @NonNull BigDecimal getHardScore() { return hardScore; } @@ -178,7 +185,7 @@ public BigDecimal getHardScore() { * * @return higher is better, usually negative, 0 if no medium constraints are broken/fulfilled */ - public BigDecimal mediumScore() { + public @NonNull BigDecimal mediumScore() { return mediumScore; } @@ -188,7 +195,7 @@ public BigDecimal mediumScore() { * @deprecated Use {@link #mediumScore()} instead. */ @Deprecated(forRemoval = true) - public BigDecimal getMediumScore() { + public @NonNull BigDecimal getMediumScore() { return mediumScore; } @@ -201,7 +208,7 @@ public BigDecimal getMediumScore() { * * @return higher is better, usually negative, 0 if no soft constraints are broken/fulfilled */ - public BigDecimal softScore() { + public @NonNull BigDecimal softScore() { return softScore; } @@ -211,7 +218,7 @@ public BigDecimal softScore() { * @deprecated Use {@link #softScore()} instead. */ @Deprecated(forRemoval = true) - public BigDecimal getSoftScore() { + public @NonNull BigDecimal getSoftScore() { return softScore; } @@ -220,7 +227,7 @@ public BigDecimal getSoftScore() { // ************************************************************************ @Override - public HardMediumSoftBigDecimalScore withInitScore(int newInitScore) { + public @NonNull HardMediumSoftBigDecimalScore withInitScore(int newInitScore) { return ofUninitialized(newInitScore, hardScore, mediumScore, softScore); } @@ -235,7 +242,7 @@ public boolean isFeasible() { } @Override - public HardMediumSoftBigDecimalScore add(HardMediumSoftBigDecimalScore addend) { + public @NonNull HardMediumSoftBigDecimalScore add(@NonNull HardMediumSoftBigDecimalScore addend) { return ofUninitialized( initScore + addend.initScore(), hardScore.add(addend.hardScore()), @@ -244,7 +251,7 @@ public HardMediumSoftBigDecimalScore add(HardMediumSoftBigDecimalScore addend) { } @Override - public HardMediumSoftBigDecimalScore subtract(HardMediumSoftBigDecimalScore subtrahend) { + public @NonNull HardMediumSoftBigDecimalScore subtract(@NonNull HardMediumSoftBigDecimalScore subtrahend) { return ofUninitialized( initScore - subtrahend.initScore(), hardScore.subtract(subtrahend.hardScore()), @@ -253,7 +260,7 @@ public HardMediumSoftBigDecimalScore subtract(HardMediumSoftBigDecimalScore subt } @Override - public HardMediumSoftBigDecimalScore multiply(double multiplicand) { + public @NonNull HardMediumSoftBigDecimalScore multiply(double multiplicand) { // Intentionally not taken "new BigDecimal(multiplicand, MathContext.UNLIMITED)" // because together with the floor rounding it gives unwanted behaviour BigDecimal multiplicandBigDecimal = BigDecimal.valueOf(multiplicand); @@ -266,7 +273,7 @@ public HardMediumSoftBigDecimalScore multiply(double multiplicand) { } @Override - public HardMediumSoftBigDecimalScore divide(double divisor) { + public @NonNull HardMediumSoftBigDecimalScore divide(double divisor) { BigDecimal divisorBigDecimal = BigDecimal.valueOf(divisor); // The (unspecified) scale/precision of the divisor should have no impact on the returned scale/precision return ofUninitialized( @@ -277,7 +284,7 @@ public HardMediumSoftBigDecimalScore divide(double divisor) { } @Override - public HardMediumSoftBigDecimalScore power(double exponent) { + public @NonNull HardMediumSoftBigDecimalScore power(double exponent) { BigDecimal exponentBigDecimal = BigDecimal.valueOf(exponent); // The (unspecified) scale/precision of the exponent should have no impact on the returned scale/precision // TODO FIXME remove .intValue() so non-integer exponents produce correct results @@ -290,17 +297,17 @@ public HardMediumSoftBigDecimalScore power(double exponent) { } @Override - public HardMediumSoftBigDecimalScore abs() { + public @NonNull HardMediumSoftBigDecimalScore abs() { return ofUninitialized(Math.abs(initScore), hardScore.abs(), mediumScore.abs(), softScore.abs()); } @Override - public HardMediumSoftBigDecimalScore zero() { + public @NonNull HardMediumSoftBigDecimalScore zero() { return HardMediumSoftBigDecimalScore.ZERO; } @Override - public Number[] toLevelNumbers() { + public @NonNull Number @NonNull [] toLevelNumbers() { return new Number[] { hardScore, mediumScore, softScore }; } @@ -322,7 +329,7 @@ public int hashCode() { } @Override - public int compareTo(HardMediumSoftBigDecimalScore other) { + public int compareTo(@NonNull HardMediumSoftBigDecimalScore other) { if (initScore != other.initScore()) { return Integer.compare(initScore, other.initScore()); } @@ -339,7 +346,7 @@ public int compareTo(HardMediumSoftBigDecimalScore other) { } @Override - public String toShortString() { + public @NonNull String toShortString() { return ScoreUtil.buildShortString(this, n -> ((BigDecimal) n).compareTo(BigDecimal.ZERO) != 0, HARD_LABEL, MEDIUM_LABEL, SOFT_LABEL); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardmediumsoftlong/HardMediumSoftLongScore.java b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardmediumsoftlong/HardMediumSoftLongScore.java index a99c483e8c..86740762fa 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardmediumsoftlong/HardMediumSoftLongScore.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardmediumsoftlong/HardMediumSoftLongScore.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.impl.score.ScoreUtil; +import org.jspecify.annotations.NonNull; + /** * This {@link Score} is based on 3 levels of long constraints: hard, medium and soft. * Hard constraints have priority over medium constraints. @@ -22,15 +24,15 @@ */ public final class HardMediumSoftLongScore implements Score { - public static final HardMediumSoftLongScore ZERO = new HardMediumSoftLongScore(0, 0L, 0L, 0L); - public static final HardMediumSoftLongScore ONE_HARD = new HardMediumSoftLongScore(0, 1L, 0L, 0L); - private static final HardMediumSoftLongScore MINUS_ONE_HARD = new HardMediumSoftLongScore(0, -1L, 0L, 0L); - public static final HardMediumSoftLongScore ONE_MEDIUM = new HardMediumSoftLongScore(0, 0L, 1L, 0L); - private static final HardMediumSoftLongScore MINUS_ONE_MEDIUM = new HardMediumSoftLongScore(0, 0L, -1L, 0L); - public static final HardMediumSoftLongScore ONE_SOFT = new HardMediumSoftLongScore(0, 0L, 0L, 1L); - private static final HardMediumSoftLongScore MINUS_ONE_SOFT = new HardMediumSoftLongScore(0, 0L, 0L, -1L); + public static final @NonNull HardMediumSoftLongScore ZERO = new HardMediumSoftLongScore(0, 0L, 0L, 0L); + public static final @NonNull HardMediumSoftLongScore ONE_HARD = new HardMediumSoftLongScore(0, 1L, 0L, 0L); + private static final @NonNull HardMediumSoftLongScore MINUS_ONE_HARD = new HardMediumSoftLongScore(0, -1L, 0L, 0L); + public static final @NonNull HardMediumSoftLongScore ONE_MEDIUM = new HardMediumSoftLongScore(0, 0L, 1L, 0L); + private static final @NonNull HardMediumSoftLongScore MINUS_ONE_MEDIUM = new HardMediumSoftLongScore(0, 0L, -1L, 0L); + public static final @NonNull HardMediumSoftLongScore ONE_SOFT = new HardMediumSoftLongScore(0, 0L, 0L, 1L); + private static final @NonNull HardMediumSoftLongScore MINUS_ONE_SOFT = new HardMediumSoftLongScore(0, 0L, 0L, -1L); - public static HardMediumSoftLongScore parseScore(String scoreString) { + public static @NonNull HardMediumSoftLongScore parseScore(@NonNull String scoreString) { String[] scoreTokens = ScoreUtil.parseScoreTokens(HardMediumSoftLongScore.class, scoreString, HARD_LABEL, MEDIUM_LABEL, SOFT_LABEL); int initScore = ScoreUtil.parseInitScore(HardMediumSoftLongScore.class, scoreString, scoreTokens[0]); @@ -40,14 +42,15 @@ public static HardMediumSoftLongScore parseScore(String scoreString) { return ofUninitialized(initScore, hardScore, mediumScore, softScore); } - public static HardMediumSoftLongScore ofUninitialized(int initScore, long hardScore, long mediumScore, long softScore) { + public static @NonNull HardMediumSoftLongScore ofUninitialized(int initScore, long hardScore, long mediumScore, + long softScore) { if (initScore == 0) { return of(hardScore, mediumScore, softScore); } return new HardMediumSoftLongScore(initScore, hardScore, mediumScore, softScore); } - public static HardMediumSoftLongScore of(long hardScore, long mediumScore, long softScore) { + public static @NonNull HardMediumSoftLongScore of(long hardScore, long mediumScore, long softScore) { if (hardScore == -1L && mediumScore == 0L && softScore == 0L) { return MINUS_ONE_HARD; } else if (hardScore == 0L) { @@ -70,7 +73,7 @@ public static HardMediumSoftLongScore of(long hardScore, long mediumScore, long return new HardMediumSoftLongScore(0, hardScore, mediumScore, softScore); } - public static HardMediumSoftLongScore ofHard(long hardScore) { + public static @NonNull HardMediumSoftLongScore ofHard(long hardScore) { if (hardScore == -1L) { return MINUS_ONE_HARD; } else if (hardScore == 0L) { @@ -81,7 +84,7 @@ public static HardMediumSoftLongScore ofHard(long hardScore) { return new HardMediumSoftLongScore(0, hardScore, 0L, 0L); } - public static HardMediumSoftLongScore ofMedium(long mediumScore) { + public static @NonNull HardMediumSoftLongScore ofMedium(long mediumScore) { if (mediumScore == -1L) { return MINUS_ONE_MEDIUM; } else if (mediumScore == 0L) { @@ -92,7 +95,7 @@ public static HardMediumSoftLongScore ofMedium(long mediumScore) { return new HardMediumSoftLongScore(0, 0L, mediumScore, 0L); } - public static HardMediumSoftLongScore ofSoft(long softScore) { + public static @NonNull HardMediumSoftLongScore ofSoft(long softScore) { if (softScore == -1L) { return MINUS_ONE_SOFT; } else if (softScore == 0L) { @@ -206,7 +209,7 @@ public long getSoftScore() { // ************************************************************************ @Override - public HardMediumSoftLongScore withInitScore(int newInitScore) { + public @NonNull HardMediumSoftLongScore withInitScore(int newInitScore) { return ofUninitialized(newInitScore, hardScore, mediumScore, softScore); } @@ -221,7 +224,7 @@ public boolean isFeasible() { } @Override - public HardMediumSoftLongScore add(HardMediumSoftLongScore addend) { + public @NonNull HardMediumSoftLongScore add(@NonNull HardMediumSoftLongScore addend) { return ofUninitialized( initScore + addend.initScore(), hardScore + addend.hardScore(), @@ -230,7 +233,7 @@ public HardMediumSoftLongScore add(HardMediumSoftLongScore addend) { } @Override - public HardMediumSoftLongScore subtract(HardMediumSoftLongScore subtrahend) { + public @NonNull HardMediumSoftLongScore subtract(@NonNull HardMediumSoftLongScore subtrahend) { return ofUninitialized( initScore - subtrahend.initScore(), hardScore - subtrahend.hardScore(), @@ -239,7 +242,7 @@ public HardMediumSoftLongScore subtract(HardMediumSoftLongScore subtrahend) { } @Override - public HardMediumSoftLongScore multiply(double multiplicand) { + public @NonNull HardMediumSoftLongScore multiply(double multiplicand) { return ofUninitialized( (int) Math.floor(initScore * multiplicand), (long) Math.floor(hardScore * multiplicand), @@ -248,7 +251,7 @@ public HardMediumSoftLongScore multiply(double multiplicand) { } @Override - public HardMediumSoftLongScore divide(double divisor) { + public @NonNull HardMediumSoftLongScore divide(double divisor) { return ofUninitialized( (int) Math.floor(initScore / divisor), (long) Math.floor(hardScore / divisor), @@ -257,7 +260,7 @@ public HardMediumSoftLongScore divide(double divisor) { } @Override - public HardMediumSoftLongScore power(double exponent) { + public @NonNull HardMediumSoftLongScore power(double exponent) { return ofUninitialized( (int) Math.floor(Math.pow(initScore, exponent)), (long) Math.floor(Math.pow(hardScore, exponent)), @@ -266,17 +269,17 @@ public HardMediumSoftLongScore power(double exponent) { } @Override - public HardMediumSoftLongScore abs() { + public @NonNull HardMediumSoftLongScore abs() { return ofUninitialized(Math.abs(initScore), Math.abs(hardScore), Math.abs(mediumScore), Math.abs(softScore)); } @Override - public HardMediumSoftLongScore zero() { + public @NonNull HardMediumSoftLongScore zero() { return HardMediumSoftLongScore.ZERO; } @Override - public Number[] toLevelNumbers() { + public Number @NonNull [] toLevelNumbers() { return new Number[] { hardScore, mediumScore, softScore }; } @@ -297,7 +300,7 @@ public int hashCode() { } @Override - public int compareTo(HardMediumSoftLongScore other) { + public int compareTo(@NonNull HardMediumSoftLongScore other) { if (initScore != other.initScore()) { return Integer.compare(initScore, other.initScore()); } else if (hardScore != other.hardScore()) { @@ -310,7 +313,7 @@ public int compareTo(HardMediumSoftLongScore other) { } @Override - public String toShortString() { + public @NonNull String toShortString() { return ScoreUtil.buildShortString(this, n -> n.longValue() != 0L, HARD_LABEL, MEDIUM_LABEL, SOFT_LABEL); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardsoft/HardSoftScore.java b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardsoft/HardSoftScore.java index a3a6d24a70..572e94c796 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardsoft/HardSoftScore.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardsoft/HardSoftScore.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.impl.score.ScoreUtil; +import org.jspecify.annotations.NonNull; + /** * This {@link Score} is based on 2 levels of int constraints: hard and soft. * Hard constraints have priority over soft constraints. @@ -22,13 +24,13 @@ */ public final class HardSoftScore implements Score { - public static final HardSoftScore ZERO = new HardSoftScore(0, 0, 0); - public static final HardSoftScore ONE_HARD = new HardSoftScore(0, 1, 0); - public static final HardSoftScore ONE_SOFT = new HardSoftScore(0, 0, 1); - private static final HardSoftScore MINUS_ONE_SOFT = new HardSoftScore(0, 0, -1); - private static final HardSoftScore MINUS_ONE_HARD = new HardSoftScore(0, -1, 0); + public static final @NonNull HardSoftScore ZERO = new HardSoftScore(0, 0, 0); + public static final @NonNull HardSoftScore ONE_HARD = new HardSoftScore(0, 1, 0); + public static final @NonNull HardSoftScore ONE_SOFT = new HardSoftScore(0, 0, 1); + private static final @NonNull HardSoftScore MINUS_ONE_SOFT = new HardSoftScore(0, 0, -1); + private static final @NonNull HardSoftScore MINUS_ONE_HARD = new HardSoftScore(0, -1, 0); - public static HardSoftScore parseScore(String scoreString) { + public static @NonNull HardSoftScore parseScore(@NonNull String scoreString) { String[] scoreTokens = parseScoreTokens(HardSoftScore.class, scoreString, HARD_LABEL, SOFT_LABEL); int initScore = parseInitScore(HardSoftScore.class, scoreString, scoreTokens[0]); int hardScore = parseLevelAsInt(HardSoftScore.class, scoreString, scoreTokens[1]); @@ -36,14 +38,14 @@ public static HardSoftScore parseScore(String scoreString) { return ofUninitialized(initScore, hardScore, softScore); } - public static HardSoftScore ofUninitialized(int initScore, int hardScore, int softScore) { + public static @NonNull HardSoftScore ofUninitialized(int initScore, int hardScore, int softScore) { if (initScore == 0) { return of(hardScore, softScore); } return new HardSoftScore(initScore, hardScore, softScore); } - public static HardSoftScore of(int hardScore, int softScore) { + public static @NonNull HardSoftScore of(int hardScore, int softScore) { // Optimization for frequently seen values. if (hardScore == 0) { if (softScore == -1) { @@ -64,7 +66,7 @@ public static HardSoftScore of(int hardScore, int softScore) { return new HardSoftScore(0, hardScore, softScore); } - public static HardSoftScore ofHard(int hardScore) { + public static @NonNull HardSoftScore ofHard(int hardScore) { // Optimization for frequently seen values. if (hardScore == -1) { return MINUS_ONE_HARD; @@ -77,7 +79,7 @@ public static HardSoftScore ofHard(int hardScore) { return new HardSoftScore(0, hardScore, 0); } - public static HardSoftScore ofSoft(int softScore) { + public static @NonNull HardSoftScore ofSoft(int softScore) { // Optimization for frequently seen values. if (softScore == -1) { return MINUS_ONE_SOFT; @@ -168,7 +170,7 @@ public int getSoftScore() { // ************************************************************************ @Override - public HardSoftScore withInitScore(int newInitScore) { + public @NonNull HardSoftScore withInitScore(int newInitScore) { return ofUninitialized(newInitScore, hardScore, softScore); } @@ -178,7 +180,7 @@ public boolean isFeasible() { } @Override - public HardSoftScore add(HardSoftScore addend) { + public @NonNull HardSoftScore add(@NonNull HardSoftScore addend) { return ofUninitialized( initScore + addend.initScore(), hardScore + addend.hardScore(), @@ -186,7 +188,7 @@ public HardSoftScore add(HardSoftScore addend) { } @Override - public HardSoftScore subtract(HardSoftScore subtrahend) { + public @NonNull HardSoftScore subtract(@NonNull HardSoftScore subtrahend) { return ofUninitialized( initScore - subtrahend.initScore(), hardScore - subtrahend.hardScore(), @@ -194,7 +196,7 @@ public HardSoftScore subtract(HardSoftScore subtrahend) { } @Override - public HardSoftScore multiply(double multiplicand) { + public @NonNull HardSoftScore multiply(double multiplicand) { return ofUninitialized( (int) Math.floor(initScore * multiplicand), (int) Math.floor(hardScore * multiplicand), @@ -202,7 +204,7 @@ public HardSoftScore multiply(double multiplicand) { } @Override - public HardSoftScore divide(double divisor) { + public @NonNull HardSoftScore divide(double divisor) { return ofUninitialized( (int) Math.floor(initScore / divisor), (int) Math.floor(hardScore / divisor), @@ -210,7 +212,7 @@ public HardSoftScore divide(double divisor) { } @Override - public HardSoftScore power(double exponent) { + public @NonNull HardSoftScore power(double exponent) { return ofUninitialized( (int) Math.floor(Math.pow(initScore, exponent)), (int) Math.floor(Math.pow(hardScore, exponent)), @@ -218,17 +220,17 @@ public HardSoftScore power(double exponent) { } @Override - public HardSoftScore abs() { + public @NonNull HardSoftScore abs() { return ofUninitialized(Math.abs(initScore), Math.abs(hardScore), Math.abs(softScore)); } @Override - public HardSoftScore zero() { + public @NonNull HardSoftScore zero() { return ZERO; } @Override - public Number[] toLevelNumbers() { + public Number @NonNull [] toLevelNumbers() { return new Number[] { hardScore, softScore }; } @@ -248,7 +250,7 @@ public int hashCode() { } @Override - public int compareTo(HardSoftScore other) { + public int compareTo(@NonNull HardSoftScore other) { if (initScore != other.initScore()) { return Integer.compare(initScore, other.initScore()); } else if (hardScore != other.hardScore()) { @@ -259,7 +261,7 @@ public int compareTo(HardSoftScore other) { } @Override - public String toShortString() { + public @NonNull String toShortString() { return ScoreUtil.buildShortString(this, n -> n.intValue() != 0, HARD_LABEL, SOFT_LABEL); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardsoftbigdecimal/HardSoftBigDecimalScore.java b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardsoftbigdecimal/HardSoftBigDecimalScore.java index 5b7583e564..d6ab3850db 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardsoftbigdecimal/HardSoftBigDecimalScore.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardsoftbigdecimal/HardSoftBigDecimalScore.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.impl.score.ScoreUtil; +import org.jspecify.annotations.NonNull; + /** * This {@link Score} is based on 2 levels of {@link BigDecimal} constraints: hard and soft. * Hard constraints have priority over soft constraints. @@ -21,11 +23,14 @@ */ public final class HardSoftBigDecimalScore implements Score { - public static final HardSoftBigDecimalScore ZERO = new HardSoftBigDecimalScore(0, BigDecimal.ZERO, BigDecimal.ZERO); - public static final HardSoftBigDecimalScore ONE_HARD = new HardSoftBigDecimalScore(0, BigDecimal.ONE, BigDecimal.ZERO); - public static final HardSoftBigDecimalScore ONE_SOFT = new HardSoftBigDecimalScore(0, BigDecimal.ZERO, BigDecimal.ONE); + public static final @NonNull HardSoftBigDecimalScore ZERO = + new HardSoftBigDecimalScore(0, BigDecimal.ZERO, BigDecimal.ZERO); + public static final @NonNull HardSoftBigDecimalScore ONE_HARD = + new HardSoftBigDecimalScore(0, BigDecimal.ONE, BigDecimal.ZERO); + public static final @NonNull HardSoftBigDecimalScore ONE_SOFT = + new HardSoftBigDecimalScore(0, BigDecimal.ZERO, BigDecimal.ONE); - public static HardSoftBigDecimalScore parseScore(String scoreString) { + public static @NonNull HardSoftBigDecimalScore parseScore(@NonNull String scoreString) { String[] scoreTokens = ScoreUtil.parseScoreTokens(HardSoftBigDecimalScore.class, scoreString, HARD_LABEL, SOFT_LABEL); int initScore = ScoreUtil.parseInitScore(HardSoftBigDecimalScore.class, scoreString, scoreTokens[0]); BigDecimal hardScore = ScoreUtil.parseLevelAsBigDecimal(HardSoftBigDecimalScore.class, scoreString, scoreTokens[1]); @@ -33,14 +38,15 @@ public static HardSoftBigDecimalScore parseScore(String scoreString) { return ofUninitialized(initScore, hardScore, softScore); } - public static HardSoftBigDecimalScore ofUninitialized(int initScore, BigDecimal hardScore, BigDecimal softScore) { + public static @NonNull HardSoftBigDecimalScore ofUninitialized(int initScore, @NonNull BigDecimal hardScore, + @NonNull BigDecimal softScore) { if (initScore == 0) { return of(hardScore, softScore); } return new HardSoftBigDecimalScore(initScore, hardScore, softScore); } - public static HardSoftBigDecimalScore of(BigDecimal hardScore, BigDecimal softScore) { + public static @NonNull HardSoftBigDecimalScore of(BigDecimal hardScore, BigDecimal softScore) { // Optimization for frequently seen values. if (hardScore.signum() == 0) { if (softScore.signum() == 0) { @@ -55,7 +61,7 @@ public static HardSoftBigDecimalScore of(BigDecimal hardScore, BigDecimal softSc return new HardSoftBigDecimalScore(0, hardScore, softScore); } - public static HardSoftBigDecimalScore ofHard(BigDecimal hardScore) { + public static @NonNull HardSoftBigDecimalScore ofHard(BigDecimal hardScore) { // Optimization for frequently seen values. if (hardScore.signum() == 0) { return ZERO; @@ -66,7 +72,7 @@ public static HardSoftBigDecimalScore ofHard(BigDecimal hardScore) { return new HardSoftBigDecimalScore(0, hardScore, BigDecimal.ZERO); } - public static HardSoftBigDecimalScore ofSoft(BigDecimal softScore) { + public static @NonNull HardSoftBigDecimalScore ofSoft(BigDecimal softScore) { // Optimization for frequently seen values. if (softScore.signum() == 0) { return ZERO; @@ -82,8 +88,8 @@ public static HardSoftBigDecimalScore ofSoft(BigDecimal softScore) { // ************************************************************************ private final int initScore; - private final BigDecimal hardScore; - private final BigDecimal softScore; + private final @NonNull BigDecimal hardScore; + private final @NonNull BigDecimal softScore; /** * Private default constructor for default marshalling/unmarshalling of unknown frameworks that use reflection. @@ -92,10 +98,10 @@ public static HardSoftBigDecimalScore ofSoft(BigDecimal softScore) { */ @SuppressWarnings("unused") private HardSoftBigDecimalScore() { - this(Integer.MIN_VALUE, null, null); + this(Integer.MIN_VALUE, BigDecimal.ZERO, BigDecimal.ZERO); } - private HardSoftBigDecimalScore(int initScore, BigDecimal hardScore, BigDecimal softScore) { + private HardSoftBigDecimalScore(int initScore, @NonNull BigDecimal hardScore, @NonNull BigDecimal softScore) { this.initScore = initScore; this.hardScore = hardScore; this.softScore = softScore; @@ -113,7 +119,7 @@ public int initScore() { * * @return higher is better, usually negative, 0 if no hard constraints are broken/fulfilled */ - public BigDecimal hardScore() { + public @NonNull BigDecimal hardScore() { return hardScore; } @@ -123,7 +129,7 @@ public BigDecimal hardScore() { * @deprecated Use {@link #hardScore()} instead. */ @Deprecated(forRemoval = true) - public BigDecimal getHardScore() { + public @NonNull BigDecimal getHardScore() { return hardScore; } @@ -136,7 +142,7 @@ public BigDecimal getHardScore() { * * @return higher is better, usually negative, 0 if no soft constraints are broken/fulfilled */ - public BigDecimal softScore() { + public @NonNull BigDecimal softScore() { return softScore; } @@ -146,7 +152,7 @@ public BigDecimal softScore() { * @deprecated Use {@link #softScore()} instead. */ @Deprecated(forRemoval = true) - public BigDecimal getSoftScore() { + public @NonNull BigDecimal getSoftScore() { return softScore; } @@ -155,7 +161,7 @@ public BigDecimal getSoftScore() { // ************************************************************************ @Override - public HardSoftBigDecimalScore withInitScore(int newInitScore) { + public @NonNull HardSoftBigDecimalScore withInitScore(int newInitScore) { return new HardSoftBigDecimalScore(newInitScore, hardScore, softScore); } @@ -165,7 +171,7 @@ public boolean isFeasible() { } @Override - public HardSoftBigDecimalScore add(HardSoftBigDecimalScore addend) { + public @NonNull HardSoftBigDecimalScore add(@NonNull HardSoftBigDecimalScore addend) { return ofUninitialized( initScore + addend.initScore(), hardScore.add(addend.hardScore()), @@ -173,7 +179,7 @@ public HardSoftBigDecimalScore add(HardSoftBigDecimalScore addend) { } @Override - public HardSoftBigDecimalScore subtract(HardSoftBigDecimalScore subtrahend) { + public @NonNull HardSoftBigDecimalScore subtract(@NonNull HardSoftBigDecimalScore subtrahend) { return ofUninitialized( initScore - subtrahend.initScore(), hardScore.subtract(subtrahend.hardScore()), @@ -181,7 +187,7 @@ public HardSoftBigDecimalScore subtract(HardSoftBigDecimalScore subtrahend) { } @Override - public HardSoftBigDecimalScore multiply(double multiplicand) { + public @NonNull HardSoftBigDecimalScore multiply(double multiplicand) { // Intentionally not taken "new BigDecimal(multiplicand, MathContext.UNLIMITED)" // because together with the floor rounding it gives unwanted behaviour BigDecimal multiplicandBigDecimal = BigDecimal.valueOf(multiplicand); @@ -193,7 +199,7 @@ public HardSoftBigDecimalScore multiply(double multiplicand) { } @Override - public HardSoftBigDecimalScore divide(double divisor) { + public @NonNull HardSoftBigDecimalScore divide(double divisor) { // Intentionally not taken "new BigDecimal(multiplicand, MathContext.UNLIMITED)" // because together with the floor rounding it gives unwanted behaviour BigDecimal divisorBigDecimal = BigDecimal.valueOf(divisor); @@ -205,7 +211,7 @@ public HardSoftBigDecimalScore divide(double divisor) { } @Override - public HardSoftBigDecimalScore power(double exponent) { + public @NonNull HardSoftBigDecimalScore power(double exponent) { // Intentionally not taken "new BigDecimal(multiplicand, MathContext.UNLIMITED)" // because together with the floor rounding it gives unwanted behaviour BigDecimal exponentBigDecimal = BigDecimal.valueOf(exponent); @@ -219,17 +225,17 @@ public HardSoftBigDecimalScore power(double exponent) { } @Override - public HardSoftBigDecimalScore abs() { + public @NonNull HardSoftBigDecimalScore abs() { return ofUninitialized(Math.abs(initScore), hardScore.abs(), softScore.abs()); } @Override - public HardSoftBigDecimalScore zero() { + public @NonNull HardSoftBigDecimalScore zero() { return ZERO; } @Override - public Number[] toLevelNumbers() { + public Number @NonNull [] toLevelNumbers() { return new Number[] { hardScore, softScore }; } @@ -249,7 +255,7 @@ public int hashCode() { } @Override - public int compareTo(HardSoftBigDecimalScore other) { + public int compareTo(@NonNull HardSoftBigDecimalScore other) { if (initScore != other.initScore()) { return Integer.compare(initScore, other.initScore()); } @@ -262,7 +268,7 @@ public int compareTo(HardSoftBigDecimalScore other) { } @Override - public String toShortString() { + public @NonNull String toShortString() { return ScoreUtil.buildShortString(this, n -> ((BigDecimal) n).compareTo(BigDecimal.ZERO) != 0, HARD_LABEL, SOFT_LABEL); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardsoftlong/HardSoftLongScore.java b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardsoftlong/HardSoftLongScore.java index 03cb975130..1826ab5050 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardsoftlong/HardSoftLongScore.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/hardsoftlong/HardSoftLongScore.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.impl.score.ScoreUtil; +import org.jspecify.annotations.NonNull; + /** * This {@link Score} is based on 2 levels of long constraints: hard and soft. * Hard constraints have priority over soft constraints. @@ -19,13 +21,13 @@ */ public final class HardSoftLongScore implements Score { - public static final HardSoftLongScore ZERO = new HardSoftLongScore(0, 0L, 0L); - public static final HardSoftLongScore ONE_HARD = new HardSoftLongScore(0, 1L, 0L); - public static final HardSoftLongScore ONE_SOFT = new HardSoftLongScore(0, 0L, 1L); - private static final HardSoftLongScore MINUS_ONE_SOFT = new HardSoftLongScore(0, 0L, -1L); - private static final HardSoftLongScore MINUS_ONE_HARD = new HardSoftLongScore(0, -1L, 0L); + public static final @NonNull HardSoftLongScore ZERO = new HardSoftLongScore(0, 0L, 0L); + public static final @NonNull HardSoftLongScore ONE_HARD = new HardSoftLongScore(0, 1L, 0L); + public static final @NonNull HardSoftLongScore ONE_SOFT = new HardSoftLongScore(0, 0L, 1L); + private static final @NonNull HardSoftLongScore MINUS_ONE_SOFT = new HardSoftLongScore(0, 0L, -1L); + private static final @NonNull HardSoftLongScore MINUS_ONE_HARD = new HardSoftLongScore(0, -1L, 0L); - public static HardSoftLongScore parseScore(String scoreString) { + public static @NonNull HardSoftLongScore parseScore(@NonNull String scoreString) { String[] scoreTokens = ScoreUtil.parseScoreTokens(HardSoftLongScore.class, scoreString, HARD_LABEL, SOFT_LABEL); int initScore = ScoreUtil.parseInitScore(HardSoftLongScore.class, scoreString, scoreTokens[0]); long hardScore = ScoreUtil.parseLevelAsLong(HardSoftLongScore.class, scoreString, scoreTokens[1]); @@ -33,14 +35,14 @@ public static HardSoftLongScore parseScore(String scoreString) { return ofUninitialized(initScore, hardScore, softScore); } - public static HardSoftLongScore ofUninitialized(int initScore, long hardScore, long softScore) { + public static @NonNull HardSoftLongScore ofUninitialized(int initScore, long hardScore, long softScore) { if (initScore == 0) { return of(hardScore, softScore); } return new HardSoftLongScore(initScore, hardScore, softScore); } - public static HardSoftLongScore of(long hardScore, long softScore) { + public static @NonNull HardSoftLongScore of(long hardScore, long softScore) { // Optimization for frequently seen values. if (hardScore == 0L) { if (softScore == -1L) { @@ -61,7 +63,7 @@ public static HardSoftLongScore of(long hardScore, long softScore) { return new HardSoftLongScore(0, hardScore, softScore); } - public static HardSoftLongScore ofHard(long hardScore) { + public static @NonNull HardSoftLongScore ofHard(long hardScore) { // Optimization for frequently seen values. if (hardScore == -1L) { return MINUS_ONE_HARD; @@ -74,7 +76,7 @@ public static HardSoftLongScore ofHard(long hardScore) { return new HardSoftLongScore(0, hardScore, 0L); } - public static HardSoftLongScore ofSoft(long softScore) { + public static @NonNull HardSoftLongScore ofSoft(long softScore) { // Optimization for frequently seen values. if (softScore == -1L) { return MINUS_ONE_SOFT; @@ -165,7 +167,7 @@ public long getSoftScore() { // ************************************************************************ @Override - public HardSoftLongScore withInitScore(int newInitScore) { + public @NonNull HardSoftLongScore withInitScore(int newInitScore) { return ofUninitialized(newInitScore, hardScore, softScore); } @@ -175,7 +177,7 @@ public boolean isFeasible() { } @Override - public HardSoftLongScore add(HardSoftLongScore addend) { + public @NonNull HardSoftLongScore add(@NonNull HardSoftLongScore addend) { return ofUninitialized( initScore + addend.initScore(), hardScore + addend.hardScore(), @@ -183,7 +185,7 @@ public HardSoftLongScore add(HardSoftLongScore addend) { } @Override - public HardSoftLongScore subtract(HardSoftLongScore subtrahend) { + public @NonNull HardSoftLongScore subtract(@NonNull HardSoftLongScore subtrahend) { return ofUninitialized( initScore - subtrahend.initScore(), hardScore - subtrahend.hardScore(), @@ -191,7 +193,7 @@ public HardSoftLongScore subtract(HardSoftLongScore subtrahend) { } @Override - public HardSoftLongScore multiply(double multiplicand) { + public @NonNull HardSoftLongScore multiply(double multiplicand) { return ofUninitialized( (int) Math.floor(initScore * multiplicand), (long) Math.floor(hardScore * multiplicand), @@ -199,7 +201,7 @@ public HardSoftLongScore multiply(double multiplicand) { } @Override - public HardSoftLongScore divide(double divisor) { + public @NonNull HardSoftLongScore divide(double divisor) { return ofUninitialized( (int) Math.floor(initScore / divisor), (long) Math.floor(hardScore / divisor), @@ -207,7 +209,7 @@ public HardSoftLongScore divide(double divisor) { } @Override - public HardSoftLongScore power(double exponent) { + public @NonNull HardSoftLongScore power(double exponent) { return ofUninitialized( (int) Math.floor(Math.pow(initScore, exponent)), (long) Math.floor(Math.pow(hardScore, exponent)), @@ -215,17 +217,17 @@ public HardSoftLongScore power(double exponent) { } @Override - public HardSoftLongScore abs() { + public @NonNull HardSoftLongScore abs() { return ofUninitialized(Math.abs(initScore), Math.abs(hardScore), Math.abs(softScore)); } @Override - public HardSoftLongScore zero() { + public @NonNull HardSoftLongScore zero() { return ZERO; } @Override - public Number[] toLevelNumbers() { + public Number @NonNull [] toLevelNumbers() { return new Number[] { hardScore, softScore }; } @@ -245,7 +247,7 @@ public int hashCode() { } @Override - public int compareTo(HardSoftLongScore other) { + public int compareTo(@NonNull HardSoftLongScore other) { if (initScore != other.initScore()) { return Integer.compare(initScore, other.initScore()); } else if (hardScore != other.hardScore()) { @@ -256,7 +258,7 @@ public int compareTo(HardSoftLongScore other) { } @Override - public String toShortString() { + public @NonNull String toShortString() { return ScoreUtil.buildShortString(this, n -> n.longValue() != 0L, HARD_LABEL, SOFT_LABEL); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/simple/SimpleScore.java b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/simple/SimpleScore.java index 66ab62d3aa..d2d8ed7fd6 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/simple/SimpleScore.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/simple/SimpleScore.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.impl.score.ScoreUtil; +import org.jspecify.annotations.NonNull; + /** * This {@link Score} is based on 1 level of int constraints. *

@@ -18,21 +20,21 @@ public final class SimpleScore implements Score { public static final SimpleScore ONE = new SimpleScore(0, 1); private static final SimpleScore MINUS_ONE = new SimpleScore(0, -1); - public static SimpleScore parseScore(String scoreString) { + public static @NonNull SimpleScore parseScore(@NonNull String scoreString) { String[] scoreTokens = ScoreUtil.parseScoreTokens(SimpleScore.class, scoreString, ""); int initScore = ScoreUtil.parseInitScore(SimpleScore.class, scoreString, scoreTokens[0]); int score = ScoreUtil.parseLevelAsInt(SimpleScore.class, scoreString, scoreTokens[1]); return ofUninitialized(initScore, score); } - public static SimpleScore ofUninitialized(int initScore, int score) { + public static @NonNull SimpleScore ofUninitialized(int initScore, int score) { if (initScore == 0) { return of(score); } return new SimpleScore(initScore, score); } - public static SimpleScore of(int score) { + public static @NonNull SimpleScore of(int score) { return switch (score) { case -1 -> MINUS_ONE; case 0 -> ZERO; @@ -94,52 +96,52 @@ public int getScore() { // ************************************************************************ @Override - public SimpleScore withInitScore(int newInitScore) { + public @NonNull SimpleScore withInitScore(int newInitScore) { return ofUninitialized(newInitScore, score); } @Override - public SimpleScore add(SimpleScore addend) { + public @NonNull SimpleScore add(@NonNull SimpleScore addend) { return ofUninitialized( initScore + addend.initScore(), score + addend.score()); } @Override - public SimpleScore subtract(SimpleScore subtrahend) { + public @NonNull SimpleScore subtract(@NonNull SimpleScore subtrahend) { return ofUninitialized( initScore - subtrahend.initScore(), score - subtrahend.score()); } @Override - public SimpleScore multiply(double multiplicand) { + public @NonNull SimpleScore multiply(double multiplicand) { return ofUninitialized( (int) Math.floor(initScore * multiplicand), (int) Math.floor(score * multiplicand)); } @Override - public SimpleScore divide(double divisor) { + public @NonNull SimpleScore divide(double divisor) { return ofUninitialized( (int) Math.floor(initScore / divisor), (int) Math.floor(score / divisor)); } @Override - public SimpleScore power(double exponent) { + public @NonNull SimpleScore power(double exponent) { return ofUninitialized( (int) Math.floor(Math.pow(initScore, exponent)), (int) Math.floor(Math.pow(score, exponent))); } @Override - public SimpleScore abs() { + public @NonNull SimpleScore abs() { return ofUninitialized(Math.abs(initScore), Math.abs(score)); } @Override - public SimpleScore zero() { + public @NonNull SimpleScore zero() { return ZERO; } @@ -149,7 +151,7 @@ public boolean isFeasible() { } @Override - public Number[] toLevelNumbers() { + public Number @NonNull [] toLevelNumbers() { return new Number[] { score }; } @@ -168,7 +170,7 @@ public int hashCode() { } @Override - public int compareTo(SimpleScore other) { + public int compareTo(@NonNull SimpleScore other) { if (initScore != other.initScore()) { return Integer.compare(initScore, other.initScore()); } else { @@ -177,7 +179,7 @@ public int compareTo(SimpleScore other) { } @Override - public String toShortString() { + public @NonNull String toShortString() { return ScoreUtil.buildShortString(this, n -> n.intValue() != 0, ""); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/simplebigdecimal/SimpleBigDecimalScore.java b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/simplebigdecimal/SimpleBigDecimalScore.java index a761370f4d..ab11406cd1 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/simplebigdecimal/SimpleBigDecimalScore.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/simplebigdecimal/SimpleBigDecimalScore.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.impl.score.ScoreUtil; +import org.jspecify.annotations.NonNull; + /** * This {@link Score} is based on 1 level of {@link BigDecimal} constraints. *

@@ -16,24 +18,24 @@ */ public final class SimpleBigDecimalScore implements Score { - public static final SimpleBigDecimalScore ZERO = new SimpleBigDecimalScore(0, BigDecimal.ZERO); - public static final SimpleBigDecimalScore ONE = new SimpleBigDecimalScore(0, BigDecimal.ONE); + public static final @NonNull SimpleBigDecimalScore ZERO = new SimpleBigDecimalScore(0, BigDecimal.ZERO); + public static final @NonNull SimpleBigDecimalScore ONE = new SimpleBigDecimalScore(0, BigDecimal.ONE); - public static SimpleBigDecimalScore parseScore(String scoreString) { + public static @NonNull SimpleBigDecimalScore parseScore(@NonNull String scoreString) { String[] scoreTokens = ScoreUtil.parseScoreTokens(SimpleBigDecimalScore.class, scoreString, ""); int initScore = ScoreUtil.parseInitScore(SimpleBigDecimalScore.class, scoreString, scoreTokens[0]); BigDecimal score = ScoreUtil.parseLevelAsBigDecimal(SimpleBigDecimalScore.class, scoreString, scoreTokens[1]); return ofUninitialized(initScore, score); } - public static SimpleBigDecimalScore ofUninitialized(int initScore, BigDecimal score) { + public static @NonNull SimpleBigDecimalScore ofUninitialized(int initScore, @NonNull BigDecimal score) { if (initScore == 0) { return of(score); } return new SimpleBigDecimalScore(initScore, score); } - public static SimpleBigDecimalScore of(BigDecimal score) { + public static @NonNull SimpleBigDecimalScore of(@NonNull BigDecimal score) { if (score.signum() == 0) { return ZERO; } else if (score.equals(BigDecimal.ONE)) { @@ -48,7 +50,7 @@ public static SimpleBigDecimalScore of(BigDecimal score) { // ************************************************************************ private final int initScore; - private final BigDecimal score; + private final @NonNull BigDecimal score; /** * Private default constructor for default marshalling/unmarshalling of unknown frameworks that use reflection. @@ -57,10 +59,10 @@ public static SimpleBigDecimalScore of(BigDecimal score) { */ @SuppressWarnings("unused") private SimpleBigDecimalScore() { - this(Integer.MIN_VALUE, null); + this(Integer.MIN_VALUE, BigDecimal.ZERO); } - private SimpleBigDecimalScore(int initScore, BigDecimal score) { + private SimpleBigDecimalScore(int initScore, @NonNull BigDecimal score) { this.initScore = initScore; this.score = score; } @@ -77,7 +79,7 @@ public int initScore() { * * @return higher is better, usually negative, 0 if no constraints are broken/fulfilled */ - public BigDecimal score() { + public @NonNull BigDecimal score() { return score; } @@ -87,7 +89,7 @@ public BigDecimal score() { * @deprecated Use {@link #score()} instead. */ @Deprecated(forRemoval = true) - public BigDecimal getScore() { + public @NonNull BigDecimal getScore() { return score; } @@ -96,26 +98,26 @@ public BigDecimal getScore() { // ************************************************************************ @Override - public SimpleBigDecimalScore withInitScore(int newInitScore) { + public @NonNull SimpleBigDecimalScore withInitScore(int newInitScore) { return ofUninitialized(newInitScore, score); } @Override - public SimpleBigDecimalScore add(SimpleBigDecimalScore addend) { + public @NonNull SimpleBigDecimalScore add(@NonNull SimpleBigDecimalScore addend) { return ofUninitialized( initScore + addend.initScore(), score.add(addend.score())); } @Override - public SimpleBigDecimalScore subtract(SimpleBigDecimalScore subtrahend) { + public @NonNull SimpleBigDecimalScore subtract(@NonNull SimpleBigDecimalScore subtrahend) { return ofUninitialized( initScore - subtrahend.initScore(), score.subtract(subtrahend.score())); } @Override - public SimpleBigDecimalScore multiply(double multiplicand) { + public @NonNull SimpleBigDecimalScore multiply(double multiplicand) { // Intentionally not taken "new BigDecimal(multiplicand, MathContext.UNLIMITED)" // because together with the floor rounding it gives unwanted behaviour BigDecimal multiplicandBigDecimal = BigDecimal.valueOf(multiplicand); @@ -126,7 +128,7 @@ public SimpleBigDecimalScore multiply(double multiplicand) { } @Override - public SimpleBigDecimalScore divide(double divisor) { + public @NonNull SimpleBigDecimalScore divide(double divisor) { // Intentionally not taken "new BigDecimal(multiplicand, MathContext.UNLIMITED)" // because together with the floor rounding it gives unwanted behaviour BigDecimal divisorBigDecimal = BigDecimal.valueOf(divisor); @@ -137,7 +139,7 @@ public SimpleBigDecimalScore divide(double divisor) { } @Override - public SimpleBigDecimalScore power(double exponent) { + public @NonNull SimpleBigDecimalScore power(double exponent) { // Intentionally not taken "new BigDecimal(multiplicand, MathContext.UNLIMITED)" // because together with the floor rounding it gives unwanted behaviour BigDecimal exponentBigDecimal = BigDecimal.valueOf(exponent); @@ -150,12 +152,12 @@ public SimpleBigDecimalScore power(double exponent) { } @Override - public SimpleBigDecimalScore abs() { + public @NonNull SimpleBigDecimalScore abs() { return ofUninitialized(Math.abs(initScore), score.abs()); } @Override - public SimpleBigDecimalScore zero() { + public @NonNull SimpleBigDecimalScore zero() { return ZERO; } @@ -165,7 +167,7 @@ public boolean isFeasible() { } @Override - public Number[] toLevelNumbers() { + public @NonNull Number @NonNull [] toLevelNumbers() { return new Number[] { score }; } @@ -184,7 +186,7 @@ public int hashCode() { } @Override - public int compareTo(SimpleBigDecimalScore other) { + public int compareTo(@NonNull SimpleBigDecimalScore other) { if (initScore != other.initScore()) { return Integer.compare(initScore, other.initScore()); } else { @@ -193,7 +195,7 @@ public int compareTo(SimpleBigDecimalScore other) { } @Override - public String toShortString() { + public @NonNull String toShortString() { return ScoreUtil.buildShortString(this, n -> ((BigDecimal) n).compareTo(BigDecimal.ZERO) != 0, ""); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/simplelong/SimpleLongScore.java b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/simplelong/SimpleLongScore.java index 882f9d2afb..34a0cb7215 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/buildin/simplelong/SimpleLongScore.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/buildin/simplelong/SimpleLongScore.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.impl.score.ScoreUtil; +import org.jspecify.annotations.NonNull; + /** * This {@link Score} is based on 1 level of long constraints. *

@@ -18,21 +20,21 @@ public final class SimpleLongScore implements Score { public static final SimpleLongScore ONE = new SimpleLongScore(0, 1L); public static final SimpleLongScore MINUS_ONE = new SimpleLongScore(0, -1L); - public static SimpleLongScore parseScore(String scoreString) { + public static @NonNull SimpleLongScore parseScore(@NonNull String scoreString) { String[] scoreTokens = ScoreUtil.parseScoreTokens(SimpleLongScore.class, scoreString, ""); int initScore = ScoreUtil.parseInitScore(SimpleLongScore.class, scoreString, scoreTokens[0]); long score = ScoreUtil.parseLevelAsLong(SimpleLongScore.class, scoreString, scoreTokens[1]); return ofUninitialized(initScore, score); } - public static SimpleLongScore ofUninitialized(int initScore, long score) { + public static @NonNull SimpleLongScore ofUninitialized(int initScore, long score) { if (initScore == 0) { return of(score); } return new SimpleLongScore(initScore, score); } - public static SimpleLongScore of(long score) { + public static @NonNull SimpleLongScore of(long score) { if (score == -1L) { return MINUS_ONE; } else if (score == 0L) { @@ -97,52 +99,52 @@ public long getScore() { // ************************************************************************ @Override - public SimpleLongScore withInitScore(int newInitScore) { + public @NonNull SimpleLongScore withInitScore(int newInitScore) { return ofUninitialized(newInitScore, score); } @Override - public SimpleLongScore add(SimpleLongScore addend) { + public @NonNull SimpleLongScore add(@NonNull SimpleLongScore addend) { return ofUninitialized( initScore + addend.initScore(), score + addend.score()); } @Override - public SimpleLongScore subtract(SimpleLongScore subtrahend) { + public @NonNull SimpleLongScore subtract(@NonNull SimpleLongScore subtrahend) { return ofUninitialized( initScore - subtrahend.initScore(), score - subtrahend.score()); } @Override - public SimpleLongScore multiply(double multiplicand) { + public @NonNull SimpleLongScore multiply(double multiplicand) { return ofUninitialized( (int) Math.floor(initScore * multiplicand), (long) Math.floor(score * multiplicand)); } @Override - public SimpleLongScore divide(double divisor) { + public @NonNull SimpleLongScore divide(double divisor) { return ofUninitialized( (int) Math.floor(initScore / divisor), (long) Math.floor(score / divisor)); } @Override - public SimpleLongScore power(double exponent) { + public @NonNull SimpleLongScore power(double exponent) { return ofUninitialized( (int) Math.floor(Math.pow(initScore, exponent)), (long) Math.floor(Math.pow(score, exponent))); } @Override - public SimpleLongScore abs() { + public @NonNull SimpleLongScore abs() { return ofUninitialized(Math.abs(initScore), Math.abs(score)); } @Override - public SimpleLongScore zero() { + public @NonNull SimpleLongScore zero() { return ZERO; } @@ -152,7 +154,7 @@ public boolean isFeasible() { } @Override - public Number[] toLevelNumbers() { + public Number @NonNull [] toLevelNumbers() { return new Number[] { score }; } @@ -171,7 +173,7 @@ public int hashCode() { } @Override - public int compareTo(SimpleLongScore other) { + public int compareTo(@NonNull SimpleLongScore other) { if (initScore != other.initScore()) { return Integer.compare(initScore, other.initScore()); } else { @@ -180,7 +182,7 @@ public int compareTo(SimpleLongScore other) { } @Override - public String toShortString() { + public @NonNull String toShortString() { return ScoreUtil.buildShortString(this, n -> n.longValue() != 0L, ""); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/calculator/ConstraintMatchAwareIncrementalScoreCalculator.java b/core/src/main/java/ai/timefold/solver/core/api/score/calculator/ConstraintMatchAwareIncrementalScoreCalculator.java index ea5ae5afda..396b0232f0 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/calculator/ConstraintMatchAwareIncrementalScoreCalculator.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/calculator/ConstraintMatchAwareIncrementalScoreCalculator.java @@ -9,6 +9,9 @@ import ai.timefold.solver.core.api.score.constraint.ConstraintMatchTotal; import ai.timefold.solver.core.api.score.constraint.Indictment; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Allows a {@link IncrementalScoreCalculator} to report {@link ConstraintMatchTotal}s * for explaining a score (= which score constraints match for how much) @@ -26,10 +29,10 @@ public interface ConstraintMatchAwareIncrementalScoreCalculator> getConstraintMatchTotals(); /** @@ -44,6 +48,7 @@ public interface ConstraintMatchAwareIncrementalScoreCalculator> getIndictmentMap(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/calculator/EasyScoreCalculator.java b/core/src/main/java/ai/timefold/solver/core/api/score/calculator/EasyScoreCalculator.java index 7f67fda934..f9e4f94fb1 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/calculator/EasyScoreCalculator.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/calculator/EasyScoreCalculator.java @@ -3,6 +3,8 @@ import ai.timefold.solver.core.api.domain.solution.PlanningSolution; import ai.timefold.solver.core.api.score.Score; +import org.jspecify.annotations.NonNull; + /** * Used for easy java {@link Score} calculation. This is non-incremental calculation, which is slow. *

@@ -17,9 +19,8 @@ public interface EasyScoreCalculator> { * This method is only called if the {@link Score} cannot be predicted. * The {@link Score} can be predicted for example after an undo move. * - * @param solution never null - * @return never null */ - Score_ calculateScore(Solution_ solution); + @NonNull + Score_ calculateScore(@NonNull Solution_ solution); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/calculator/IncrementalScoreCalculator.java b/core/src/main/java/ai/timefold/solver/core/api/score/calculator/IncrementalScoreCalculator.java index f8e161c681..f0e25312ea 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/calculator/IncrementalScoreCalculator.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/calculator/IncrementalScoreCalculator.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.domain.variable.PlanningVariable; import ai.timefold.solver.core.api.score.Score; +import org.jspecify.annotations.NonNull; + /** * Used for incremental java {@link Score} calculation. * This is much faster than {@link EasyScoreCalculator} but requires much more code to implement too. @@ -19,67 +21,64 @@ public interface IncrementalScoreCalculator indictedObjectList, Score_ score) { + public ConstraintMatch(@NonNull ConstraintRef constraintRef, @NonNull ConstraintJustification justification, + @NonNull Collection indictedObjectList, @NonNull Score_ score) { this.constraintRef = requireNonNull(constraintRef); this.justification = requireNonNull(justification); this.indictedObjectList = @@ -97,7 +94,7 @@ public ConstraintMatch(ConstraintRef constraintRef, ConstraintJustification just this.score = requireNonNull(score); } - public ConstraintRef getConstraintRef() { + public @NonNull ConstraintRef getConstraintRef() { return constraintRef; } @@ -164,10 +161,8 @@ public List getJustificationList() { * in which case it returns the return value of that function. *
  • For incremental score calculation, it returns what the calculator is implemented to return.
  • * - * - * @return never null */ - public Justification_ getJustification() { + public @NonNull Justification_ getJustification() { return (Justification_) justification; } @@ -182,13 +177,13 @@ public Justification_ getJustif *
  • For incremental score calculation, it returns what the calculator is implemented to return.
  • * * - * @return never null, may be empty or contain null + * @return may be empty or contain null */ - public List getIndictedObjectList() { + public @NonNull List getIndictedObjectList() { return indictedObjectList; } - public Score_ getScore() { + public @NonNull Score_ getScore() { return score; } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/constraint/ConstraintMatchTotal.java b/core/src/main/java/ai/timefold/solver/core/api/score/constraint/ConstraintMatchTotal.java index 667d5f6de3..5484c4f5fa 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/constraint/ConstraintMatchTotal.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/constraint/ConstraintMatchTotal.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.ScoreExplanation; import ai.timefold.solver.core.api.solver.SolutionManager; +import org.jspecify.annotations.NonNull; + /** * Explains the {@link Score} of a {@link PlanningSolution}, from the opposite side than {@link Indictment}. * Retrievable from {@link ScoreExplanation#getConstraintMatchTotalMap()}. @@ -30,9 +32,7 @@ static String composeConstraintId(String constraintPackage, String constraintNam return constraintPackage + "/" + constraintName; } - /** - * @return never null - */ + @NonNull ConstraintRef getConstraintRef(); /** @@ -57,14 +57,11 @@ default String getConstraintName() { * The effective value of constraint weight after applying optional overrides. * It is independent to the state of the {@link PlanningVariable planning variables}. * Do not confuse with {@link #getScore()}. - * - * @return never null */ + @NonNull Score_ getConstraintWeight(); - /** - * @return never null - */ + @NonNull Set> getConstraintMatchSet(); /** @@ -76,9 +73,8 @@ default int getConstraintMatchCount() { /** * Sum of the {@link #getConstraintMatchSet()}'s {@link ConstraintMatch#getScore()}. - * - * @return never null */ + @NonNull Score_ getScore(); /** diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/constraint/ConstraintRef.java b/core/src/main/java/ai/timefold/solver/core/api/score/constraint/ConstraintRef.java index 3f8ba66e2e..5657951e8c 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/constraint/ConstraintRef.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/constraint/ConstraintRef.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.domain.constraintweight.ConstraintConfiguration; import ai.timefold.solver.core.api.domain.constraintweight.ConstraintWeight; +import org.jspecify.annotations.NonNull; + /** * Represents a unique identifier of a constraint. *

    @@ -23,7 +25,7 @@ * it is equal to the {@link ConstraintWeight#value()}. * @param constraintId Always derived from {@code packageName} and {@code constraintName}. */ -public record ConstraintRef(String packageName, String constraintName, String constraintId) +public record ConstraintRef(@NonNull String packageName, @NonNull String constraintName, String constraintId) implements Comparable { diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/constraint/Indictment.java b/core/src/main/java/ai/timefold/solver/core/api/score/constraint/Indictment.java index 07fd6ebab5..45644647b3 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/constraint/Indictment.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/constraint/Indictment.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.api.score.ScoreExplanation; import ai.timefold.solver.core.api.score.stream.ConstraintJustification; +import org.jspecify.annotations.NonNull; + /** * Explains the {@link Score} of a {@link PlanningSolution}, from the opposite side than {@link ConstraintMatchTotal}. * Retrievable from {@link ScoreExplanation#getIndictmentMap()}. @@ -36,14 +38,11 @@ default Object getJustification() { * It is part of {@link ConstraintMatch#getIndictedObjectList()} of every {@link ConstraintMatch} * returned by {@link #getConstraintMatchSet()}. * - * @return never null * @param Shorthand so that the user does not need to cast in user code. */ - IndictedObject_ getIndictedObject(); + @NonNull IndictedObject_ getIndictedObject(); - /** - * @return never null - */ + @NonNull Set> getConstraintMatchSet(); /** @@ -59,8 +58,9 @@ default int getConstraintMatchCount() { * This is equivalent to retrieving {@link #getConstraintMatchSet()} * and collecting all {@link ConstraintMatch#getJustification()} objects into a list. * - * @return never null, guaranteed to contain unique instances + * @return guaranteed to contain unique instances */ + @NonNull List getJustificationList(); /** @@ -69,8 +69,9 @@ default int getConstraintMatchCount() { * This is equivalent to retrieving {@link #getConstraintMatchSet()} * and collecting all matching {@link ConstraintMatch#getJustification()} objects into a list. * - * @return never null, guaranteed to contain unique instances + * @return guaranteed to contain unique instances */ + @NonNull default List getJustificationList(Class justificationClass) { return getJustificationList() @@ -82,9 +83,8 @@ default int getConstraintMatchCount() { /** * Sum of the {@link #getConstraintMatchSet()}'s {@link ConstraintMatch#getScore()}. - * - * @return never null */ + @NonNull Score_ getScore(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/director/ScoreDirector.java b/core/src/main/java/ai/timefold/solver/core/api/score/director/ScoreDirector.java index 67ce0651e8..02df8237e1 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/director/ScoreDirector.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/director/ScoreDirector.java @@ -6,6 +6,9 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.api.solver.change.ProblemChange; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * The ScoreDirector holds the {@link PlanningSolution working solution} * and calculates the {@link Score} for it. @@ -19,9 +22,8 @@ public interface ScoreDirector { *

    * Because a {@link Score} is best calculated incrementally (by deltas), * the {@link ScoreDirector} needs to be notified when its {@link PlanningSolution working solution} changes. - * - * @return never null */ + @NonNull Solution_ getWorkingSolution(); void beforeVariableChanged(Object entity, String variableName); @@ -140,14 +142,13 @@ default void afterProblemFactRemoved(Object problemFact) { * Matching is determined by the {@link LookUpStrategyType} on {@link PlanningSolution}. * Matching uses a {@link PlanningId} by default. * - * @param externalObject sometimes null * @return null if externalObject is null * @throws IllegalArgumentException if there is no workingObject for externalObject, if it cannot be looked up * or if the externalObject's class is not supported * @throws IllegalStateException if it cannot be looked up * @param the object type */ - E lookUpWorkingObject(E externalObject); + @Nullable E lookUpWorkingObject(@Nullable E externalObject); /** * As defined by {@link #lookUpWorkingObject(Object)}, @@ -155,12 +156,11 @@ default void afterProblemFactRemoved(Object problemFact) { * It's recommended to use {@link #lookUpWorkingObject(Object)} instead, * especially in move rebasing code. * - * @param externalObject sometimes null * @return null if externalObject is null or if there is no workingObject for externalObject * @throws IllegalArgumentException if it cannot be looked up or if the externalObject's class is not supported * @throws IllegalStateException if it cannot be looked up * @param the object type */ - E lookUpWorkingObjectOrReturnNull(E externalObject); + @Nullable E lookUpWorkingObjectOrReturnNull(@Nullable E externalObject); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/Constraint.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/Constraint.java index fc6783e09a..4da1be1641 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/Constraint.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/Constraint.java @@ -3,6 +3,9 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.api.score.constraint.ConstraintRef; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * This represents a single constraint in the {@link ConstraintStream} API * that impacts the {@link Score}. @@ -28,13 +31,13 @@ public interface Constraint { * Returns a human-friendly description of the constraint. * The format of the description is left unspecified and will not be parsed in any way. * - * @return never null, may be left empty + * @return may be left empty */ - default String getDescription() { + default @NonNull String getDescription() { return ""; } - default String getConstraintGroup() { + default @NonNull String getConstraintGroup() { return DEFAULT_CONSTRAINT_GROUP; } @@ -44,7 +47,7 @@ default String getConstraintGroup() { * * @return null if the constraint does not have a weight defined */ - default > Score_ getConstraintWeight() { + default > @Nullable Score_ getConstraintWeight() { return null; } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintBuilder.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintBuilder.java index bada819427..542a8a8ef4 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintBuilder.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintBuilder.java @@ -4,6 +4,8 @@ import ai.timefold.solver.core.api.score.constraint.ConstraintMatchTotal; import ai.timefold.solver.core.api.score.constraint.ConstraintRef; +import org.jspecify.annotations.NonNull; + public interface ConstraintBuilder { /** @@ -11,10 +13,9 @@ public interface ConstraintBuilder { * The {@link ConstraintRef#packageName() constraint package} defaults to the package of the {@link PlanningSolution} class. * The constraint will be placed in the {@link Constraint#DEFAULT_CONSTRAINT_GROUP default constraint group}. * - * @param constraintName never null, shows up in {@link ConstraintMatchTotal} during score justification - * @return never null + * @param constraintName shows up in {@link ConstraintMatchTotal} during score justification */ - default Constraint asConstraint(String constraintName) { + default @NonNull Constraint asConstraint(@NonNull String constraintName) { return asConstraintDescribed(constraintName, ""); } @@ -23,11 +24,10 @@ default Constraint asConstraint(String constraintName) { * The {@link ConstraintRef#packageName() constraint package} defaults to the package of the {@link PlanningSolution} class. * The constraint will be placed in the {@link Constraint#DEFAULT_CONSTRAINT_GROUP default constraint group}. * - * @param constraintName never null, shows up in {@link ConstraintMatchTotal} during score justification - * @param constraintDescription never null - * @return never null + * @param constraintName shows up in {@link ConstraintMatchTotal} during score justification */ - default Constraint asConstraintDescribed(String constraintName, String constraintDescription) { + @NonNull + default Constraint asConstraintDescribed(@NonNull String constraintName, @NonNull String constraintDescription) { return asConstraintDescribed(constraintName, constraintDescription, Constraint.DEFAULT_CONSTRAINT_GROUP); } @@ -35,12 +35,12 @@ default Constraint asConstraintDescribed(String constraintName, String constrain * Builds a {@link Constraint} from the constraint stream. * The {@link ConstraintRef#packageName() constraint package} defaults to the package of the {@link PlanningSolution} class. * - * @param constraintName never null, shows up in {@link ConstraintMatchTotal} during score justification - * @param constraintDescription never null - * @param constraintGroup never null, only allows alphanumeric characters, "-" and "_" - * @return never null + * @param constraintName shows up in {@link ConstraintMatchTotal} during score justification + * @param constraintGroup only allows alphanumeric characters, "-" and "_" */ - Constraint asConstraintDescribed(String constraintName, String constraintDescription, String constraintGroup); + @NonNull + Constraint asConstraintDescribed(@NonNull String constraintName, @NonNull String constraintDescription, + @NonNull String constraintGroup); /** * Builds a {@link Constraint} from the constraint stream. diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintCollectors.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintCollectors.java index ae36796f77..fc0137cfe0 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintCollectors.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintCollectors.java @@ -51,6 +51,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.uni.InnerUniConstraintCollectors; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + /** * Creates an {@link UniConstraintCollector}, {@link BiConstraintCollector}, ... instance * for use in {@link UniConstraintStream#groupBy(Function, UniConstraintCollector)}, ... @@ -69,58 +71,57 @@ public final class ConstraintCollectors { * The default result of the collector (e.g. when never called) is {@code 0}. * * @param type of the matched fact - * @return never null */ - public static UniConstraintCollector count() { + public static @NonNull UniConstraintCollector count() { return InnerUniConstraintCollectors.count(); } /** * As defined by {@link #count()}. */ - public static UniConstraintCollector countLong() { + public static @NonNull UniConstraintCollector countLong() { return InnerUniConstraintCollectors.countLong(); } /** * As defined by {@link #count()}. */ - public static BiConstraintCollector countBi() { + public static @NonNull BiConstraintCollector countBi() { return InnerBiConstraintCollectors.count(); } /** * As defined by {@link #count()}. */ - public static BiConstraintCollector countLongBi() { + public static @NonNull BiConstraintCollector countLongBi() { return InnerBiConstraintCollectors.countLong(); } /** * As defined by {@link #count()}. */ - public static TriConstraintCollector countTri() { + public static @NonNull TriConstraintCollector countTri() { return InnerTriConstraintCollectors.count(); } /** * As defined by {@link #count()}. */ - public static TriConstraintCollector countLongTri() { + public static @NonNull TriConstraintCollector countLongTri() { return InnerTriConstraintCollectors.countLong(); } /** * As defined by {@link #count()}. */ - public static QuadConstraintCollector countQuad() { + public static @NonNull QuadConstraintCollector countQuad() { return InnerQuadConstraintCollectors.count(); } /** * As defined by {@link #count()}. */ - public static QuadConstraintCollector countLongQuad() { + public static @NonNull QuadConstraintCollector countLongQuad() { return InnerQuadConstraintCollectors.countLong(); } @@ -145,64 +146,63 @@ public final class ConstraintCollectors { * The default result of the collector (e.g. when never called) is {@code 0}. * * @param type of the matched fact - * @return never null */ - public static UniConstraintCollector countDistinct(Function groupValueMapping) { + public static @NonNull UniConstraintCollector countDistinct(@NonNull Function groupValueMapping) { return InnerUniConstraintCollectors.countDistinct(groupValueMapping); } /** * As defined by {@link #countDistinct(Function)}. */ - public static UniConstraintCollector countDistinctLong(Function groupValueMapping) { + public static @NonNull UniConstraintCollector countDistinctLong(@NonNull Function groupValueMapping) { return InnerUniConstraintCollectors.countDistinctLong(groupValueMapping); } /** * As defined by {@link #countDistinct(Function)}. */ - public static BiConstraintCollector countDistinct( - BiFunction groupValueMapping) { + public static @NonNull BiConstraintCollector countDistinct( + @NonNull BiFunction groupValueMapping) { return InnerBiConstraintCollectors.countDistinct(groupValueMapping); } /** * As defined by {@link #countDistinct(Function)}. */ - public static BiConstraintCollector countDistinctLong( - BiFunction groupValueMapping) { + public static @NonNull BiConstraintCollector countDistinctLong( + @NonNull BiFunction groupValueMapping) { return InnerBiConstraintCollectors.countDistinctLong(groupValueMapping); } /** * As defined by {@link #countDistinct(Function)}. */ - public static TriConstraintCollector countDistinct( - TriFunction groupValueMapping) { + public static @NonNull TriConstraintCollector countDistinct( + @NonNull TriFunction groupValueMapping) { return InnerTriConstraintCollectors.countDistinct(groupValueMapping); } /** * As defined by {@link #countDistinct(Function)}. */ - public static TriConstraintCollector countDistinctLong( - TriFunction groupValueMapping) { + public static @NonNull TriConstraintCollector countDistinctLong( + @NonNull TriFunction groupValueMapping) { return InnerTriConstraintCollectors.countDistinctLong(groupValueMapping); } /** * As defined by {@link #countDistinct(Function)}. */ - public static QuadConstraintCollector countDistinct( - QuadFunction groupValueMapping) { + public static @NonNull QuadConstraintCollector countDistinct( + @NonNull QuadFunction groupValueMapping) { return InnerQuadConstraintCollectors.countDistinct(groupValueMapping); } /** * As defined by {@link #countDistinct(Function)}. */ - public static QuadConstraintCollector countDistinctLong( - QuadFunction groupValueMapping) { + public static @NonNull QuadConstraintCollector countDistinctLong( + @NonNull QuadFunction groupValueMapping) { return InnerQuadConstraintCollectors.countDistinctLong(groupValueMapping); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintFactory.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintFactory.java index 9c3a80a79e..e7804ebbac 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintFactory.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintFactory.java @@ -14,6 +14,8 @@ import ai.timefold.solver.core.api.score.stream.bi.BiJoiner; import ai.timefold.solver.core.api.score.stream.uni.UniConstraintStream; +import org.jspecify.annotations.NonNull; + /** * The factory to create every {@link ConstraintStream} (for example with {@link #forEach(Class)}) * which ends in a {@link Constraint} returned by {@link ConstraintProvider#defineConstraints(ConstraintFactory)}. @@ -21,10 +23,10 @@ public interface ConstraintFactory { /** - * @return never null * @deprecated Do not rely on any constraint package in user code. */ @Deprecated(forRemoval = true, since = "1.13.0") + @NonNull String getDefaultConstraintPackage(); // ************************************************************************ @@ -59,19 +61,17 @@ public interface ConstraintFactory { * Adding the field is strongly recommended. * * - * @param sourceClass never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} - * @return never null */ - UniConstraintStream forEach(Class sourceClass); + @NonNull UniConstraintStream forEach(@NonNull Class sourceClass); /** * As defined by {@link #forEachIncludingUnassigned(Class)}. - * + * * @deprecated Use {@link #forEachIncludingUnassigned(Class)} instead. */ @Deprecated(forRemoval = true, since = "1.8.0") - default UniConstraintStream forEachIncludingNullVars(Class sourceClass) { + default @NonNull UniConstraintStream forEachIncludingNullVars(@NonNull Class sourceClass) { return forEachIncludingUnassigned(sourceClass); } @@ -82,11 +82,9 @@ default UniConstraintStream forEachIncludingNullVars(Class sourceClass * or shadow entities not assigned to any applicable list variable * (for {@link PlanningListVariable#allowsUnassignedValues()}). * - * @param sourceClass never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} - * @return never null */ - UniConstraintStream forEachIncludingUnassigned(Class sourceClass); + @NonNull UniConstraintStream forEachIncludingUnassigned(@NonNull Class sourceClass); /** * Create a new {@link BiConstraintStream} for every unique combination of A and another A with a higher {@link PlanningId}. @@ -99,11 +97,10 @@ default UniConstraintStream forEachIncludingNullVars(Class sourceClass * This method is syntactic sugar for {@link UniConstraintStream#join(Class)}. * It automatically adds a {@link Joiners#lessThan(Function) lessThan} joiner on the {@link PlanningId} of A. * - * @param sourceClass never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @return a stream that matches every unique combination of A and another A */ - default BiConstraintStream forEachUniquePair(Class sourceClass) { + default @NonNull BiConstraintStream forEachUniquePair(@NonNull Class sourceClass) { return forEachUniquePair(sourceClass, new BiJoiner[0]); } @@ -121,60 +118,50 @@ default BiConstraintStream forEachUniquePair(Class sourceClass) { *

    * This method has overloaded methods with multiple {@link BiJoiner} parameters. * - * @param sourceClass never null - * @param joiner never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @return a stream that matches every unique combination of A and another A for which the {@link BiJoiner} is true */ - default BiConstraintStream forEachUniquePair(Class sourceClass, BiJoiner joiner) { + default @NonNull BiConstraintStream forEachUniquePair(@NonNull Class sourceClass, + @NonNull BiJoiner joiner) { return forEachUniquePair(sourceClass, new BiJoiner[] { joiner }); } /** * As defined by {@link #forEachUniquePair(Class, BiJoiner)}. * - * @param sourceClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @return a stream that matches every unique combination of A and another A for which all the * {@link BiJoiner joiners} are true */ - default BiConstraintStream forEachUniquePair(Class sourceClass, BiJoiner joiner1, - BiJoiner joiner2) { + default @NonNull BiConstraintStream forEachUniquePair(@NonNull Class sourceClass, + @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2) { return forEachUniquePair(sourceClass, new BiJoiner[] { joiner1, joiner2 }); } /** * As defined by {@link #forEachUniquePair(Class, BiJoiner)}. * - * @param sourceClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @return a stream that matches every unique combination of A and another A for which all the * {@link BiJoiner joiners} are true */ - default BiConstraintStream forEachUniquePair(Class sourceClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3) { + default @NonNull BiConstraintStream forEachUniquePair(@NonNull Class sourceClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, + @NonNull BiJoiner joiner3) { return forEachUniquePair(sourceClass, new BiJoiner[] { joiner1, joiner2, joiner3 }); } /** * As defined by {@link #forEachUniquePair(Class, BiJoiner)}. * - * @param sourceClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @return a stream that matches every unique combination of A and another A for which all the * {@link BiJoiner joiners} are true */ - default BiConstraintStream forEachUniquePair(Class sourceClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull BiConstraintStream forEachUniquePair(@NonNull Class sourceClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, + @NonNull BiJoiner joiner3, @NonNull BiJoiner joiner4) { return forEachUniquePair(sourceClass, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -185,13 +172,11 @@ default BiConstraintStream forEachUniquePair(Class sourceClass, BiJ * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link BiJoiner} parameters. * - * @param sourceClass never null - * @param joiners never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @return a stream that matches every unique combination of A and another A for which all the * {@link BiJoiner joiners} are true */ - BiConstraintStream forEachUniquePair(Class sourceClass, BiJoiner... joiners); + @NonNull BiConstraintStream forEachUniquePair(@NonNull Class sourceClass, @NonNull BiJoiner... joiners); // ************************************************************************ // from* (deprecated) @@ -227,15 +212,13 @@ default BiConstraintStream forEachUniquePair(Class sourceClass, BiJ * for which each genuine {@link PlanningVariable} (of the fromClass or a superclass thereof) is initialized. * This filtering will NOT automatically apply to genuine planning variables of subclass planning entities of the fromClass. * + * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @deprecated This method is deprecated in favor of {@link #forEach(Class)}, * which exhibits the same behavior for planning variables * which both allow and don't allow unassigned values. - * @param fromClass never null - * @param the type of the matched problem fact or {@link PlanningEntity planning entity} - * @return never null */ @Deprecated(forRemoval = true) - UniConstraintStream from(Class fromClass); + @NonNull UniConstraintStream from(@NonNull Class fromClass); /** * This method is deprecated. @@ -249,13 +232,12 @@ default BiConstraintStream forEachUniquePair(Class sourceClass, BiJ * As defined by {@link #from(Class)}, * but without any filtering of uninitialized {@link PlanningEntity planning entities}. * - * @deprecated Prefer {@link #forEachIncludingUnassigned(Class)}. - * @param fromClass never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} - * @return never null + * @deprecated Prefer {@link #forEachIncludingUnassigned(Class)}. */ @Deprecated(forRemoval = true) - UniConstraintStream fromUnfiltered(Class fromClass); + @NonNull + UniConstraintStream fromUnfiltered(@NonNull Class fromClass); /** * This method is deprecated. @@ -277,12 +259,11 @@ default BiConstraintStream forEachUniquePair(Class sourceClass, BiJ * @deprecated Prefer {@link #forEachUniquePair(Class)}, * which exhibits the same behavior for planning variables * which both allow and don't allow unassigned values. - * @param fromClass never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @return a stream that matches every unique combination of A and another A */ @Deprecated(forRemoval = true) - default BiConstraintStream fromUniquePair(Class fromClass) { + default @NonNull BiConstraintStream fromUniquePair(@NonNull Class fromClass) { return fromUniquePair(fromClass, new BiJoiner[0]); } @@ -309,13 +290,11 @@ default BiConstraintStream fromUniquePair(Class fromClass) { * @deprecated Prefer {@link #forEachUniquePair(Class, BiJoiner)}, * which exhibits the same behavior for planning variables * which both allow and don't allow unassigned values. - * @param fromClass never null - * @param joiner never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @return a stream that matches every unique combination of A and another A for which the {@link BiJoiner} is true */ @Deprecated(forRemoval = true) - default BiConstraintStream fromUniquePair(Class fromClass, BiJoiner joiner) { + default @NonNull BiConstraintStream fromUniquePair(@NonNull Class fromClass, @NonNull BiJoiner joiner) { return fromUniquePair(fromClass, new BiJoiner[] { joiner }); } @@ -331,15 +310,13 @@ default BiConstraintStream fromUniquePair(Class fromClass, BiJoiner * @deprecated Prefer {@link #forEachUniquePair(Class, BiJoiner, BiJoiner)}, * which exhibits the same behavior for planning variables * which both allow and don't allow unassigned values. - * @param fromClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @return a stream that matches every unique combination of A and another A for which all the * {@link BiJoiner joiners} are true */ @Deprecated(forRemoval = true) - default BiConstraintStream fromUniquePair(Class fromClass, BiJoiner joiner1, BiJoiner joiner2) { + default @NonNull BiConstraintStream fromUniquePair(@NonNull Class fromClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2) { return fromUniquePair(fromClass, new BiJoiner[] { joiner1, joiner2 }); } @@ -355,17 +332,14 @@ default BiConstraintStream fromUniquePair(Class fromClass, BiJoiner * @deprecated Prefer {@link #forEachUniquePair(Class, BiJoiner, BiJoiner, BiJoiner)}, * which exhibits the same behavior for planning variables * which both allow and don't allow unassigned values. - * @param fromClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null + * * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @return a stream that matches every unique combination of A and another A for which all the * {@link BiJoiner joiners} are true */ @Deprecated(forRemoval = true) - default BiConstraintStream fromUniquePair(Class fromClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3) { + default @NonNull BiConstraintStream fromUniquePair(@NonNull Class fromClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3) { return fromUniquePair(fromClass, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -378,21 +352,17 @@ default BiConstraintStream fromUniquePair(Class fromClass, BiJoiner *

    * As defined by {@link #fromUniquePair(Class, BiJoiner)}. * - * @deprecated Prefer {@link #forEachUniquePair(Class, BiJoiner, BiJoiner, BiJoiner, BiJoiner)}, - * which exhibits the same behavior for planning variables - * which both allow and don't allow unassigned values. - * @param fromClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @return a stream that matches every unique combination of A and another A for which all the * {@link BiJoiner joiners} are true + * @deprecated Prefer {@link #forEachUniquePair(Class, BiJoiner, BiJoiner, BiJoiner, BiJoiner)}, + * which exhibits the same behavior for planning variables + * which both allow and don't allow unassigned values. */ @Deprecated(forRemoval = true) - default BiConstraintStream fromUniquePair(Class fromClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull BiConstraintStream fromUniquePair(@NonNull Class fromClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, + @NonNull BiJoiner joiner3, @NonNull BiJoiner joiner4) { return fromUniquePair(fromClass, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -409,16 +379,15 @@ default BiConstraintStream fromUniquePair(Class fromClass, BiJoiner * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link BiJoiner} parameters. * - * @deprecated Prefer {@link #forEachUniquePair(Class, BiJoiner...)}, - * which exhibits the same behavior for planning variables - * which both allow and don't allow unassigned values. - * @param fromClass never null - * @param joiners never null * @param the type of the matched problem fact or {@link PlanningEntity planning entity} * @return a stream that matches every unique combination of A and another A for which all the * {@link BiJoiner joiners} are true + * @deprecated Prefer {@link #forEachUniquePair(Class, BiJoiner...)}, + * which exhibits the same behavior for planning variables + * which both allow and don't allow unassigned values. */ @Deprecated(forRemoval = true) - BiConstraintStream fromUniquePair(Class fromClass, BiJoiner... joiners); + @NonNull + BiConstraintStream fromUniquePair(@NonNull Class fromClass, @NonNull BiJoiner... joiners); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintMetaModel.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintMetaModel.java index b83bfb818d..d9a87e3f70 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintMetaModel.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintMetaModel.java @@ -5,6 +5,9 @@ import ai.timefold.solver.core.api.score.constraint.ConstraintRef; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Provides information about the known constraints. * Works in combination with {@link ConstraintProvider}. @@ -14,31 +17,33 @@ public interface ConstraintMetaModel { /** * Returns the constraint for the given reference. * - * @param constraintRef never null * @return null if such constraint does not exist */ - Constraint getConstraint(ConstraintRef constraintRef); + @Nullable + Constraint getConstraint(@NonNull ConstraintRef constraintRef); /** * Returns all constraints defined in the {@link ConstraintProvider}. * - * @return never null, iteration order is undefined + * @return iteration order is undefined */ + @NonNull Collection getConstraints(); /** * Returns all constraints from {@link #getConstraints()} that belong to the given group. * - * @param constraintGroup never null - * @return never null, iteration order is undefined + * @return iteration order is undefined */ - Collection getConstraintsPerGroup(String constraintGroup); + @NonNull + Collection getConstraintsPerGroup(@NonNull String constraintGroup); /** * Returns constraint groups with at least one constraint in it. * - * @return never null, iteration order is undefined + * @return iteration order is undefined */ + @NonNull Set getConstraintGroups(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintProvider.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintProvider.java index 95aacd5046..0b12378b81 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintProvider.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintProvider.java @@ -3,6 +3,8 @@ import ai.timefold.solver.core.api.domain.constraintweight.ConstraintWeight; import ai.timefold.solver.core.api.score.Score; +import org.jspecify.annotations.NonNull; + /** * Used by Constraint Streams' {@link Score} calculation. * An implementation must be stateless in order to facilitate building a single set of constraints @@ -14,11 +16,10 @@ public interface ConstraintProvider { * This method is called once to create the constraints. * To create a {@link Constraint}, start with {@link ConstraintFactory#forEach(Class)}. * - * @param constraintFactory never null * @return an array of all {@link Constraint constraints} that could apply. * The constraints with a zero {@link ConstraintWeight} for a particular problem * will be automatically disabled when scoring that problem, to improve performance. */ - Constraint[] defineConstraints(ConstraintFactory constraintFactory); + Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintStream.java index eb50643a0a..e4c9e525c9 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintStream.java @@ -17,6 +17,8 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintStream; import ai.timefold.solver.core.api.solver.SolutionManager; +import org.jspecify.annotations.NonNull; + /** * A constraint stream is a declaration on how to match {@link UniConstraintStream one}, {@link BiConstraintStream two} * or more objects. @@ -72,9 +74,8 @@ public interface ConstraintStream { /** * The {@link ConstraintFactory} that build this. - * - * @return never null */ + @NonNull ConstraintFactory getConstraintFactory(); // ************************************************************************ @@ -90,24 +91,20 @@ public interface ConstraintStream { * The {@link ConstraintRef#packageName() constraint package} defaults to the package of the {@link PlanningSolution} class. * * @deprecated Prefer {@link UniConstraintStream#penalize(Score)} and equivalent bi/tri/... overloads. - * @param constraintName never null, shows up in {@link ConstraintMatchTotal} during score justification - * @param constraintWeight never null - * @return never null + * @param constraintName shows up in {@link ConstraintMatchTotal} during score justification */ @Deprecated(forRemoval = true) - Constraint penalize(String constraintName, Score constraintWeight); + @NonNull + Constraint penalize(@NonNull String constraintName, @NonNull Score constraintWeight); /** * As defined by {@link #penalize(String, Score)}. * * @deprecated Prefer {@link UniConstraintStream#penalize(Score)} and equivalent bi/tri/... overloads. - * @param constraintPackage never null - * @param constraintName never null - * @param constraintWeight never null - * @return never null */ @Deprecated(forRemoval = true) - Constraint penalize(String constraintPackage, String constraintName, Score constraintWeight); + @NonNull + Constraint penalize(@NonNull String constraintPackage, @NonNull String constraintName, @NonNull Score constraintWeight); /** * Negatively impact the {@link Score}: subtract the {@link ConstraintWeight} for each match. @@ -119,23 +116,21 @@ public interface ConstraintStream { * The {@link ConstraintRef#packageName() constraint package} defaults to * {@link ConstraintConfiguration#constraintPackage()}. * - * @param constraintName never null, shows up in {@link ConstraintMatchTotal} during score justification - * @return never null + * @param constraintName shows up in {@link ConstraintMatchTotal} during score justification * @deprecated Prefer {@code penalize()} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true) - Constraint penalizeConfigurable(String constraintName); + @NonNull + Constraint penalizeConfigurable(@NonNull String constraintName); /** * As defined by {@link #penalizeConfigurable(String)}. * - * @param constraintPackage never null - * @param constraintName never null - * @return never null * @deprecated Prefer {@code penalize()} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true) - Constraint penalizeConfigurable(String constraintPackage, String constraintName); + @NonNull + Constraint penalizeConfigurable(@NonNull String constraintPackage, @NonNull String constraintName); /** * Positively impact the {@link Score}: add the constraintWeight for each match. @@ -146,24 +141,20 @@ public interface ConstraintStream { * The {@link ConstraintRef#packageName() constraint package} defaults to the package of the {@link PlanningSolution} class. * * @deprecated Prefer {@link UniConstraintStream#reward(Score)} and equivalent bi/tri/... overloads. - * @param constraintName never null, shows up in {@link ConstraintMatchTotal} during score justification - * @param constraintWeight never null - * @return never null + * @param constraintName shows up in {@link ConstraintMatchTotal} during score justification */ @Deprecated(forRemoval = true) - Constraint reward(String constraintName, Score constraintWeight); + @NonNull + Constraint reward(@NonNull String constraintName, @NonNull Score constraintWeight); /** * As defined by {@link #reward(String, Score)}. * * @deprecated Prefer {@link UniConstraintStream#reward(Score)} and equivalent bi/tri/... overloads. - * @param constraintPackage never null - * @param constraintName never null - * @param constraintWeight never null - * @return never null */ @Deprecated(forRemoval = true) - Constraint reward(String constraintPackage, String constraintName, Score constraintWeight); + @NonNull + Constraint reward(@NonNull String constraintPackage, @NonNull String constraintName, @NonNull Score constraintWeight); /** * Positively impact the {@link Score}: add the {@link ConstraintWeight} for each match. @@ -175,23 +166,21 @@ public interface ConstraintStream { * The {@link ConstraintRef#packageName() constraint package} defaults to * {@link ConstraintConfiguration#constraintPackage()}. * - * @param constraintName never null, shows up in {@link ConstraintMatchTotal} during score justification - * @return never null + * @param constraintName shows up in {@link ConstraintMatchTotal} during score justification * @deprecated Prefer {@code reward()} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true) - Constraint rewardConfigurable(String constraintName); + @NonNull + Constraint rewardConfigurable(@NonNull String constraintName); /** * As defined by {@link #rewardConfigurable(String)}. * - * @param constraintPackage never null - * @param constraintName never null - * @return never null * @deprecated Prefer {@code reward()} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true) - Constraint rewardConfigurable(String constraintPackage, String constraintName); + @NonNull + Constraint rewardConfigurable(@NonNull String constraintPackage, @NonNull String constraintName); /** * Positively or negatively impact the {@link Score} by the constraintWeight for each match. @@ -202,23 +191,19 @@ public interface ConstraintStream { * The {@link ConstraintRef#packageName() constraint package} defaults to the package of the {@link PlanningSolution} class. * * @deprecated Prefer {@link UniConstraintStream#impact(Score)} and equivalent bi/tri/... overloads. - * @param constraintName never null, shows up in {@link ConstraintMatchTotal} during score justification - * @param constraintWeight never null - * @return never null + * @param constraintName shows up in {@link ConstraintMatchTotal} during score justification */ @Deprecated(forRemoval = true) - Constraint impact(String constraintName, Score constraintWeight); + @NonNull + Constraint impact(@NonNull String constraintName, @NonNull Score constraintWeight); /** * As defined by {@link #impact(String, Score)}. * * @deprecated Prefer {@link UniConstraintStream#impact(Score)} and equivalent bi/tri/... overloads. - * @param constraintPackage never null - * @param constraintName never null - * @param constraintWeight never null - * @return never null */ @Deprecated(forRemoval = true) - Constraint impact(String constraintPackage, String constraintName, Score constraintWeight); + @NonNull + Constraint impact(@NonNull String constraintPackage, @NonNull String constraintName, @NonNull Score constraintWeight); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/DefaultConstraintJustification.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/DefaultConstraintJustification.java index dcbd16f4c8..c22d9f90da 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/DefaultConstraintJustification.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/DefaultConstraintJustification.java @@ -8,6 +8,9 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.api.score.constraint.ConstraintMatch; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Default implementation of {@link ConstraintJustification}, returned by {@link ConstraintMatch#getJustification()} * unless the user defined a custom justification mapping. @@ -15,27 +18,28 @@ public final class DefaultConstraintJustification implements ConstraintJustification, Comparable { - public static DefaultConstraintJustification of(Score impact, Object fact) { + public static @NonNull DefaultConstraintJustification of(Score impact, Object fact) { return of(impact, Collections.singletonList(fact)); } - public static DefaultConstraintJustification of(Score impact, Object factA, Object factB) { + public static @NonNull DefaultConstraintJustification of(Score impact, Object factA, Object factB) { return of(impact, Arrays.asList(factA, factB)); } - public static DefaultConstraintJustification of(Score impact, Object factA, Object factB, Object factC) { + public static @NonNull DefaultConstraintJustification of(Score impact, Object factA, Object factB, Object factC) { return of(impact, Arrays.asList(factA, factB, factC)); } - public static DefaultConstraintJustification of(Score impact, Object factA, Object factB, Object factC, Object factD) { + public static @NonNull DefaultConstraintJustification of(Score impact, Object factA, Object factB, Object factC, + Object factD) { return of(impact, Arrays.asList(factA, factB, factC, factD)); } - public static DefaultConstraintJustification of(Score impact, Object... facts) { + public static @NonNull DefaultConstraintJustification of(Score impact, Object... facts) { return of(impact, Arrays.asList(facts)); } - public static DefaultConstraintJustification of(Score impact, List facts) { + public static @NonNull DefaultConstraintJustification of(Score impact, List facts) { return new DefaultConstraintJustification(impact, facts); } @@ -51,11 +55,7 @@ public > Score_ getImpact() { return (Score_) impact; } - /** - * - * @return never null; may contain null - */ - public List getFacts() { + public @NonNull List<@Nullable Object> getFacts() { return facts; } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/Joiners.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/Joiners.java index 71e5ea8ff5..a2a2f11d86 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/Joiners.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/Joiners.java @@ -26,6 +26,8 @@ import ai.timefold.solver.core.impl.score.stream.common.tri.FilteringTriJoiner; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + /** * Creates an {@link BiJoiner}, {@link TriJoiner}, ... instance * for use in {@link UniConstraintStream#join(Class, BiJoiner)}, ... @@ -43,9 +45,8 @@ public final class Joiners { * As defined by {@link #equal(Function)} with {@link Function#identity()} as the argument. * * @param the type of both objects - * @return never null */ - public static BiJoiner equal() { + public static @NonNull BiJoiner equal() { return equal(ConstantLambdaUtils.identity()); } @@ -55,9 +56,8 @@ public static BiJoiner equal() { * @param the type of both objects * @param the type of the property to compare * @param mapping mapping function to apply to both A and B - * @return never null */ - public static BiJoiner equal(Function mapping) { + public static @NonNull BiJoiner equal(Function mapping) { return equal(mapping, mapping); } @@ -73,9 +73,8 @@ public static BiJoiner equal(Function mapping * @param the type of the property to compare * @param leftMapping mapping function to apply to A * @param rightMapping mapping function to apply to B - * @return never null */ - public static BiJoiner equal(Function leftMapping, + public static @NonNull BiJoiner equal(Function leftMapping, Function rightMapping) { return new DefaultBiJoiner<>(leftMapping, JoinerType.EQUAL, rightMapping); } @@ -86,9 +85,9 @@ public static BiJoiner equal(Function left * @param mapping mapping function to apply * @param the type of both objects * @param the type of the property to compare - * @return never null */ - public static > BiJoiner lessThan(Function mapping) { + public static > @NonNull BiJoiner + lessThan(Function mapping) { return lessThan(mapping, mapping); } @@ -105,9 +104,8 @@ public static > BiJoiner lessTh * @param the type of object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > BiJoiner lessThan( + public static > @NonNull BiJoiner lessThan( Function leftMapping, Function rightMapping) { return new DefaultBiJoiner<>(leftMapping, JoinerType.LESS_THAN, rightMapping); } @@ -118,9 +116,8 @@ public static > BiJoiner les * @param mapping mapping function to apply * @param the type of both objects * @param the type of the property to compare - * @return never null */ - public static > BiJoiner lessThanOrEqual( + public static > @NonNull BiJoiner lessThanOrEqual( Function mapping) { return lessThanOrEqual(mapping, mapping); } @@ -139,9 +136,8 @@ public static > BiJoiner lessTh * @param the type of object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > BiJoiner lessThanOrEqual( + public static > @NonNull BiJoiner lessThanOrEqual( Function leftMapping, Function rightMapping) { return new DefaultBiJoiner<>(leftMapping, JoinerType.LESS_THAN_OR_EQUAL, rightMapping); } @@ -152,9 +148,8 @@ public static > BiJoiner les * @param mapping mapping function to apply * @param the type of both objects * @param the type of the property to compare - * @return never null */ - public static > BiJoiner greaterThan( + public static > @NonNull BiJoiner greaterThan( Function mapping) { return greaterThan(mapping, mapping); } @@ -172,9 +167,8 @@ public static > BiJoiner greate * @param the type of object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > BiJoiner greaterThan( + public static > @NonNull BiJoiner greaterThan( Function leftMapping, Function rightMapping) { return new DefaultBiJoiner<>(leftMapping, JoinerType.GREATER_THAN, rightMapping); } @@ -185,9 +179,8 @@ public static > BiJoiner gre * @param mapping mapping function to apply * @param the type of both objects * @param the type of the property to compare - * @return never null */ - public static > BiJoiner greaterThanOrEqual( + public static > @NonNull BiJoiner greaterThanOrEqual( Function mapping) { return greaterThanOrEqual(mapping, mapping); } @@ -206,9 +199,8 @@ public static > BiJoiner greate * @param the type of object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > BiJoiner greaterThanOrEqual( + public static > @NonNull BiJoiner greaterThanOrEqual( Function leftMapping, Function rightMapping) { return new DefaultBiJoiner<>(leftMapping, JoinerType.GREATER_THAN_OR_EQUAL, rightMapping); } @@ -220,12 +212,11 @@ public static > BiJoiner gre * with filter being {@code age == 20}, * this joiner will produce pairs {@code (Ann, Ann), (Ann, Eric), (Eric, Ann), (Eric, Eric)}. * - * @param filter never null, filter to apply + * @param filter filter to apply * @param type of the first fact in the tuple * @param type of the second fact in the tuple - * @return never null */ - public static BiJoiner filtering(BiPredicate filter) { + public static @NonNull BiJoiner filtering(@NonNull BiPredicate filter) { return new FilteringBiJoiner<>(filter); } @@ -243,9 +234,8 @@ public static BiJoiner filtering(BiPredicate filter) { * @param endMapping maps the argument to the end point of its interval (exclusive) * @param the type of both the first and second argument * @param the type used to define the interval, comparable - * @return never null */ - public static > BiJoiner overlapping( + public static > @NonNull BiJoiner overlapping( Function startMapping, Function endMapping) { return overlapping(startMapping, endMapping, startMapping, endMapping); } @@ -260,9 +250,8 @@ public static > BiJoiner overla * @param the type of the first argument * @param the type of the second argument * @param the type used to define the interval, comparable - * @return never null */ - public static > BiJoiner overlapping( + public static > @NonNull BiJoiner overlapping( Function leftStartMapping, Function leftEndMapping, Function rightStartMapping, Function rightEndMapping) { return Joiners.lessThan(leftStartMapping, rightEndMapping) @@ -282,9 +271,8 @@ public static > BiJoiner ove * @param the type of the property to compare * @param leftMapping mapping function to apply to (A,B) * @param rightMapping mapping function to apply to C - * @return never null */ - public static TriJoiner equal(BiFunction leftMapping, + public static @NonNull TriJoiner equal(BiFunction leftMapping, Function rightMapping) { return new DefaultTriJoiner<>(leftMapping, JoinerType.EQUAL, rightMapping); } @@ -298,9 +286,8 @@ public static TriJoiner equal(BiFunction the type of the second object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > TriJoiner lessThan( + public static > @NonNull TriJoiner lessThan( BiFunction leftMapping, Function rightMapping) { return new DefaultTriJoiner<>(leftMapping, JoinerType.LESS_THAN, rightMapping); } @@ -314,9 +301,8 @@ public static > TriJoiner the type of the second object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > TriJoiner lessThanOrEqual( + public static > @NonNull TriJoiner lessThanOrEqual( BiFunction leftMapping, Function rightMapping) { return new DefaultTriJoiner<>(leftMapping, JoinerType.LESS_THAN_OR_EQUAL, rightMapping); } @@ -330,9 +316,8 @@ public static > TriJoiner the type of the second object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > TriJoiner greaterThan( + public static > @NonNull TriJoiner greaterThan( BiFunction leftMapping, Function rightMapping) { return new DefaultTriJoiner<>(leftMapping, JoinerType.GREATER_THAN, rightMapping); } @@ -346,9 +331,8 @@ public static > TriJoiner the type of the second object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > TriJoiner greaterThanOrEqual( + public static > @NonNull TriJoiner greaterThanOrEqual( BiFunction leftMapping, Function rightMapping) { return new DefaultTriJoiner<>(leftMapping, JoinerType.GREATER_THAN_OR_EQUAL, rightMapping); } @@ -356,13 +340,12 @@ public static > TriJoiner type of the first fact in the tuple * @param type of the second fact in the tuple * @param type of the third fact in the tuple - * @return never null */ - public static TriJoiner filtering(TriPredicate filter) { + public static @NonNull TriJoiner filtering(@NonNull TriPredicate filter) { return new FilteringTriJoiner<>(filter); } @@ -377,9 +360,8 @@ public static TriJoiner filtering(TriPredicate filte * @param the type of the second argument * @param the type of the third argument * @param the type used to define the interval, comparable - * @return never null */ - public static > TriJoiner overlapping( + public static > @NonNull TriJoiner overlapping( BiFunction leftStartMapping, BiFunction leftEndMapping, Function rightStartMapping, Function rightEndMapping) { return Joiners.lessThan(leftStartMapping, rightEndMapping) @@ -400,9 +382,8 @@ public static > TriJoiner the type of the property to compare * @param leftMapping mapping function to apply to (A, B, C) * @param rightMapping mapping function to apply to D - * @return never null */ - public static QuadJoiner equal( + public static @NonNull QuadJoiner equal( TriFunction leftMapping, Function rightMapping) { return new DefaultQuadJoiner<>(leftMapping, JoinerType.EQUAL, rightMapping); } @@ -417,9 +398,8 @@ public static QuadJoiner equal( * @param the type of the third object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > QuadJoiner lessThan( + public static > @NonNull QuadJoiner lessThan( TriFunction leftMapping, Function rightMapping) { return new DefaultQuadJoiner<>(leftMapping, JoinerType.LESS_THAN, rightMapping); } @@ -434,9 +414,8 @@ public static > QuadJoiner the type of the third object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > QuadJoiner lessThanOrEqual( + public static > @NonNull QuadJoiner lessThanOrEqual( TriFunction leftMapping, Function rightMapping) { return new DefaultQuadJoiner<>(leftMapping, JoinerType.LESS_THAN_OR_EQUAL, rightMapping); } @@ -451,9 +430,8 @@ public static > QuadJoiner the type of the third object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > QuadJoiner greaterThan( + public static > @NonNull QuadJoiner greaterThan( TriFunction leftMapping, Function rightMapping) { return new DefaultQuadJoiner<>(leftMapping, JoinerType.GREATER_THAN, rightMapping); } @@ -468,9 +446,8 @@ public static > QuadJoiner the type of the third object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > QuadJoiner greaterThanOrEqual( + public static > @NonNull QuadJoiner greaterThanOrEqual( TriFunction leftMapping, Function rightMapping) { return new DefaultQuadJoiner<>(leftMapping, JoinerType.GREATER_THAN_OR_EQUAL, rightMapping); } @@ -478,14 +455,13 @@ public static > QuadJoiner type of the first fact in the tuple * @param type of the second fact in the tuple * @param type of the third fact in the tuple * @param type of the fourth fact in the tuple - * @return never null */ - public static QuadJoiner filtering(QuadPredicate filter) { + public static @NonNull QuadJoiner filtering(@NonNull QuadPredicate filter) { return new FilteringQuadJoiner<>(filter); } @@ -501,9 +477,8 @@ public static QuadJoiner filtering(QuadPredicate the type of the third argument * @param the type of the fourth argument * @param the type used to define the interval, comparable - * @return never null */ - public static > QuadJoiner overlapping( + public static > @NonNull QuadJoiner overlapping( TriFunction leftStartMapping, TriFunction leftEndMapping, Function rightStartMapping, Function rightEndMapping) { return Joiners.lessThan(leftStartMapping, rightEndMapping) @@ -525,9 +500,8 @@ public static > QuadJoiner the type of the property to compare * @param leftMapping mapping function to apply to (A,B,C,D) * @param rightMapping mapping function to apply to E - * @return never null */ - public static PentaJoiner equal( + public static @NonNull PentaJoiner equal( QuadFunction leftMapping, Function rightMapping) { return new DefaultPentaJoiner<>(leftMapping, JoinerType.EQUAL, rightMapping); } @@ -543,9 +517,8 @@ public static PentaJoiner equal( * @param the type of the fourth object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > PentaJoiner lessThan( + public static > @NonNull PentaJoiner lessThan( QuadFunction leftMapping, Function rightMapping) { return new DefaultPentaJoiner<>(leftMapping, JoinerType.LESS_THAN, rightMapping); } @@ -561,9 +534,8 @@ public static > PentaJoin * @param the type of the fourth object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > PentaJoiner lessThanOrEqual( + public static > @NonNull PentaJoiner lessThanOrEqual( QuadFunction leftMapping, Function rightMapping) { return new DefaultPentaJoiner<>(leftMapping, JoinerType.LESS_THAN_OR_EQUAL, rightMapping); } @@ -579,9 +551,8 @@ public static > PentaJoin * @param the type of the fourth object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > PentaJoiner greaterThan( + public static > @NonNull PentaJoiner greaterThan( QuadFunction leftMapping, Function rightMapping) { return new DefaultPentaJoiner<>(leftMapping, JoinerType.GREATER_THAN, rightMapping); } @@ -597,25 +568,24 @@ public static > PentaJoin * @param the type of the fourth object on the left * @param the type of object on the right * @param the type of the property to compare - * @return never null */ - public static > PentaJoiner greaterThanOrEqual( - QuadFunction leftMapping, Function rightMapping) { + public static > @NonNull PentaJoiner + greaterThanOrEqual( + QuadFunction leftMapping, Function rightMapping) { return new DefaultPentaJoiner<>(leftMapping, JoinerType.GREATER_THAN_OR_EQUAL, rightMapping); } /** * As defined by {@link #filtering(BiPredicate)}. * - * @param filter never null, filter to apply + * @param filter filter to apply * @param the type of the first object on the left * @param the type of the second object on the left * @param the type of the third object on the left * @param the type of the fourth object on the left * @param the type of object on the right - * @return never null */ - public static PentaJoiner filtering(PentaPredicate filter) { + public static @NonNull PentaJoiner filtering(@NonNull PentaPredicate filter) { return new FilteringPentaJoiner<>(filter); } @@ -632,9 +602,8 @@ public static PentaJoiner filtering(PentaPredicat * @param the type of the fourth argument * @param the type of the fifth argument * @param the type used to define the interval, comparable - * @return never null */ - public static > PentaJoiner overlapping( + public static > @NonNull PentaJoiner overlapping( QuadFunction leftStartMapping, QuadFunction leftEndMapping, Function rightStartMapping, Function rightEndMapping) { return Joiners.lessThan(leftStartMapping, rightEndMapping) diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiConstraintBuilder.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiConstraintBuilder.java index cc10d41d76..29d352124f 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiConstraintBuilder.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiConstraintBuilder.java @@ -12,6 +12,8 @@ import ai.timefold.solver.core.api.score.stream.ConstraintBuilder; import ai.timefold.solver.core.api.score.stream.ConstraintJustification; +import org.jspecify.annotations.NonNull; + /** * Used to build a {@link Constraint} out of a {@link BiConstraintStream}, applying optional configuration. * To build the constraint, use one of the terminal operations, such as {@link #asConstraint(String)}. @@ -29,20 +31,20 @@ public interface BiConstraintBuilder> extends * Sets a custom function to apply on a constraint match to justify it. * * @see ConstraintMatch - * @param justificationMapping never null * @return this */ + @NonNull BiConstraintBuilder justifyWith( - TriFunction justificationMapping); + @NonNull TriFunction justificationMapping); /** * Sets a custom function to mark any object returned by it as responsible for causing the constraint to match. * Each object in the collection returned by this function will become an {@link Indictment} * and be available as a key in {@link ScoreExplanation#getIndictmentMap()}. * - * @param indictedObjectsMapping never null * @return this */ - BiConstraintBuilder indictWith(BiFunction> indictedObjectsMapping); + @NonNull + BiConstraintBuilder indictWith(@NonNull BiFunction> indictedObjectsMapping); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiConstraintCollector.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiConstraintCollector.java index 14e0cfbee5..d2f554e014 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiConstraintCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiConstraintCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.ConstraintStream; import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; +import org.jspecify.annotations.NonNull; + /** * As described by {@link UniConstraintCollector}, only for {@link BiConstraintStream}. * @@ -24,9 +26,8 @@ public interface BiConstraintCollector { /** * A lambda that creates the result container, one for each group key combination. - * - * @return never null */ + @NonNull Supplier supplier(); /** @@ -34,15 +35,15 @@ public interface BiConstraintCollector { * accumulates it in the result container * and returns an undo operation for that accumulation. * - * @return never null, the undo operation. This lambda is called when the facts no longer matches. + * @return the undo operation. This lambda is called when the facts no longer matches. */ + @NonNull TriFunction accumulator(); /** * A lambda that converts the result container into the result. - * - * @return never null */ + @NonNull Function finisher(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiConstraintStream.java index b8b28a4180..f72e84d96a 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiConstraintStream.java @@ -35,6 +35,8 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintStream; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + /** * A {@link ConstraintStream} that matches two facts. * @@ -55,11 +57,9 @@ public interface BiConstraintStream extends ConstraintStream { * Important: This is slower and less scalable than {@link UniConstraintStream#join(UniConstraintStream, BiJoiner)} * with a proper {@link BiJoiner} predicate (such as {@link Joiners#equal(Function, Function)}, * because the latter applies hashing and/or indexing, so it doesn't create every combination just to filter it out. - * - * @param predicate never null - * @return never null */ - BiConstraintStream filter(BiPredicate predicate); + @NonNull + BiConstraintStream filter(@NonNull BiPredicate predicate); // ************************************************************************ // Join @@ -73,11 +73,10 @@ public interface BiConstraintStream extends ConstraintStream { * because it doesn't apply hashing and/or indexing on the properties, * so it creates and checks every combination of [A, B] and C. * - * @param otherStream never null * @param the type of the third matched fact - * @return never null, a stream that matches every combination of [A, B] and C + * @return a stream that matches every combination of [A, B] and C */ - default TriConstraintStream join(UniConstraintStream otherStream) { + default @NonNull TriConstraintStream join(@NonNull UniConstraintStream otherStream) { return join(otherStream, new TriJoiner[0]); } @@ -90,13 +89,12 @@ default TriConstraintStream join(UniConstraintStream otherStream * because it applies hashing and/or indexing on the properties, * so it doesn't create nor checks every combination of [A, B] and C. * - * @param otherStream never null - * @param joiner never null * @param the type of the third matched fact - * @return never null, a stream that matches every combination of [A, B] and C for which the {@link TriFunction} is + * @return a stream that matches every combination of [A, B] and C for which the {@link TriFunction} is * true */ - default TriConstraintStream join(UniConstraintStream otherStream, TriJoiner joiner) { + default @NonNull TriConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner joiner) { return join(otherStream, new TriJoiner[] { joiner }); } @@ -104,15 +102,13 @@ default TriConstraintStream join(UniConstraintStream otherStream * As defined by {@link #join(Class, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the third matched fact - * @return never null, a stream that matches every combination of [A, B] and C for which all the + * @return a stream that matches every combination of [A, B] and C for which all the * {@link TriJoiner joiners} are true */ - default TriConstraintStream join(UniConstraintStream otherStream, TriJoiner joiner1, - TriJoiner joiner2) { + default @NonNull TriConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2) { return join(otherStream, new TriJoiner[] { joiner1, joiner2 }); } @@ -120,16 +116,13 @@ default TriConstraintStream join(UniConstraintStream otherStream * As defined by {@link #join(Class, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the third matched fact - * @return never null, a stream that matches every combination of [A, B] and C for which all the + * @return a stream that matches every combination of [A, B] and C for which all the * {@link TriJoiner joiners} are true */ - default TriConstraintStream join(UniConstraintStream otherStream, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3) { + default @NonNull TriConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3) { return join(otherStream, new TriJoiner[] { joiner1, joiner2, joiner3 }); } @@ -137,17 +130,13 @@ default TriConstraintStream join(UniConstraintStream otherStream * As defined by {@link #join(Class, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the third matched fact - * @return never null, a stream that matches every combination of [A, B] and C for which all the + * @return a stream that matches every combination of [A, B] and C for which all the * {@link TriJoiner joiners} are true */ - default TriConstraintStream join(UniConstraintStream otherStream, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3, TriJoiner joiner4) { + default @NonNull TriConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner joiner1, @NonNull TriJoiner joiner2, + @NonNull TriJoiner joiner3, @NonNull TriJoiner joiner4) { return join(otherStream, new TriJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -159,13 +148,12 @@ default TriConstraintStream join(UniConstraintStream otherStream * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link BiJoiner} parameters. * - * @param otherStream never null - * @param joiners never null * @param the type of the third matched fact - * @return never null, a stream that matches every combination of [A, B] and C for which all the + * @return a stream that matches every combination of [A, B] and C for which all the * {@link TriJoiner joiners} are true */ - TriConstraintStream join(UniConstraintStream otherStream, TriJoiner... joiners); + @NonNull TriConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner... joiners); /** * Create a new {@link TriConstraintStream} for every combination of [A, B] and C. @@ -182,11 +170,10 @@ default TriConstraintStream join(UniConstraintStream otherStream *

    * This method is syntactic sugar for {@link #join(UniConstraintStream)}. * - * @param otherClass never null * @param the type of the third matched fact - * @return never null, a stream that matches every combination of [A, B] and C + * @return a stream that matches every combination of [A, B] and C */ - default TriConstraintStream join(Class otherClass) { + default @NonNull TriConstraintStream join(@NonNull Class otherClass) { return join(otherClass, new TriJoiner[0]); } @@ -207,13 +194,11 @@ default TriConstraintStream join(Class otherClass) { *

    * This method has overloaded methods with multiple {@link TriJoiner} parameters. * - * @param otherClass never null - * @param joiner never null * @param the type of the third matched fact - * @return never null, a stream that matches every combination of [A, B] and C for which the {@link TriJoiner} is + * @return a stream that matches every combination of [A, B] and C for which the {@link TriJoiner} is * true */ - default TriConstraintStream join(Class otherClass, TriJoiner joiner) { + default @NonNull TriConstraintStream join(@NonNull Class otherClass, @NonNull TriJoiner joiner) { return join(otherClass, new TriJoiner[] { joiner }); } @@ -221,15 +206,13 @@ default TriConstraintStream join(Class otherClass, TriJoiner the type of the third matched fact - * @return never null, a stream that matches every combination of [A, B] and C for which all the + * @return a stream that matches every combination of [A, B] and C for which all the * {@link TriJoiner joiners} are true */ - default TriConstraintStream join(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2) { + default @NonNull TriConstraintStream join(@NonNull Class otherClass, @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2) { return join(otherClass, new TriJoiner[] { joiner1, joiner2 }); } @@ -237,16 +220,12 @@ default TriConstraintStream join(Class otherClass, TriJoiner the type of the third matched fact - * @return never null, a stream that matches every combination of [A, B] and C for which all the + * @return a stream that matches every combination of [A, B] and C for which all the * {@link TriJoiner joiners} are true */ - default TriConstraintStream join(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3) { + default @NonNull TriConstraintStream join(@NonNull Class otherClass, @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3) { return join(otherClass, new TriJoiner[] { joiner1, joiner2, joiner3 }); } @@ -254,17 +233,12 @@ default TriConstraintStream join(Class otherClass, TriJoiner the type of the third matched fact - * @return never null, a stream that matches every combination of [A, B] and C for which all the + * @return a stream that matches every combination of [A, B] and C for which all the * {@link TriJoiner joiners} are true */ - default TriConstraintStream join(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3, TriJoiner joiner4) { + default @NonNull TriConstraintStream join(@NonNull Class otherClass, @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3, @NonNull TriJoiner joiner4) { return join(otherClass, new TriJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -276,13 +250,11 @@ default TriConstraintStream join(Class otherClass, TriJoiner the type of the third matched fact - * @return never null, a stream that matches every combination of [A, B] and C for which all the + * @return a stream that matches every combination of [A, B] and C for which all the * {@link TriJoiner joiners} are true */ - TriConstraintStream join(Class otherClass, TriJoiner... joiners); + @NonNull TriConstraintStream join(@NonNull Class otherClass, @NonNull TriJoiner... joiners); // ************************************************************************ // If (not) exists @@ -299,13 +271,12 @@ default TriConstraintStream join(Class otherClass, TriJoiner the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner} + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner} * is true */ - default BiConstraintStream ifExists(Class otherClass, TriJoiner joiner) { + default @NonNull BiConstraintStream ifExists(@NonNull Class otherClass, @NonNull TriJoiner joiner) { return ifExists(otherClass, new TriJoiner[] { joiner }); } @@ -313,15 +284,12 @@ default BiConstraintStream ifExists(Class otherClass, TriJoiner the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s * are true */ - default BiConstraintStream ifExists(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2) { + default @NonNull BiConstraintStream ifExists(@NonNull Class otherClass, @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2) { return ifExists(otherClass, new TriJoiner[] { joiner1, joiner2 }); } @@ -329,16 +297,12 @@ default BiConstraintStream ifExists(Class otherClass, TriJoiner the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s * are true */ - default BiConstraintStream ifExists(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3) { + default @NonNull BiConstraintStream ifExists(@NonNull Class otherClass, @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3) { return ifExists(otherClass, new TriJoiner[] { joiner1, joiner2, joiner3 }); } @@ -346,17 +310,13 @@ default BiConstraintStream ifExists(Class otherClass, TriJoiner the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s * are true */ - default BiConstraintStream ifExists(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3, TriJoiner joiner4) { + default @NonNull BiConstraintStream ifExists(@NonNull Class otherClass, @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3, @NonNull TriJoiner joiner4) { return ifExists(otherClass, new TriJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -368,13 +328,11 @@ default BiConstraintStream ifExists(Class otherClass, TriJoiner the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s * are true */ - BiConstraintStream ifExists(Class otherClass, TriJoiner... joiners); + @NonNull BiConstraintStream ifExists(@NonNull Class otherClass, @NonNull TriJoiner... joiners); /** * Create a new {@link BiConstraintStream} for every pair of A and B where C exists for which the {@link TriJoiner} @@ -382,13 +340,12 @@ default BiConstraintStream ifExists(Class otherClass, TriJoiner * This method has overloaded methods with multiple {@link TriJoiner} parameters. * - * @param otherStream never null - * @param joiner never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner} + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner} * is true */ - default BiConstraintStream ifExists(UniConstraintStream otherStream, TriJoiner joiner) { + default @NonNull BiConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner joiner) { return ifExists(otherStream, new TriJoiner[] { joiner }); } @@ -396,15 +353,13 @@ default BiConstraintStream ifExists(UniConstraintStream otherStream * As defined by {@link #ifExists(UniConstraintStream, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s * are true */ - default BiConstraintStream ifExists(UniConstraintStream otherStream, TriJoiner joiner1, - TriJoiner joiner2) { + default @NonNull BiConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2) { return ifExists(otherStream, new TriJoiner[] { joiner1, joiner2 }); } @@ -412,16 +367,13 @@ default BiConstraintStream ifExists(UniConstraintStream otherStream * As defined by {@link #ifExists(UniConstraintStream, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s * are true */ - default BiConstraintStream ifExists(UniConstraintStream otherStream, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3) { + default @NonNull BiConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner joiner1, @NonNull TriJoiner joiner2, + @NonNull TriJoiner joiner3) { return ifExists(otherStream, new TriJoiner[] { joiner1, joiner2, joiner3 }); } @@ -429,17 +381,13 @@ default BiConstraintStream ifExists(UniConstraintStream otherStream * As defined by {@link #ifExists(UniConstraintStream, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s * are true */ - default BiConstraintStream ifExists(UniConstraintStream otherStream, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3, TriJoiner joiner4) { + default @NonNull BiConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3, @NonNull TriJoiner joiner4) { return ifExists(otherStream, new TriJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -451,13 +399,12 @@ default BiConstraintStream ifExists(UniConstraintStream otherStream * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link TriJoiner} parameters. * - * @param otherStream never null - * @param joiners never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s * are true */ - BiConstraintStream ifExists(UniConstraintStream otherStream, TriJoiner... joiners); + @NonNull BiConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner... joiners); /** * Create a new {@link BiConstraintStream} for every pair of A and B where C exists for which the {@link TriJoiner} @@ -468,13 +415,12 @@ default BiConstraintStream ifExists(UniConstraintStream otherStream *

    * This method has overloaded methods with multiple {@link TriJoiner} parameters. * - * @param otherClass never null - * @param joiner never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner} + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner} * is true */ - default BiConstraintStream ifExistsIncludingUnassigned(Class otherClass, TriJoiner joiner) { + default @NonNull BiConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull TriJoiner joiner) { return ifExistsIncludingUnassigned(otherClass, new TriJoiner[] { joiner }); } @@ -482,15 +428,12 @@ default BiConstraintStream ifExistsIncludingUnassigned(Class otherC * As defined by {@link #ifExistsIncludingUnassigned(Class, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s * are true */ - default BiConstraintStream ifExistsIncludingUnassigned(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2) { + default @NonNull BiConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull TriJoiner joiner1, @NonNull TriJoiner joiner2) { return ifExistsIncludingUnassigned(otherClass, new TriJoiner[] { joiner1, joiner2 }); } @@ -498,16 +441,12 @@ default BiConstraintStream ifExistsIncludingUnassigned(Class otherC * As defined by {@link #ifExistsIncludingNullVars(Class, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s * are true */ - default BiConstraintStream ifExistsIncludingUnassigned(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3) { + default @NonNull BiConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull TriJoiner joiner1, @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3) { return ifExistsIncludingUnassigned(otherClass, new TriJoiner[] { joiner1, joiner2, joiner3 }); } @@ -515,17 +454,13 @@ default BiConstraintStream ifExistsIncludingUnassigned(Class otherC * As defined by {@link #ifExistsIncludingUnassigned(Class, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s * are true */ - default BiConstraintStream ifExistsIncludingUnassigned(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3, TriJoiner joiner4) { + default @NonNull BiConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull TriJoiner joiner1, @NonNull TriJoiner joiner2, + @NonNull TriJoiner joiner3, @NonNull TriJoiner joiner4) { return ifExistsIncludingUnassigned(otherClass, new TriJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -537,13 +472,12 @@ default BiConstraintStream ifExistsIncludingUnassigned(Class otherC * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link TriJoiner} parameters. * - * @param otherClass never null - * @param joiners never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s + * @return a stream that matches every pair of A and B where C exists for which the {@link TriJoiner}s * are true */ - BiConstraintStream ifExistsIncludingUnassigned(Class otherClass, TriJoiner... joiners); + @NonNull BiConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull TriJoiner... joiners); /** * Create a new {@link BiConstraintStream} for every pair of A and B where C does not exist for which the @@ -556,13 +490,12 @@ default BiConstraintStream ifExistsIncludingUnassigned(Class otherC * a different definition of exists applies. * (See {@link ConstraintFactory#from(Class)} Javadoc.) * - * @param otherClass never null - * @param joiner never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner} is true */ - default BiConstraintStream ifNotExists(Class otherClass, TriJoiner joiner) { + default @NonNull BiConstraintStream ifNotExists(@NonNull Class otherClass, + @NonNull TriJoiner joiner) { return ifNotExists(otherClass, new TriJoiner[] { joiner }); } @@ -570,15 +503,12 @@ default BiConstraintStream ifNotExists(Class otherClass, TriJoiner< * As defined by {@link #ifNotExists(Class, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner}s are true */ - default BiConstraintStream ifNotExists(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2) { + default @NonNull BiConstraintStream ifNotExists(@NonNull Class otherClass, @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2) { return ifNotExists(otherClass, new TriJoiner[] { joiner1, joiner2 }); } @@ -586,16 +516,12 @@ default BiConstraintStream ifNotExists(Class otherClass, TriJoiner< * As defined by {@link #ifNotExists(Class, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner}s are true */ - default BiConstraintStream ifNotExists(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3) { + default @NonNull BiConstraintStream ifNotExists(@NonNull Class otherClass, @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3) { return ifNotExists(otherClass, new TriJoiner[] { joiner1, joiner2, joiner3 }); } @@ -603,17 +529,12 @@ default BiConstraintStream ifNotExists(Class otherClass, TriJoiner< * As defined by {@link #ifNotExists(Class, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner}s are true */ - default BiConstraintStream ifNotExists(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3, TriJoiner joiner4) { + default @NonNull BiConstraintStream ifNotExists(@NonNull Class otherClass, @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3, @NonNull TriJoiner joiner4) { return ifNotExists(otherClass, new TriJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -625,13 +546,11 @@ default BiConstraintStream ifNotExists(Class otherClass, TriJoiner< * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link TriJoiner} parameters. * - * @param otherClass never null - * @param joiners never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner}s are true */ - BiConstraintStream ifNotExists(Class otherClass, TriJoiner... joiners); + @NonNull BiConstraintStream ifNotExists(@NonNull Class otherClass, @NonNull TriJoiner... joiners); /** * Create a new {@link BiConstraintStream} for every pair of A and B where C does not exist for which the @@ -639,13 +558,12 @@ default BiConstraintStream ifNotExists(Class otherClass, TriJoiner< *

    * This method has overloaded methods with multiple {@link TriJoiner} parameters. * - * @param otherStream never null - * @param joiner never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner} is true */ - default BiConstraintStream ifNotExists(UniConstraintStream otherStream, TriJoiner joiner) { + default @NonNull BiConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner joiner) { return ifNotExists(otherStream, new TriJoiner[] { joiner }); } @@ -653,15 +571,12 @@ default BiConstraintStream ifNotExists(UniConstraintStream otherStr * As defined by {@link #ifNotExists(UniConstraintStream, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner}s are true */ - default BiConstraintStream ifNotExists(UniConstraintStream otherStream, TriJoiner joiner1, - TriJoiner joiner2) { + default @NonNull BiConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner joiner1, @NonNull TriJoiner joiner2) { return ifNotExists(otherStream, new TriJoiner[] { joiner1, joiner2 }); } @@ -669,16 +584,13 @@ default BiConstraintStream ifNotExists(UniConstraintStream otherStr * As defined by {@link #ifNotExists(UniConstraintStream, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null + * * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner}s are true */ - default BiConstraintStream ifNotExists(UniConstraintStream otherStream, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3) { + default @NonNull BiConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner joiner1, @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3) { return ifNotExists(otherStream, new TriJoiner[] { joiner1, joiner2, joiner3 }); } @@ -686,17 +598,13 @@ default BiConstraintStream ifNotExists(UniConstraintStream otherStr * As defined by {@link #ifNotExists(UniConstraintStream, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner}s are true */ - default BiConstraintStream ifNotExists(UniConstraintStream otherStream, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3, TriJoiner joiner4) { + default @NonNull BiConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner joiner1, @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3, + @NonNull TriJoiner joiner4) { return ifNotExists(otherStream, new TriJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -708,13 +616,12 @@ default BiConstraintStream ifNotExists(UniConstraintStream otherStr * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link TriJoiner} parameters. * - * @param otherStream never null - * @param joiners never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner}s are true */ - BiConstraintStream ifNotExists(UniConstraintStream otherStream, TriJoiner... joiners); + @NonNull BiConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner... joiners); /** * Create a new {@link BiConstraintStream} for every pair of A and B where C does not exist for which the @@ -725,13 +632,12 @@ default BiConstraintStream ifNotExists(UniConstraintStream otherStr *

    * This operation can be thought of as an or between streams. * - * @param otherStream never null - * @param paddingFunction never null, function to find the padding for the second fact - * @return never null + * @param paddingFunction function to find the padding for the second fact */ - BiConstraintStream concat(UniConstraintStream otherStream, Function paddingFunction); + @NonNull + BiConstraintStream concat(@NonNull UniConstraintStream otherStream, @NonNull Function paddingFunction); /** * Returns a new {@link BiConstraintStream} containing all the tuples of both this {@link BiConstraintStream} and the @@ -1284,10 +1164,9 @@ default BiConstraintStream concat(UniConstraintStream otherStream) { *

    * This operation can be thought of as an or between streams. * - * @param otherStream never null - * @return never null */ - BiConstraintStream concat(BiConstraintStream otherStream); + @NonNull + BiConstraintStream concat(@NonNull BiConstraintStream otherStream); /** * Returns a new {@link TriConstraintStream} containing all the tuples of both this {@link BiConstraintStream} @@ -1301,11 +1180,8 @@ default BiConstraintStream concat(UniConstraintStream otherStream) { * {@code [(A1, A2, null), (B1, B2, null), (C1, C2, null), (C1, C2, C3), (D1, D2, D3), (E1, E2, E3)]}. *

    * This operation can be thought of as an or between streams. - * - * @param otherStream never null - * @return never null */ - default TriConstraintStream concat(TriConstraintStream otherStream) { + default @NonNull TriConstraintStream concat(@NonNull TriConstraintStream otherStream) { return concat(otherStream, biConstantNull()); } @@ -1322,11 +1198,11 @@ default TriConstraintStream concat(TriConstraintStream oth *

    * This operation can be thought of as an or between streams. * - * @param otherStream never null - * @param paddingFunction never null, function to find the padding for the third fact - * @return never null + * @param paddingFunction function to find the padding for the third fact */ - TriConstraintStream concat(TriConstraintStream otherStream, BiFunction paddingFunction); + @NonNull + TriConstraintStream concat(@NonNull TriConstraintStream otherStream, + @NonNull BiFunction paddingFunction); /** * Returns a new {@link QuadConstraintStream} containing all the tuples of both this {@link BiConstraintStream} @@ -1342,10 +1218,8 @@ default TriConstraintStream concat(TriConstraintStream oth *

    * This operation can be thought of as an or between streams. * - * @param otherStream never null - * @return never null */ - default QuadConstraintStream concat(QuadConstraintStream otherStream) { + default @NonNull QuadConstraintStream concat(@NonNull QuadConstraintStream otherStream) { return concat(otherStream, biConstantNull(), biConstantNull()); } @@ -1363,13 +1237,11 @@ default QuadConstraintStream concat(QuadConstraintStream * This operation can be thought of as an or between streams. * - * @param otherStream never null - * @param paddingFunctionC never null, function to find the padding for the third fact - * @param paddingFunctionD never null, function to find the padding for the fourth fact - * @return never null + * @param paddingFunctionC function to find the padding for the third fact + * @param paddingFunctionD function to find the padding for the fourth fact */ - QuadConstraintStream concat(QuadConstraintStream otherStream, - BiFunction paddingFunctionC, BiFunction paddingFunctionD); + @NonNull QuadConstraintStream concat(@NonNull QuadConstraintStream otherStream, + @NonNull BiFunction paddingFunctionC, @NonNull BiFunction paddingFunctionD); // ************************************************************************ // expand @@ -1387,10 +1259,9 @@ QuadConstraintStream concat(QuadConstraintStream * prefer {@link #expand(BiFunction, BiFunction)}. * * @param mapping function to produce the new fact from the original tuple - * @return never null * @param type of the final fact of the new tuple */ - TriConstraintStream expand(BiFunction mapping); + @NonNull TriConstraintStream expand(@NonNull BiFunction mapping); /** * Adds two facts to the end of the tuple, increasing the cardinality of the stream. @@ -1403,12 +1274,12 @@ QuadConstraintStream concat(QuadConstraintStream * * @param mappingC function to produce the new third fact from the original tuple * @param mappingD function to produce the new final fact from the original tuple - * @return never null * @param type of the third fact of the new tuple * @param type of the final fact of the new tuple */ - QuadConstraintStream expand(BiFunction mappingC, - BiFunction mappingD); + @NonNull QuadConstraintStream expand( + @NonNull BiFunction mappingC, + @NonNull BiFunction mappingD); // ************************************************************************ // Penalize/reward @@ -1416,28 +1287,23 @@ QuadConstraintStream expand(BiFun /** * As defined by {@link #penalize(Score, ToIntBiFunction)}, where the match weight is one (1). - * - * @return never null */ - default > BiConstraintBuilder penalize(Score_ constraintWeight) { + default > @NonNull BiConstraintBuilder penalize(Score_ constraintWeight) { return penalize(constraintWeight, biConstantOne()); } /** * As defined by {@link #penalizeLong(Score, ToLongBiFunction)}, where the match weight is one (1). - * - * @return never null */ - default > BiConstraintBuilder penalizeLong(Score_ constraintWeight) { + default > @NonNull BiConstraintBuilder penalizeLong(Score_ constraintWeight) { return penalizeLong(constraintWeight, biConstantOneLong()); } /** * As defined by {@link #penalizeBigDecimal(Score, BiFunction)}, where the match weight is one (1). - * - * @return never null */ - default > BiConstraintBuilder penalizeBigDecimal(Score_ constraintWeight) { + default > @NonNull BiConstraintBuilder + penalizeBigDecimal(Score_ constraintWeight) { return penalizeBigDecimal(constraintWeight, biConstantOneBigDecimal()); } @@ -1452,24 +1318,23 @@ default > BiConstraintBuilder penaliz * For non-int {@link Score} types use {@link #penalizeLong(Score, ToLongBiFunction)} or * {@link #penalizeBigDecimal(Score, BiFunction)} instead. * - * @param constraintWeight never null - * @param matchWeigher never null, the result of this function (matchWeight) is multiplied by the constraintWeight - * @return never null + * @param matchWeigher the result of this function (matchWeight) is multiplied by the constraintWeight */ - > BiConstraintBuilder penalize(Score_ constraintWeight, - ToIntBiFunction matchWeigher); + > @NonNull BiConstraintBuilder penalize(@NonNull Score_ constraintWeight, + @NonNull ToIntBiFunction matchWeigher); /** * As defined by {@link #penalize(Score, ToIntBiFunction)}, with a penalty of type long. */ - > BiConstraintBuilder penalizeLong(Score_ constraintWeight, - ToLongBiFunction matchWeigher); + > @NonNull BiConstraintBuilder penalizeLong(@NonNull Score_ constraintWeight, + @NonNull ToLongBiFunction matchWeigher); /** * As defined by {@link #penalize(Score, ToIntBiFunction)}, with a penalty of type {@link BigDecimal}. */ - > BiConstraintBuilder penalizeBigDecimal(Score_ constraintWeight, - BiFunction matchWeigher); + > @NonNull BiConstraintBuilder penalizeBigDecimal( + @NonNull Score_ constraintWeight, + @NonNull BiFunction matchWeigher); /** * Negatively impacts the {@link Score}, @@ -1506,7 +1371,7 @@ > BiConstraintBuilder penalizeBigDeci /** * As defined by {@link #penalizeConfigurable(ToIntBiFunction)}, with a penalty of type long. - * + * * @deprecated Prefer {@link #penalizeLong(Score, ToLongBiFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -1514,7 +1379,7 @@ > BiConstraintBuilder penalizeBigDeci /** * As defined by {@link #penalizeConfigurable(ToIntBiFunction)}, with a penalty of type {@link BigDecimal}. - * + * * @deprecated Prefer {@link #penalizeBigDecimal(Score, BiFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -1522,10 +1387,8 @@ > BiConstraintBuilder penalizeBigDeci /** * As defined by {@link #reward(Score, ToIntBiFunction)}, where the match weight is one (1). - * - * @return never null */ - default > BiConstraintBuilder reward(Score_ constraintWeight) { + default > @NonNull BiConstraintBuilder reward(@NonNull Score_ constraintWeight) { return reward(constraintWeight, biConstantOne()); } @@ -1540,24 +1403,22 @@ default > BiConstraintBuilder reward( * For non-int {@link Score} types use {@link #rewardLong(Score, ToLongBiFunction)} or * {@link #rewardBigDecimal(Score, BiFunction)} instead. * - * @param constraintWeight never null - * @param matchWeigher never null, the result of this function (matchWeight) is multiplied by the constraintWeight - * @return never null + * @param matchWeigher the result of this function (matchWeight) is multiplied by the constraintWeight */ - > BiConstraintBuilder reward(Score_ constraintWeight, - ToIntBiFunction matchWeigher); + > @NonNull BiConstraintBuilder reward(@NonNull Score_ constraintWeight, + @NonNull ToIntBiFunction matchWeigher); /** * As defined by {@link #reward(Score, ToIntBiFunction)}, with a penalty of type long. */ - > BiConstraintBuilder rewardLong(Score_ constraintWeight, - ToLongBiFunction matchWeigher); + > @NonNull BiConstraintBuilder rewardLong(@NonNull Score_ constraintWeight, + @NonNull ToLongBiFunction matchWeigher); /** * As defined by {@link #reward(Score, ToIntBiFunction)}, with a penalty of type {@link BigDecimal}. */ - > BiConstraintBuilder rewardBigDecimal(Score_ constraintWeight, - BiFunction matchWeigher); + > @NonNull BiConstraintBuilder rewardBigDecimal(@NonNull Score_ constraintWeight, + @NonNull BiFunction matchWeigher); /** * Positively impacts the {@link Score}, @@ -1594,7 +1455,7 @@ > BiConstraintBuilder rewardBigDecima /** * As defined by {@link #rewardConfigurable(ToIntBiFunction)}, with a penalty of type long. - * + * * @deprecated Prefer {@link #rewardLong(Score, ToLongBiFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -1602,7 +1463,7 @@ > BiConstraintBuilder rewardBigDecima /** * As defined by {@link #rewardConfigurable(ToIntBiFunction)}, with a penalty of type {@link BigDecimal}. - * + * * @deprecated Prefer {@link #rewardBigDecimal(Score, BiFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -1614,11 +1475,8 @@ > BiConstraintBuilder rewardBigDecima *

    * Use {@code penalize(...)} or {@code reward(...)} instead, unless this constraint can both have positive and * negative weights. - * - * @param constraintWeight never null - * @return never null */ - default > BiConstraintBuilder impact(Score_ constraintWeight) { + default > @NonNull BiConstraintBuilder impact(@NonNull Score_ constraintWeight) { return impact(constraintWeight, biConstantOne()); } @@ -1632,24 +1490,22 @@ default > BiConstraintBuilder impact( * Use {@code penalize(...)} or {@code reward(...)} instead, unless this constraint can both have positive and * negative weights. * - * @param constraintWeight never null - * @param matchWeigher never null, the result of this function (matchWeight) is multiplied by the constraintWeight - * @return never null + * @param matchWeigher the result of this function (matchWeight) is multiplied by the constraintWeight */ - > BiConstraintBuilder impact(Score_ constraintWeight, - ToIntBiFunction matchWeigher); + > @NonNull BiConstraintBuilder impact(@NonNull Score_ constraintWeight, + @NonNull ToIntBiFunction matchWeigher); /** * As defined by {@link #impact(Score, ToIntBiFunction)}, with an impact of type long. */ - > BiConstraintBuilder impactLong(Score_ constraintWeight, - ToLongBiFunction matchWeigher); + > @NonNull BiConstraintBuilder impactLong(@NonNull Score_ constraintWeight, + @NonNull ToLongBiFunction matchWeigher); /** * As defined by {@link #impact(Score, ToIntBiFunction)}, with an impact of type {@link BigDecimal}. */ - > BiConstraintBuilder impactBigDecimal(Score_ constraintWeight, - BiFunction matchWeigher); + > @NonNull BiConstraintBuilder impactBigDecimal(@NonNull Score_ constraintWeight, + @NonNull BiFunction matchWeigher); /** * Positively impacts the {@link Score} by the {@link ConstraintWeight} for each match, @@ -1683,7 +1539,7 @@ > BiConstraintBuilder impactBigDecima /** * As defined by {@link #impactConfigurable(ToIntBiFunction)}, with an impact of type long. - * + * * @deprecated Prefer {@link #impactLong(Score, ToLongBiFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -1691,7 +1547,7 @@ > BiConstraintBuilder impactBigDecima /** * As defined by {@link #impactConfigurable(ToIntBiFunction)}, with an impact of type BigDecimal. - * + * * @deprecated Prefer {@link #impactBigDecimal(Score, BiFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -1705,7 +1561,7 @@ > BiConstraintBuilder impactBigDecima * As defined by {@link #complement(Class, Function)}, * where the padding function pads with null. */ - default BiConstraintStream complement(Class otherClass) { + default @NonNull BiConstraintStream complement(@NonNull Class otherClass) { return complement(otherClass, uniConstantNull()); } @@ -1720,11 +1576,10 @@ default BiConstraintStream complement(Class otherClass) { * The rest of the tuple will be padded with the result of the padding function, * applied on the new instance. * - * @param otherClass never null - * @param paddingFunction never null, function to find the padding for the second fact - * @return never null + * @param paddingFunction function to find the padding for the second fact */ - default BiConstraintStream complement(Class otherClass, Function paddingFunction) { + default @NonNull BiConstraintStream complement(@NonNull Class otherClass, + @NonNull Function paddingFunction) { var firstStream = this; var remapped = firstStream.map(ConstantLambdaUtils.biPickFirst()); var secondStream = getConstraintFactory().forEach(otherClass) diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiJoiner.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiJoiner.java index c188612779..e63eb63594 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiJoiner.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/bi/BiJoiner.java @@ -3,6 +3,8 @@ import ai.timefold.solver.core.api.score.stream.Joiners; import ai.timefold.solver.core.api.score.stream.uni.UniConstraintStream; +import org.jspecify.annotations.NonNull; + /** * Created with {@link Joiners}. * Used by {@link UniConstraintStream#join(Class, BiJoiner)}, ... @@ -10,7 +12,7 @@ * @see Joiners */ public interface BiJoiner { - - BiJoiner and(BiJoiner otherJoiner); + @NonNull + BiJoiner and(@NonNull BiJoiner otherJoiner); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/Break.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/Break.java index 3115c37eca..2a4fb1b37b 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/Break.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/Break.java @@ -1,5 +1,7 @@ package ai.timefold.solver.core.api.score.stream.common; +import org.jspecify.annotations.NonNull; + /** * Represents a gap between two {@link Sequence sequences}. * For instance, the list [1,2,4,5,6,10] has a break of length 2 between 2 and 4, @@ -24,16 +26,18 @@ public interface Break> { * Return the end of the sequence before this break. For the * break between 6 and 10, this will return 6. * - * @return never null; the item this break is directly after + * @return the item this break is directly after */ + @NonNull Value_ getPreviousSequenceEnd(); /** * Return the start of the sequence after this break. For the * break between 6 and 10, this will return 10. * - * @return never null; the item this break is directly before + * @return the item this break is directly before */ + @NonNull Value_ getNextSequenceStart(); /** @@ -41,8 +45,9 @@ public interface Break> { * between {@link #getNextSequenceStart()} and {@link #getPreviousSequenceEnd()}. For the * break between 6 and 10, this will return 4. * - * @return never null; the length of this break + * @return the length of this break */ + @NonNull Difference_ getLength(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/ConnectedRange.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/ConnectedRange.java index b83bb408ff..5447a72e5a 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/ConnectedRange.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/ConnectedRange.java @@ -1,5 +1,7 @@ package ai.timefold.solver.core.api.score.stream.common; +import org.jspecify.annotations.NonNull; + /** * Represents a collection of ranges that are connected, meaning * the union of all the ranges results in the range @@ -13,24 +15,24 @@ public interface ConnectedRange, Diffe extends Iterable { /** * Get the number of ranges contained by this {@link ConnectedRange}. - * - * @return never null, the number of ranges contained by this {@link ConnectedRange}. + * + * @return the number of ranges contained by this {@link ConnectedRange}. */ int getContainedRangeCount(); /** * True if this {@link ConnectedRange} has at least one pair of * ranges that overlaps each other, false otherwise. - * - * @return never null, true iff there at least one pair of overlapping ranges in this {@link ConnectedRange}. + * + * @return true iff there at least one pair of overlapping ranges in this {@link ConnectedRange}. */ boolean hasOverlap(); /** * Get the minimum number of overlapping ranges for any point contained by * this {@link ConnectedRange}. - * - * @return never null, the minimum number of overlapping ranges for any point + * + * @return the minimum number of overlapping ranges for any point * in this {@link ConnectedRange}. */ int getMinimumOverlap(); @@ -38,30 +40,33 @@ public interface ConnectedRange, Diffe /** * Get the maximum number of overlapping ranges for any point contained by * this {@link ConnectedRange}. - * - * @return never null, the maximum number of overlapping ranges for any point + * + * @return the maximum number of overlapping ranges for any point * in this {@link ConnectedRange}. */ int getMaximumOverlap(); /** * Get the length of this {@link ConnectedRange}. - * + * * @return The difference between {@link #getEnd()} and {@link #getStart()}. */ + @NonNull Difference_ getLength(); /** * Gets the first start point represented by this {@link ConnectedRange}. - * + * * @return never null, the first start point represented by this {@link ConnectedRange}. */ + @NonNull Point_ getStart(); /** * Gets the last end point represented by this {@link ConnectedRange}. - * - * @return never null, the last end point represented by this {@link ConnectedRange}. + * + * @return the last end point represented by this {@link ConnectedRange}. */ + @NonNull Point_ getEnd(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/ConnectedRangeChain.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/ConnectedRangeChain.java index 55a6c4555a..a492eee179 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/ConnectedRangeChain.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/ConnectedRangeChain.java @@ -1,5 +1,7 @@ package ai.timefold.solver.core.api.score.stream.common; +import org.jspecify.annotations.NonNull; + /** * Contains info regarding {@link ConnectedRange}s and {@link RangeGap}s for a collection of ranges. * @@ -10,14 +12,16 @@ public interface ConnectedRangeChain, Difference_ extends Comparable> { /** - * @return never null, an iterable that iterates through the {@link ConnectedRange}s + * @return an iterable that iterates through the {@link ConnectedRange}s * contained in the collection in ascending order of their start points */ + @NonNull Iterable> getConnectedRanges(); /** - * @return never null, an iterable that iterates through the {@link RangeGap}s contained in + * @return an iterable that iterates through the {@link RangeGap}s contained in * the collection in ascending order of their start points */ + @NonNull Iterable> getGaps(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/LoadBalance.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/LoadBalance.java index 5f04cb593c..3969d80fcd 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/LoadBalance.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/LoadBalance.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.score.stream.ConstraintCollectors; +import org.jspecify.annotations.NonNull; + /** * Calculates the unfairness measure for a particular input. * It is the result @@ -23,8 +25,8 @@ public interface LoadBalance { * For use in justifications, create a defensive copy of the map; * the map itself is mutable and will be mutated by the constraint collector. * - * @return never null */ + @NonNull Map loads(); /** @@ -36,8 +38,9 @@ public interface LoadBalance { * Comparing unfairness between solutions of different input problems is not helpful. * Only compare unfairness measures of solutions which have the same set of balanced items as input. * - * @return never null, never negative, six decimal places + * @return never negative, six decimal places */ + @NonNull BigDecimal unfairness(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/RangeGap.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/RangeGap.java index e84a8ce4b9..62ffd29a57 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/RangeGap.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/RangeGap.java @@ -1,5 +1,7 @@ package ai.timefold.solver.core.api.score.stream.common; +import org.jspecify.annotations.NonNull; + /** * A {@link RangeGap} is a gap between two consecutive {@link ConnectedRange}s. * For instance, the list [(1,3),(2,4),(3,5),(7,8)] has a grap of length 2 between 5 and 7. @@ -12,16 +14,18 @@ public interface RangeGap, Difference_ extends * Return the end of the {@link ConnectedRange} before this gap. * For the gap between 6 and 10, this will return 6. * - * @return never null, the item this gap is directly after + * @return the item this gap is directly after */ + @NonNull Point_ getPreviousRangeEnd(); /** * Return the start of the {@link ConnectedRange} after this gap. * For the gap between 6 and 10, this will return 10. * - * @return never null, the item this gap is directly before + * @return the item this gap is directly before */ + @NonNull Point_ getNextRangeStart(); /** @@ -29,7 +33,8 @@ public interface RangeGap, Difference_ extends * between {@link #getNextRangeStart()} and {@link #getPreviousRangeEnd()}. * For the gap between 6 and 10, this will return 4. * - * @return never null, the length of this break + * @return the length of this break */ + @NonNull Difference_ getLength(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/Sequence.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/Sequence.java index 25a3391223..8cdced33ba 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/Sequence.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/Sequence.java @@ -2,6 +2,9 @@ import java.util.Collection; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Represents a series of consecutive values. * For instance, the list [1,2,4,5,6,10] has three sequences: [1,2], [4,5,6], and [10]. @@ -12,13 +15,15 @@ public interface Sequence> { /** - * @return never null; the first item in the sequence. + * @return the first item in the sequence. */ + @NonNull Value_ getFirstItem(); /** - * @return never null; the last item in the sequence. + * @return the last item in the sequence. */ + @NonNull Value_ getLastItem(); /** @@ -34,16 +39,19 @@ public interface Sequence> { /** * @return If this is not the first sequence, the break before it. Otherwise, null. */ + @Nullable Break getPreviousBreak(); /** * @return If this is not the last sequence, the break after it. Otherwise, null. */ + @Nullable Break getNextBreak(); /** - * @return never null; items in this sequence + * @return items in this sequence */ + @NonNull Collection getItems(); /** @@ -52,7 +60,8 @@ public interface Sequence> { int getCount(); /** - * @return never null; the difference between the last item and first item in this sequence + * @return the difference between the last item and first item in this sequence */ + @NonNull Difference_ getLength(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/SequenceChain.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/SequenceChain.java index 6eb304db66..72574c5eb1 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/SequenceChain.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/common/SequenceChain.java @@ -2,6 +2,9 @@ import java.util.Collection; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Contains info regarding the consecutive sequences and breaks in a collection of points. * @@ -11,13 +14,15 @@ public interface SequenceChain> { /** - * @return never null; the sequences contained in the collection in ascending order. + * @return the sequences contained in the collection in ascending order. */ + @NonNull Collection> getConsecutiveSequences(); /** - * @return never null; the breaks contained in the collection in ascending order. + * @return the breaks contained in the collection in ascending order. */ + @NonNull Collection> getBreaks(); /** @@ -25,6 +30,7 @@ public interface SequenceChain getFirstSequence(); /** @@ -32,6 +38,7 @@ public interface SequenceChain getLastSequence(); /** @@ -39,6 +46,7 @@ public interface SequenceChain getFirstBreak(); /** @@ -46,6 +54,7 @@ public interface SequenceChain getLastBreak(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/quad/QuadConstraintBuilder.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/quad/QuadConstraintBuilder.java index 7c038548fb..1a69137579 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/quad/QuadConstraintBuilder.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/quad/QuadConstraintBuilder.java @@ -12,6 +12,8 @@ import ai.timefold.solver.core.api.score.stream.ConstraintBuilder; import ai.timefold.solver.core.api.score.stream.ConstraintJustification; +import org.jspecify.annotations.NonNull; + /** * Used to build a {@link Constraint} out of a {@link QuadConstraintStream}, applying optional configuration. * To build the constraint, use one of the terminal operations, such as {@link #asConstraint(String)}. @@ -27,21 +29,21 @@ public interface QuadConstraintBuilder> /** * Sets a custom function to apply on a constraint match to justify it. * - * @see ConstraintMatch - * @param justificationMapping never null * @return this + * @see ConstraintMatch */ - QuadConstraintBuilder justifyWith( - PentaFunction justificationMapping); + @NonNull QuadConstraintBuilder justifyWith( + @NonNull PentaFunction justificationMapping); /** * Sets a custom function to mark any object returned by it as responsible for causing the constraint to match. * Each object in the collection returned by this function will become an {@link Indictment} * and be available as a key in {@link ScoreExplanation#getIndictmentMap()}. * - * @param indictedObjectsMapping never null * @return this */ - QuadConstraintBuilder indictWith(QuadFunction> indictedObjectsMapping); + @NonNull + QuadConstraintBuilder indictWith( + @NonNull QuadFunction> indictedObjectsMapping); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/quad/QuadConstraintCollector.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/quad/QuadConstraintCollector.java index f323f39f3c..3e29f57037 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/quad/QuadConstraintCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/quad/QuadConstraintCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.ConstraintStream; import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; +import org.jspecify.annotations.NonNull; + /** * As described by {@link UniConstraintCollector}, only for {@link QuadConstraintStream}. * @@ -26,9 +28,8 @@ public interface QuadConstraintCollector /** * A lambda that creates the result container, one for each group key combination. - * - * @return never null */ + @NonNull Supplier supplier(); /** @@ -36,15 +37,15 @@ public interface QuadConstraintCollector * accumulates it in the result container * and returns an undo operation for that accumulation. * - * @return never null, the undo operation. This lambda is called when the facts no longer matches. + * @return the undo operation. This lambda is called when the facts no longer matches. */ + @NonNull PentaFunction accumulator(); /** * A lambda that converts the result container into the result. - * - * @return never null */ + @NonNull Function finisher(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/quad/QuadJoiner.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/quad/QuadJoiner.java index b100d8530b..a96a463857 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/quad/QuadJoiner.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/quad/QuadJoiner.java @@ -3,6 +3,8 @@ import ai.timefold.solver.core.api.score.stream.Joiners; import ai.timefold.solver.core.api.score.stream.tri.TriConstraintStream; +import org.jspecify.annotations.NonNull; + /** * Created with {@link Joiners}. * Used by {@link TriConstraintStream#join(Class, QuadJoiner)}, ... @@ -11,6 +13,7 @@ */ public interface QuadJoiner { - QuadJoiner and(QuadJoiner otherJoiner); + @NonNull + QuadJoiner and(@NonNull QuadJoiner otherJoiner); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriConstraintBuilder.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriConstraintBuilder.java index 99ea78afb5..f015f2c4c7 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriConstraintBuilder.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriConstraintBuilder.java @@ -12,6 +12,8 @@ import ai.timefold.solver.core.api.score.stream.ConstraintBuilder; import ai.timefold.solver.core.api.score.stream.ConstraintJustification; +import org.jspecify.annotations.NonNull; + /** * Used to build a {@link Constraint} out of a {@link TriConstraintStream}, applying optional configuration. * To build the constraint, use one of the terminal operations, such as {@link #asConstraint(String)}. @@ -28,20 +30,19 @@ public interface TriConstraintBuilder> ext * Sets a custom function to apply on a constraint match to justify it. * * @see ConstraintMatch - * @param justificationMapping never null * @return this */ - TriConstraintBuilder justifyWith( - QuadFunction justificationMapping); + @NonNull TriConstraintBuilder justifyWith( + @NonNull QuadFunction justificationMapping); /** * Sets a custom function to mark any object returned by it as responsible for causing the constraint to match. * Each object in the collection returned by this function will become an {@link Indictment} * and be available as a key in {@link ScoreExplanation#getIndictmentMap()}. * - * @param indictedObjectsMapping never null * @return this */ - TriConstraintBuilder indictWith(TriFunction> indictedObjectsMapping); + @NonNull + TriConstraintBuilder indictWith(@NonNull TriFunction> indictedObjectsMapping); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriConstraintCollector.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriConstraintCollector.java index 12c6b4b470..4d075f3287 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriConstraintCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriConstraintCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.ConstraintStream; import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; +import org.jspecify.annotations.NonNull; + /** * As described by {@link UniConstraintCollector}, only for {@link TriConstraintStream}. * @@ -25,9 +27,8 @@ public interface TriConstraintCollector { /** * A lambda that creates the result container, one for each group key combination. - * - * @return never null */ + @NonNull Supplier supplier(); /** @@ -35,15 +36,15 @@ public interface TriConstraintCollector { * accumulates it in the result container * and returns an undo operation for that accumulation. * - * @return never null, the undo operation. This lambda is called when the facts no longer matches. + * @return the undo operation. This lambda is called when the facts no longer matches. */ + @NonNull QuadFunction accumulator(); /** * A lambda that converts the result container into the result. - * - * @return never null */ + @NonNull Function finisher(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriConstraintStream.java index be17deb29d..3d9222da56 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriConstraintStream.java @@ -36,6 +36,8 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintStream; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + /** * A {@link ConstraintStream} that matches three facts. * @@ -57,11 +59,9 @@ public interface TriConstraintStream extends ConstraintStream { * Important: This is slower and less scalable than {@link BiConstraintStream#join(UniConstraintStream, TriJoiner)} * with a proper {@link TriJoiner} predicate (such as {@link Joiners#equal(BiFunction, Function)}, * because the latter applies hashing and/or indexing, so it doesn't create every combination just to filter it out. - * - * @param predicate never null - * @return never null */ - TriConstraintStream filter(TriPredicate predicate); + @NonNull + TriConstraintStream filter(@NonNull TriPredicate predicate); // ************************************************************************ // Join @@ -75,11 +75,10 @@ public interface TriConstraintStream extends ConstraintStream { * because it doesn't apply hashing and/or indexing on the properties, * so it creates and checks every combination of [A, B] and C. * - * @param otherStream never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every combination of [A, B, C] and D + * @return a stream that matches every combination of [A, B, C] and D */ - default QuadConstraintStream join(UniConstraintStream otherStream) { + default @NonNull QuadConstraintStream join(@NonNull UniConstraintStream otherStream) { return join(otherStream, new QuadJoiner[0]); } @@ -92,13 +91,12 @@ default QuadConstraintStream join(UniConstraintStream otherSt * because it applies hashing and/or indexing on the properties, * so it doesn't create nor checks every combination of [A, B, C] and D. * - * @param otherStream never null - * @param joiner never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every combination of [A, B, C] and D for which the {@link QuadJoiner} + * @return a stream that matches every combination of [A, B, C] and D for which the {@link QuadJoiner} * is true */ - default QuadConstraintStream join(UniConstraintStream otherStream, QuadJoiner joiner) { + default @NonNull QuadConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner joiner) { return join(otherStream, new QuadJoiner[] { joiner }); } @@ -106,15 +104,12 @@ default QuadConstraintStream join(UniConstraintStream otherSt * As defined by {@link #join(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every combination of [A, B, C] and D for which all the + * @return a stream that matches every combination of [A, B, C] and D for which all the * {@link QuadJoiner joiners} are true */ - default QuadConstraintStream join(UniConstraintStream otherStream, - QuadJoiner joiner1, QuadJoiner joiner2) { + default @NonNull QuadConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2) { return join(otherStream, new QuadJoiner[] { joiner1, joiner2 }); } @@ -122,16 +117,13 @@ default QuadConstraintStream join(UniConstraintStream otherSt * As defined by {@link #join(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every combination of [A, B, C] and D for which all the + * @return a stream that matches every combination of [A, B, C] and D for which all the * {@link QuadJoiner joiners} are true */ - default QuadConstraintStream join(UniConstraintStream otherStream, - QuadJoiner joiner1, QuadJoiner joiner2, QuadJoiner joiner3) { + default @NonNull QuadConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2, + @NonNull QuadJoiner joiner3) { return join(otherStream, new QuadJoiner[] { joiner1, joiner2, joiner3 }); } @@ -139,18 +131,14 @@ default QuadConstraintStream join(UniConstraintStream otherSt * As defined by {@link #join(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every combination of [A, B, C] and D for which all the + * @return a stream that matches every combination of [A, B, C] and D for which all the * {@link QuadJoiner joiners} are true */ - default QuadConstraintStream join(UniConstraintStream otherStream, - QuadJoiner joiner1, QuadJoiner joiner2, QuadJoiner joiner3, - QuadJoiner joiner4) { + default @NonNull QuadConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2, + @NonNull QuadJoiner joiner3, + @NonNull QuadJoiner joiner4) { return join(otherStream, new QuadJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -162,13 +150,12 @@ default QuadConstraintStream join(UniConstraintStream otherSt * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link QuadJoiner} parameters. * - * @param otherStream never null - * @param joiners never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every combination of [A, B, C] and D for which all the + * @return a stream that matches every combination of [A, B, C] and D for which all the * {@link QuadJoiner joiners} are true */ - QuadConstraintStream join(UniConstraintStream otherStream, QuadJoiner... joiners); + @NonNull QuadConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner... joiners); /** * Create a new {@link QuadConstraintStream} for every combination of [A, B, C] and D. @@ -185,11 +172,10 @@ default QuadConstraintStream join(UniConstraintStream otherSt *

    * This method is syntactic sugar for {@link #join(UniConstraintStream)}. * - * @param otherClass never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every combination of [A, B, C] and D + * @return a stream that matches every combination of [A, B, C] and D */ - default QuadConstraintStream join(Class otherClass) { + default @NonNull QuadConstraintStream join(@NonNull Class otherClass) { return join(otherClass, new QuadJoiner[0]); } @@ -211,13 +197,12 @@ default QuadConstraintStream join(Class otherClass) { *

    * This method has overloaded methods with multiple {@link QuadJoiner} parameters. * - * @param otherClass never null - * @param joiner never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every combination of [A, B, C] and D for which the {@link QuadJoiner} + * @return a stream that matches every combination of [A, B, C] and D for which the {@link QuadJoiner} * is true */ - default QuadConstraintStream join(Class otherClass, QuadJoiner joiner) { + default @NonNull QuadConstraintStream join(@NonNull Class otherClass, + @NonNull QuadJoiner joiner) { return join(otherClass, new QuadJoiner[] { joiner }); } @@ -225,15 +210,13 @@ default QuadConstraintStream join(Class otherClass, QuadJoine * As defined by {@link #join(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every combination of [A, B, C] and D for which all the + * @return a stream that matches every combination of [A, B, C] and D for which all the * {@link QuadJoiner joiners} are true */ - default QuadConstraintStream join(Class otherClass, QuadJoiner joiner1, - QuadJoiner joiner2) { + default @NonNull QuadConstraintStream join(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, + @NonNull QuadJoiner joiner2) { return join(otherClass, new QuadJoiner[] { joiner1, joiner2 }); } @@ -241,16 +224,13 @@ default QuadConstraintStream join(Class otherClass, QuadJoine * As defined by {@link #join(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every combination of [A, B, C] and D for which all the + * @return a stream that matches every combination of [A, B, C] and D for which all the * {@link QuadJoiner joiners} are true */ - default QuadConstraintStream join(Class otherClass, QuadJoiner joiner1, - QuadJoiner joiner2, QuadJoiner joiner3) { + default @NonNull QuadConstraintStream join(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, + @NonNull QuadJoiner joiner2, @NonNull QuadJoiner joiner3) { return join(otherClass, new QuadJoiner[] { joiner1, joiner2, joiner3 }); } @@ -258,17 +238,14 @@ default QuadConstraintStream join(Class otherClass, QuadJoine * As defined by {@link #join(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every combination of [A, B, C] and D for which all the + * @return a stream that matches every combination of [A, B, C] and D for which all the * {@link QuadJoiner joiners} are true */ - default QuadConstraintStream join(Class otherClass, QuadJoiner joiner1, - QuadJoiner joiner2, QuadJoiner joiner3, QuadJoiner joiner4) { + default @NonNull QuadConstraintStream join(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, + @NonNull QuadJoiner joiner2, @NonNull QuadJoiner joiner3, + @NonNull QuadJoiner joiner4) { return join(otherClass, new QuadJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -280,13 +257,12 @@ default QuadConstraintStream join(Class otherClass, QuadJoine * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link QuadJoiner} parameters. * - * @param otherClass never null - * @param joiners never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every combination of [A, B, C] and D for which all the + * @return a stream that matches every combination of [A, B, C] and D for which all the * {@link QuadJoiner joiners} are true */ - QuadConstraintStream join(Class otherClass, QuadJoiner... joiners); + @NonNull QuadConstraintStream join(@NonNull Class otherClass, + @NonNull QuadJoiner... joiners); // ************************************************************************ // If (not) exists @@ -303,13 +279,12 @@ default QuadConstraintStream join(Class otherClass, QuadJoine * a different definition of exists applies. * (See {@link ConstraintFactory#from(Class)} Javadoc.) * - * @param otherClass never null - * @param joiner never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner} is true */ - default TriConstraintStream ifExists(Class otherClass, QuadJoiner joiner) { + default @NonNull TriConstraintStream ifExists(@NonNull Class otherClass, + @NonNull QuadJoiner joiner) { return ifExists(otherClass, new QuadJoiner[] { joiner }); } @@ -317,15 +292,13 @@ default TriConstraintStream ifExists(Class otherClass, QuadJoine * As defined by {@link #ifExists(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifExists(Class otherClass, QuadJoiner joiner1, - QuadJoiner joiner2) { + default @NonNull TriConstraintStream ifExists(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, + @NonNull QuadJoiner joiner2) { return ifExists(otherClass, new QuadJoiner[] { joiner1, joiner2 }); } @@ -333,16 +306,13 @@ default TriConstraintStream ifExists(Class otherClass, QuadJoine * As defined by {@link #ifExists(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifExists(Class otherClass, QuadJoiner joiner1, - QuadJoiner joiner2, QuadJoiner joiner3) { + default @NonNull TriConstraintStream ifExists(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, + @NonNull QuadJoiner joiner2, @NonNull QuadJoiner joiner3) { return ifExists(otherClass, new QuadJoiner[] { joiner1, joiner2, joiner3 }); } @@ -350,17 +320,14 @@ default TriConstraintStream ifExists(Class otherClass, QuadJoine * As defined by {@link #ifExists(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifExists(Class otherClass, QuadJoiner joiner1, - QuadJoiner joiner2, QuadJoiner joiner3, QuadJoiner joiner4) { + default @NonNull TriConstraintStream ifExists(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, + @NonNull QuadJoiner joiner2, @NonNull QuadJoiner joiner3, + @NonNull QuadJoiner joiner4) { return ifExists(otherClass, new QuadJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -372,13 +339,12 @@ default TriConstraintStream ifExists(Class otherClass, QuadJoine * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link QuadJoiner} parameters. * - * @param otherClass never null - * @param joiners never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner}s are true */ - TriConstraintStream ifExists(Class otherClass, QuadJoiner... joiners); + @NonNull TriConstraintStream ifExists(@NonNull Class otherClass, + @NonNull QuadJoiner... joiners); /** * Create a new {@link BiConstraintStream} for every tuple of A, B and C where D exists for which the @@ -386,13 +352,12 @@ default TriConstraintStream ifExists(Class otherClass, QuadJoine *

    * This method has overloaded methods with multiple {@link QuadJoiner} parameters. * - * @param otherStream never null - * @param joiner never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner} is true */ - default TriConstraintStream ifExists(UniConstraintStream otherStream, QuadJoiner joiner) { + default @NonNull TriConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner joiner) { return ifExists(otherStream, new QuadJoiner[] { joiner }); } @@ -400,15 +365,13 @@ default TriConstraintStream ifExists(UniConstraintStream otherSt * As defined by {@link #ifExists(UniConstraintStream, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifExists(UniConstraintStream otherStream, QuadJoiner joiner1, - QuadJoiner joiner2) { + default @NonNull TriConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner joiner1, + @NonNull QuadJoiner joiner2) { return ifExists(otherStream, new QuadJoiner[] { joiner1, joiner2 }); } @@ -416,16 +379,13 @@ default TriConstraintStream ifExists(UniConstraintStream otherSt * As defined by {@link #ifExists(UniConstraintStream, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifExists(UniConstraintStream otherStream, QuadJoiner joiner1, - QuadJoiner joiner2, QuadJoiner joiner3) { + default @NonNull TriConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner joiner1, + @NonNull QuadJoiner joiner2, @NonNull QuadJoiner joiner3) { return ifExists(otherStream, new QuadJoiner[] { joiner1, joiner2, joiner3 }); } @@ -433,17 +393,14 @@ default TriConstraintStream ifExists(UniConstraintStream otherSt * As defined by {@link #ifExists(UniConstraintStream, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifExists(UniConstraintStream otherStream, QuadJoiner joiner1, - QuadJoiner joiner2, QuadJoiner joiner3, QuadJoiner joiner4) { + default @NonNull TriConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner joiner1, + @NonNull QuadJoiner joiner2, @NonNull QuadJoiner joiner3, + @NonNull QuadJoiner joiner4) { return ifExists(otherStream, new QuadJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -455,13 +412,12 @@ default TriConstraintStream ifExists(UniConstraintStream otherSt * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link QuadJoiner} parameters. * - * @param otherStream never null - * @param joiners never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner}s are true */ - TriConstraintStream ifExists(UniConstraintStream otherStream, QuadJoiner... joiners); + @NonNull TriConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner... joiners); /** * Create a new {@link BiConstraintStream} for every tuple of A, B and C where D exists for which the @@ -472,14 +428,12 @@ default TriConstraintStream ifExists(UniConstraintStream otherSt *

    * This method has overloaded methods with multiple {@link QuadJoiner} parameters. * - * @param otherClass never null - * @param joiner never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner} is true */ - default TriConstraintStream ifExistsIncludingUnassigned(Class otherClass, - QuadJoiner joiner) { + default @NonNull TriConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull QuadJoiner joiner) { return ifExistsIncludingUnassigned(otherClass, new QuadJoiner[] { joiner }); } @@ -487,15 +441,12 @@ default TriConstraintStream ifExistsIncludingUnassigned(Class ot * As defined by {@link #ifExistsIncludingUnassigned(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifExistsIncludingUnassigned(Class otherClass, - QuadJoiner joiner1, QuadJoiner joiner2) { + default @NonNull TriConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2) { return ifExistsIncludingUnassigned(otherClass, new QuadJoiner[] { joiner1, joiner2 }); } @@ -503,16 +454,13 @@ default TriConstraintStream ifExistsIncludingUnassigned(Class ot * As defined by {@link #ifExistsIncludingUnassigned(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifExistsIncludingUnassigned(Class otherClass, - QuadJoiner joiner1, QuadJoiner joiner2, QuadJoiner joiner3) { + default @NonNull TriConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2, + @NonNull QuadJoiner joiner3) { return ifExistsIncludingUnassigned(otherClass, new QuadJoiner[] { joiner1, joiner2, joiner3 }); } @@ -520,18 +468,13 @@ default TriConstraintStream ifExistsIncludingUnassigned(Class ot * As defined by {@link #ifExistsIncludingUnassigned(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifExistsIncludingUnassigned(Class otherClass, - QuadJoiner joiner1, QuadJoiner joiner2, QuadJoiner joiner3, - QuadJoiner joiner4) { + default @NonNull TriConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2, + @NonNull QuadJoiner joiner3, @NonNull QuadJoiner joiner4) { return ifExistsIncludingUnassigned(otherClass, new QuadJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -543,13 +486,12 @@ default TriConstraintStream ifExistsIncludingUnassigned(Class ot * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link QuadJoiner} parameters. * - * @param otherClass never null - * @param joiners never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D exists for which the + * @return a stream that matches every tuple of A, B and C where D exists for which the * {@link QuadJoiner}s are true */ - TriConstraintStream ifExistsIncludingUnassigned(Class otherClass, QuadJoiner... joiners); + @NonNull TriConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull QuadJoiner... joiners); /** * Create a new {@link BiConstraintStream} for every tuple of A, B and C where D does not exist for which the @@ -562,13 +504,12 @@ default TriConstraintStream ifExistsIncludingUnassigned(Class ot * a different definition of exists applies. * (See {@link ConstraintFactory#from(Class)} Javadoc.) * - * @param otherClass never null - * @param joiner never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner} is true */ - default TriConstraintStream ifNotExists(Class otherClass, QuadJoiner joiner) { + default @NonNull TriConstraintStream ifNotExists(@NonNull Class otherClass, + @NonNull QuadJoiner joiner) { return ifNotExists(otherClass, new QuadJoiner[] { joiner }); } @@ -576,15 +517,12 @@ default TriConstraintStream ifNotExists(Class otherClass, QuadJo * As defined by {@link #ifNotExists(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifNotExists(Class otherClass, QuadJoiner joiner1, - QuadJoiner joiner2) { + default @NonNull TriConstraintStream ifNotExists(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2) { return ifNotExists(otherClass, new QuadJoiner[] { joiner1, joiner2 }); } @@ -592,16 +530,13 @@ default TriConstraintStream ifNotExists(Class otherClass, QuadJo * As defined by {@link #ifNotExists(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifNotExists(Class otherClass, QuadJoiner joiner1, - QuadJoiner joiner2, QuadJoiner joiner3) { + default @NonNull TriConstraintStream ifNotExists(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2, + @NonNull QuadJoiner joiner3) { return ifNotExists(otherClass, new QuadJoiner[] { joiner1, joiner2, joiner3 }); } @@ -609,17 +544,13 @@ default TriConstraintStream ifNotExists(Class otherClass, QuadJo * As defined by {@link #ifNotExists(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifNotExists(Class otherClass, QuadJoiner joiner1, - QuadJoiner joiner2, QuadJoiner joiner3, QuadJoiner joiner4) { + default @NonNull TriConstraintStream ifNotExists(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2, + @NonNull QuadJoiner joiner3, @NonNull QuadJoiner joiner4) { return ifNotExists(otherClass, new QuadJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -632,12 +563,11 @@ default TriConstraintStream ifNotExists(Class otherClass, QuadJo * Therefore, there are overloaded methods with up to 4 {@link QuadJoiner} parameters. * * @param the type of the fourth matched fact - * @param otherClass never null - * @param joiners never null - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner}s are true */ - TriConstraintStream ifNotExists(Class otherClass, QuadJoiner... joiners); + @NonNull TriConstraintStream ifNotExists(@NonNull Class otherClass, + @NonNull QuadJoiner... joiners); /** * Create a new {@link BiConstraintStream} for every tuple of A, B and C where D does not exist for which the @@ -645,13 +575,12 @@ default TriConstraintStream ifNotExists(Class otherClass, QuadJo *

    * This method has overloaded methods with multiple {@link QuadJoiner} parameters. * - * @param otherStream never null - * @param joiner never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner} is true */ - default TriConstraintStream ifNotExists(UniConstraintStream otherStream, QuadJoiner joiner) { + default @NonNull TriConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner joiner) { return ifNotExists(otherStream, new QuadJoiner[] { joiner }); } @@ -659,15 +588,12 @@ default TriConstraintStream ifNotExists(UniConstraintStream othe * As defined by {@link #ifNotExists(UniConstraintStream, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifNotExists(UniConstraintStream otherStream, QuadJoiner joiner1, - QuadJoiner joiner2) { + default @NonNull TriConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2) { return ifNotExists(otherStream, new QuadJoiner[] { joiner1, joiner2 }); } @@ -675,16 +601,13 @@ default TriConstraintStream ifNotExists(UniConstraintStream othe * As defined by {@link #ifNotExists(UniConstraintStream, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifNotExists(UniConstraintStream otherStream, QuadJoiner joiner1, - QuadJoiner joiner2, QuadJoiner joiner3) { + default @NonNull TriConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2, + @NonNull QuadJoiner joiner3) { return ifNotExists(otherStream, new QuadJoiner[] { joiner1, joiner2, joiner3 }); } @@ -692,17 +615,13 @@ default TriConstraintStream ifNotExists(UniConstraintStream othe * As defined by {@link #ifNotExists(UniConstraintStream, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifNotExists(UniConstraintStream otherStream, QuadJoiner joiner1, - QuadJoiner joiner2, QuadJoiner joiner3, QuadJoiner joiner4) { + default @NonNull TriConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2, + @NonNull QuadJoiner joiner3, @NonNull QuadJoiner joiner4) { return ifNotExists(otherStream, new QuadJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -715,12 +634,11 @@ default TriConstraintStream ifNotExists(UniConstraintStream othe * Therefore, there are overloaded methods with up to 4 {@link QuadJoiner} parameters. * * @param the type of the fourth matched fact - * @param otherStream never null - * @param joiners never null - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner}s are true */ - TriConstraintStream ifNotExists(UniConstraintStream otherStream, QuadJoiner... joiners); + @NonNull TriConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner... joiners); /** * Create a new {@link BiConstraintStream} for every tuple of A, B and C where D does not exist for which the @@ -731,14 +649,12 @@ default TriConstraintStream ifNotExists(UniConstraintStream othe *

    * This method has overloaded methods with multiple {@link QuadJoiner} parameters. * - * @param otherClass never null - * @param joiner never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner} is true */ - default TriConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, - QuadJoiner joiner) { + default @NonNull TriConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull QuadJoiner joiner) { return ifNotExistsIncludingUnassigned(otherClass, new QuadJoiner[] { joiner }); } @@ -746,15 +662,12 @@ default TriConstraintStream ifNotExistsIncludingUnassigned(Class * As defined by {@link #ifNotExistsIncludingUnassigned(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, - QuadJoiner joiner1, QuadJoiner joiner2) { + default @NonNull TriConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2) { return ifNotExistsIncludingUnassigned(otherClass, new QuadJoiner[] { joiner1, joiner2 }); } @@ -762,16 +675,13 @@ default TriConstraintStream ifNotExistsIncludingUnassigned(Class * As defined by {@link #ifNotExistsIncludingUnassigned(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, - QuadJoiner joiner1, QuadJoiner joiner2, QuadJoiner joiner3) { + default @NonNull TriConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2, + @NonNull QuadJoiner joiner3) { return ifNotExistsIncludingUnassigned(otherClass, new QuadJoiner[] { joiner1, joiner2, joiner3 }); } @@ -779,18 +689,13 @@ default TriConstraintStream ifNotExistsIncludingUnassigned(Class * As defined by {@link #ifNotExistsIncludingUnassigned(Class, QuadJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the fourth matched fact - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner}s are true */ - default TriConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, - QuadJoiner joiner1, QuadJoiner joiner2, QuadJoiner joiner3, - QuadJoiner joiner4) { + default @NonNull TriConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull QuadJoiner joiner1, @NonNull QuadJoiner joiner2, + @NonNull QuadJoiner joiner3, @NonNull QuadJoiner joiner4) { return ifNotExistsIncludingUnassigned(otherClass, new QuadJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -803,13 +708,11 @@ default TriConstraintStream ifNotExistsIncludingUnassigned(Class * Therefore, there are overloaded methods with up to 4 {@link QuadJoiner} parameters. * * @param the type of the fourth matched fact - * @param otherClass never null - * @param joiners never null - * @return never null, a stream that matches every tuple of A, B and C where D does not exist for which the + * @return a stream that matches every tuple of A, B and C where D does not exist for which the * {@link QuadJoiner}s are true */ - TriConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, - QuadJoiner... joiners); + @NonNull TriConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull QuadJoiner... joiners); // ************************************************************************ // Group by @@ -819,42 +722,40 @@ TriConstraintStream ifNotExistsIncludingUnassigned(Class otherCl * Convert the {@link TriConstraintStream} to a {@link UniConstraintStream}, containing only a single tuple, the * result of applying {@link TriConstraintCollector}. * - * @param collector never null, the collector to perform the grouping operation with + * @param collector the collector to perform the grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of a fact in the destination {@link UniConstraintStream}'s tuple - * @return never null */ - UniConstraintStream groupBy( - TriConstraintCollector collector); + @NonNull UniConstraintStream groupBy( + @NonNull TriConstraintCollector collector); /** * Convert the {@link TriConstraintStream} to a {@link BiConstraintStream}, containing only a single tuple, * the result of applying two {@link TriConstraintCollector}s. * - * @param collectorA never null, the collector to perform the first grouping operation with + * @param collectorA the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorB never null, the collector to perform the second grouping operation with + * @param collectorB the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the first fact in the destination {@link BiConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the second fact in the destination {@link BiConstraintStream}'s tuple - * @return never null */ - BiConstraintStream groupBy( - TriConstraintCollector collectorA, - TriConstraintCollector collectorB); + @NonNull BiConstraintStream groupBy( + @NonNull TriConstraintCollector collectorA, + @NonNull TriConstraintCollector collectorB); /** * Convert the {@link TriConstraintStream} to a {@link TriConstraintStream}, containing only a single tuple, * the result of applying three {@link TriConstraintCollector}s. * - * @param collectorA never null, the collector to perform the first grouping operation with + * @param collectorA the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorB never null, the collector to perform the second grouping operation with + * @param collectorB the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorC never null, the collector to perform the third grouping operation with + * @param collectorC the collector to perform the third grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the first fact in the destination {@link TriConstraintStream}'s tuple @@ -862,25 +763,24 @@ BiConstraintStream the type of the second fact in the destination {@link TriConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the third fact in the destination {@link TriConstraintStream}'s tuple - * @return never null */ - TriConstraintStream groupBy( - TriConstraintCollector collectorA, - TriConstraintCollector collectorB, - TriConstraintCollector collectorC); + @NonNull TriConstraintStream groupBy( + @NonNull TriConstraintCollector collectorA, + @NonNull TriConstraintCollector collectorB, + @NonNull TriConstraintCollector collectorC); /** * Convert the {@link TriConstraintStream} to a {@link QuadConstraintStream}, containing only a single tuple, * the result of applying four {@link TriConstraintCollector}s. * - * @param collectorA never null, the collector to perform the first grouping operation with + * @param collectorA the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorB never null, the collector to perform the second grouping operation with + * @param collectorB the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorC never null, the collector to perform the third grouping operation with + * @param collectorC the collector to perform the third grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorD never null, the collector to perform the fourth grouping operation with + * @param collectorD the collector to perform the fourth grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the first fact in the destination {@link QuadConstraintStream}'s tuple @@ -890,26 +790,24 @@ TriConstraintStream groupBy( * @param the type of the third fact in the destination {@link QuadConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream groupBy( - TriConstraintCollector collectorA, - TriConstraintCollector collectorB, - TriConstraintCollector collectorC, - TriConstraintCollector collectorD); + @NonNull QuadConstraintStream groupBy( + @NonNull TriConstraintCollector collectorA, + @NonNull TriConstraintCollector collectorB, + @NonNull TriConstraintCollector collectorC, + @NonNull TriConstraintCollector collectorD); /** * Convert the {@link TriConstraintStream} to a {@link UniConstraintStream}, containing the set of tuples resulting * from applying the group key mapping function on all tuples of the original stream. * Neither tuple of the new stream {@link Objects#equals(Object, Object)} any other. * - * @param groupKeyMapping never null, mapping function to convert each element in the stream to a different element + * @param groupKeyMapping mapping function to convert each element in the stream to a different element * @param the type of a fact in the destination {@link UniConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. - * @return never null */ - UniConstraintStream groupBy(TriFunction groupKeyMapping); + @NonNull UniConstraintStream groupBy(@NonNull TriFunction groupKeyMapping); /** * Convert the {@link TriConstraintStream} to a {@link BiConstraintStream}, consisting of unique tuples. @@ -918,18 +816,17 @@ QuadConstraintStream groupBy( * The second fact is the return value of a given {@link TriConstraintCollector} applied on all incoming tuples with * the same first fact. * - * @param groupKeyMapping never null, function to convert the fact in the original tuple to a different fact - * @param collector never null, the collector to perform the grouping operation with + * @param groupKeyMapping function to convert the fact in the original tuple to a different fact + * @param collector the collector to perform the grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the type of the first fact in the destination {@link BiConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the second fact in the destination {@link BiConstraintStream}'s tuple - * @return never null */ - BiConstraintStream groupBy( - TriFunction groupKeyMapping, - TriConstraintCollector collector); + @NonNull BiConstraintStream groupBy( + @NonNull TriFunction groupKeyMapping, + @NonNull TriConstraintCollector collector); /** * Convert the {@link TriConstraintStream} to a {@link TriConstraintStream}, consisting of unique tuples with three @@ -939,10 +836,10 @@ BiConstraintStream gr * The remaining facts are the return value of the respective {@link TriConstraintCollector} applied on all * incoming tuples with the same first fact. * - * @param groupKeyMapping never null, function to convert the fact in the original tuple to a different fact - * @param collectorB never null, the collector to perform the first grouping operation with + * @param groupKeyMapping function to convert the fact in the original tuple to a different fact + * @param collectorB the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorC never null, the collector to perform the second grouping operation with + * @param collectorC the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the type of the first fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -950,13 +847,13 @@ BiConstraintStream gr * @param the type of the second fact in the destination {@link TriConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the third fact in the destination {@link TriConstraintStream}'s tuple - * @return never null */ + - TriConstraintStream groupBy( - TriFunction groupKeyMapping, - TriConstraintCollector collectorB, - TriConstraintCollector collectorC); + @NonNull TriConstraintStream groupBy( + @NonNull TriFunction groupKeyMapping, + @NonNull TriConstraintCollector collectorB, + @NonNull TriConstraintCollector collectorC); /** * Convert the {@link TriConstraintStream} to a {@link QuadConstraintStream}, consisting of unique tuples with four @@ -966,12 +863,12 @@ TriConstraintStream groupBy( * The remaining facts are the return value of the respective {@link TriConstraintCollector} applied on all * incoming tuples with the same first fact. * - * @param groupKeyMapping never null, function to convert the fact in the original tuple to a different fact - * @param collectorB never null, the collector to perform the first grouping operation with + * @param groupKeyMapping function to convert the fact in the original tuple to a different fact + * @param collectorB the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorC never null, the collector to perform the second grouping operation with + * @param collectorC the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorD never null, the collector to perform the third grouping operation with + * @param collectorD the collector to perform the third grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the type of the first fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -981,14 +878,13 @@ TriConstraintStream groupBy( * @param the type of the third fact in the destination {@link QuadConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream groupBy( - TriFunction groupKeyMapping, - TriConstraintCollector collectorB, - TriConstraintCollector collectorC, - TriConstraintCollector collectorD); + @NonNull QuadConstraintStream groupBy( + @NonNull TriFunction groupKeyMapping, + @NonNull TriConstraintCollector collectorB, + @NonNull TriConstraintCollector collectorC, + @NonNull TriConstraintCollector collectorD); /** * Convert the {@link TriConstraintStream} to a {@link BiConstraintStream}, consisting of unique tuples. @@ -997,16 +893,16 @@ QuadConstraintStream groupBy( * The second fact is the return value of the second group key mapping function, applied on all incoming tuples with * the same first fact. * - * @param groupKeyAMapping never null, function to convert the facts in the original tuple to a new fact - * @param groupKeyBMapping never null, function to convert the facts in the original tuple to another new fact + * @param groupKeyAMapping function to convert the facts in the original tuple to a new fact + * @param groupKeyBMapping function to convert the facts in the original tuple to another new fact * @param the type of the first fact in the destination {@link BiConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the second fact in the destination {@link BiConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. - * @return never null */ - BiConstraintStream groupBy( - TriFunction groupKeyAMapping, TriFunction groupKeyBMapping); + @NonNull BiConstraintStream groupBy( + @NonNull TriFunction groupKeyAMapping, + @NonNull TriFunction groupKeyBMapping); /** * Combines the semantics of {@link #groupBy(TriFunction, TriFunction)} and {@link #groupBy(TriConstraintCollector)}. @@ -1014,9 +910,9 @@ BiConstraintStream groupBy( * and the third fact is the result of applying {@link TriConstraintCollector#finisher()} on all the tuples of the * original {@link UniConstraintStream} that belong to the group. * - * @param groupKeyAMapping never null, function to convert the original tuple into a first fact - * @param groupKeyBMapping never null, function to convert the original tuple into a second fact - * @param collector never null, the collector to perform the grouping operation with + * @param groupKeyAMapping function to convert the original tuple into a first fact + * @param groupKeyBMapping function to convert the original tuple into a second fact + * @param collector the collector to perform the grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the type of the first fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -1024,11 +920,11 @@ BiConstraintStream groupBy( * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the third fact in the destination {@link TriConstraintStream}'s tuple - * @return never null */ - TriConstraintStream groupBy( - TriFunction groupKeyAMapping, TriFunction groupKeyBMapping, - TriConstraintCollector collector); + @NonNull TriConstraintStream groupBy( + @NonNull TriFunction groupKeyAMapping, + @NonNull TriFunction groupKeyBMapping, + @NonNull TriConstraintCollector collector); /** * Combines the semantics of {@link #groupBy(TriFunction, TriFunction)} and {@link #groupBy(TriConstraintCollector)}. @@ -1038,11 +934,11 @@ TriConstraintStream the type of the first fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -1052,13 +948,13 @@ TriConstraintStream the type of the third fact in the destination {@link QuadConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream groupBy( - TriFunction groupKeyAMapping, TriFunction groupKeyBMapping, - TriConstraintCollector collectorC, - TriConstraintCollector collectorD); + @NonNull QuadConstraintStream groupBy( + @NonNull TriFunction groupKeyAMapping, + @NonNull TriFunction groupKeyBMapping, + @NonNull TriConstraintCollector collectorC, + @NonNull TriConstraintCollector collectorD); /** * Convert the {@link TriConstraintStream} to a {@link TriConstraintStream}, consisting of unique tuples with three @@ -1070,20 +966,20 @@ QuadConstraintStream groupBy( * The third fact is the return value of the third group key mapping function, applied on all incoming tuples with * the same first fact. * - * @param groupKeyAMapping never null, function to convert the original tuple into a first fact - * @param groupKeyBMapping never null, function to convert the original tuple into a second fact - * @param groupKeyCMapping never null, function to convert the original tuple into a third fact + * @param groupKeyAMapping function to convert the original tuple into a first fact + * @param groupKeyBMapping function to convert the original tuple into a second fact + * @param groupKeyCMapping function to convert the original tuple into a third fact * @param the type of the first fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the second fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the third fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. - * @return never null */ - TriConstraintStream groupBy( - TriFunction groupKeyAMapping, TriFunction groupKeyBMapping, - TriFunction groupKeyCMapping); + @NonNull TriConstraintStream groupBy( + @NonNull TriFunction groupKeyAMapping, + @NonNull TriFunction groupKeyBMapping, + @NonNull TriFunction groupKeyCMapping); /** * Combines the semantics of {@link #groupBy(TriFunction, TriFunction)} and {@link #groupBy(TriConstraintCollector)}. @@ -1091,10 +987,10 @@ TriConstraintStream the type of the first fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -1104,13 +1000,13 @@ TriConstraintStream the mutable accumulation type (often hidden as an implementation detail) * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream groupBy( - TriFunction groupKeyAMapping, TriFunction groupKeyBMapping, - TriFunction groupKeyCMapping, - TriConstraintCollector collectorD); + @NonNull QuadConstraintStream groupBy( + @NonNull TriFunction groupKeyAMapping, + @NonNull TriFunction groupKeyBMapping, + @NonNull TriFunction groupKeyCMapping, + @NonNull TriConstraintCollector collectorD); /** * Convert the {@link TriConstraintStream} to a {@link QuadConstraintStream}, consisting of unique tuples with four @@ -1124,10 +1020,10 @@ QuadConstraintStream groupBy( * The fourth fact is the return value of the fourth group key mapping function, applied on all incoming tuples with * the same first fact. * - * @param groupKeyAMapping never null, function to convert the original tuple into a first fact - * @param groupKeyBMapping never null, function to convert the original tuple into a second fact - * @param groupKeyCMapping never null, function to convert the original tuple into a third fact - * @param groupKeyDMapping never null, function to convert the original tuple into a fourth fact + * @param groupKeyAMapping function to convert the original tuple into a first fact + * @param groupKeyBMapping function to convert the original tuple into a second fact + * @param groupKeyCMapping function to convert the original tuple into a third fact + * @param groupKeyDMapping function to convert the original tuple into a fourth fact * @param the type of the first fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the second fact in the destination {@link QuadConstraintStream}'s tuple; @@ -1136,12 +1032,13 @@ QuadConstraintStream groupBy( * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. - * @return never null */ - QuadConstraintStream groupBy( - TriFunction groupKeyAMapping, TriFunction groupKeyBMapping, - TriFunction groupKeyCMapping, TriFunction groupKeyDMapping); + @NonNull QuadConstraintStream groupBy( + @NonNull TriFunction groupKeyAMapping, + @NonNull TriFunction groupKeyBMapping, + @NonNull TriFunction groupKeyCMapping, + @NonNull TriFunction groupKeyDMapping); // ************************************************************************ // Operations with duplicate tuple possibility @@ -1150,55 +1047,51 @@ QuadConstraintStream groupBy( /** * As defined by {@link UniConstraintStream#map(Function)}. * - * @param mapping never null, function to convert the original tuple into the new tuple + * @param mapping function to convert the original tuple into the new tuple * @param the type of the only fact in the resulting {@link UniConstraintStream}'s tuple - * @return never null */ - UniConstraintStream map(TriFunction mapping); + @NonNull UniConstraintStream map(@NonNull TriFunction mapping); /** * As defined by {@link #map(TriFunction)}, only resulting in {@link BiConstraintStream}. * - * @param mappingA never null, function to convert the original tuple into the first fact of a new tuple - * @param mappingB never null, function to convert the original tuple into the second fact of a new tuple + * @param mappingA function to convert the original tuple into the first fact of a new tuple + * @param mappingB function to convert the original tuple into the second fact of a new tuple * @param the type of the first fact in the resulting {@link BiConstraintStream}'s tuple * @param the type of the first fact in the resulting {@link BiConstraintStream}'s tuple - * @return never null */ - BiConstraintStream map(TriFunction mappingA, - TriFunction mappingB); + @NonNull BiConstraintStream map(@NonNull TriFunction mappingA, + @NonNull TriFunction mappingB); /** * As defined by {@link #map(TriFunction)}, only resulting in {@link TriConstraintStream}. * - * @param mappingA never null, function to convert the original tuple into the first fact of a new tuple - * @param mappingB never null, function to convert the original tuple into the second fact of a new tuple - * @param mappingC never null, function to convert the original tuple into the third fact of a new tuple + * @param mappingA function to convert the original tuple into the first fact of a new tuple + * @param mappingB function to convert the original tuple into the second fact of a new tuple + * @param mappingC function to convert the original tuple into the third fact of a new tuple * @param the type of the first fact in the resulting {@link TriConstraintStream}'s tuple * @param the type of the first fact in the resulting {@link TriConstraintStream}'s tuple * @param the type of the third fact in the resulting {@link TriConstraintStream}'s tuple - * @return never null */ - TriConstraintStream map( - TriFunction mappingA, TriFunction mappingB, - TriFunction mappingC); + @NonNull TriConstraintStream map( + @NonNull TriFunction mappingA, @NonNull TriFunction mappingB, + @NonNull TriFunction mappingC); /** * As defined by {@link #map(TriFunction)}, only resulting in {@link QuadConstraintStream}. * - * @param mappingA never null, function to convert the original tuple into the first fact of a new tuple - * @param mappingB never null, function to convert the original tuple into the second fact of a new tuple - * @param mappingC never null, function to convert the original tuple into the third fact of a new tuple - * @param mappingD never null, function to convert the original tuple into the fourth fact of a new tuple + * @param mappingA function to convert the original tuple into the first fact of a new tuple + * @param mappingB function to convert the original tuple into the second fact of a new tuple + * @param mappingC function to convert the original tuple into the third fact of a new tuple + * @param mappingD function to convert the original tuple into the fourth fact of a new tuple * @param the type of the first fact in the resulting {@link QuadConstraintStream}'s tuple * @param the type of the first fact in the resulting {@link QuadConstraintStream}'s tuple * @param the type of the third fact in the resulting {@link QuadConstraintStream}'s tuple * @param the type of the third fact in the resulting {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream map( - TriFunction mappingA, TriFunction mappingB, - TriFunction mappingC, TriFunction mappingD); + @NonNull QuadConstraintStream map( + @NonNull TriFunction mappingA, @NonNull TriFunction mappingB, + @NonNull TriFunction mappingC, @NonNull TriFunction mappingD); /** * As defined by {@link BiConstraintStream#flattenLast(Function)}. @@ -1207,11 +1100,10 @@ QuadConstraintStream TriConstraintStream flattenLast(Function> mapping); + @NonNull TriConstraintStream flattenLast(@NonNull Function> mapping); /** * Removes duplicate tuples from the stream, according to the tuple's facts @@ -1224,9 +1116,8 @@ QuadConstraintStream distinct(); /** @@ -1241,11 +1132,8 @@ QuadConstraintStream * This operation can be thought of as an or between streams. - * - * @param otherStream never null - * @return never null */ - default TriConstraintStream concat(UniConstraintStream otherStream) { + default @NonNull TriConstraintStream concat(@NonNull UniConstraintStream otherStream) { return concat(otherStream, uniConstantNull(), uniConstantNull()); } @@ -1262,13 +1150,12 @@ default TriConstraintStream concat(UniConstraintStream otherStream) *

    * This operation can be thought of as an or between streams. * - * @param otherStream never null - * @param paddingFunctionB never null, function to find the padding for the second fact - * @param paddingFunctionC never null, function to find the padding for the third fact - * @return never null + * @param paddingFunctionB function to find the padding for the second fact + * @param paddingFunctionC function to find the padding for the third fact */ - TriConstraintStream concat(UniConstraintStream otherStream, Function paddingFunctionB, - Function paddingFunctionC); + @NonNull + TriConstraintStream concat(@NonNull UniConstraintStream otherStream, @NonNull Function paddingFunctionB, + @NonNull Function paddingFunctionC); /** * Returns a new {@link TriConstraintStream} containing all the tuples of both this {@link TriConstraintStream} @@ -1282,11 +1169,8 @@ TriConstraintStream concat(UniConstraintStream otherStream, Function * {@code [(A1, A2, A3), (B1, B2, B3), (C1, C2, C3), (C1, C2, null), (D1, D2, null), (E1, E2, null)]}. *

    * This operation can be thought of as an or between streams. - * - * @param otherStream never null - * @return never null */ - default TriConstraintStream concat(BiConstraintStream otherStream) { + default @NonNull TriConstraintStream concat(@NonNull BiConstraintStream otherStream) { return concat(otherStream, biConstantNull()); } @@ -1303,11 +1187,11 @@ default TriConstraintStream concat(BiConstraintStream otherStream *

    * This operation can be thought of as an or between streams. * - * @param otherStream never null - * @param paddingFunctionC never null, function to find the padding for the third fact - * @return never null + * @param paddingFunctionC function to find the padding for the third fact */ - TriConstraintStream concat(BiConstraintStream otherStream, BiFunction paddingFunctionC); + @NonNull + TriConstraintStream concat(@NonNull BiConstraintStream otherStream, + @NonNull BiFunction paddingFunctionC); /** * Returns a new {@link TriConstraintStream} containing all the tuples of both this {@link TriConstraintStream} and the @@ -1322,10 +1206,9 @@ default TriConstraintStream concat(BiConstraintStream otherStream *

    * This operation can be thought of as an or between streams. * - * @param otherStream never null - * @return never null */ - TriConstraintStream concat(TriConstraintStream otherStream); + @NonNull + TriConstraintStream concat(@NonNull TriConstraintStream otherStream); /** * Returns a new {@link QuadConstraintStream} containing all the tuples of both this {@link TriConstraintStream} @@ -1339,11 +1222,8 @@ default TriConstraintStream concat(BiConstraintStream otherStream * {@code [(A1, A2, A3, null), (B1, B2, B3, null), (C1, C2, C3, null), (C1, C2, C3, C4), (D1, D2, D3, D4), (E1, E2, E3, E4)]}. *

    * This operation can be thought of as an or between streams. - * - * @param otherStream never null - * @return never null */ - default QuadConstraintStream concat(QuadConstraintStream otherStream) { + default @NonNull QuadConstraintStream concat(@NonNull QuadConstraintStream otherStream) { return concat(otherStream, triConstantNull()); } @@ -1361,12 +1241,10 @@ default QuadConstraintStream concat(QuadConstraintStream * This operation can be thought of as an or between streams. * - * @param otherStream never null - * @param paddingFunction never null, function to find the padding for the fourth fact - * @return never null + * @param paddingFunction function to find the padding for the fourth fact */ - QuadConstraintStream concat(QuadConstraintStream otherStream, - TriFunction paddingFunction); + @NonNull QuadConstraintStream concat(@NonNull QuadConstraintStream otherStream, + @NonNull TriFunction paddingFunction); // ************************************************************************ // expand @@ -1382,10 +1260,9 @@ QuadConstraintStream concat(QuadConstraintStream oth * coming from tuple creation. * * @param mapping function to produce the new fact from the original tuple - * @return never null * @param type of the final fact of the new tuple */ - QuadConstraintStream expand(TriFunction mapping); + @NonNull QuadConstraintStream expand(@NonNull TriFunction mapping); // ************************************************************************ // complement @@ -1395,7 +1272,7 @@ QuadConstraintStream concat(QuadConstraintStream oth * As defined by {@link #complement(Class, Function, Function)}, * where the padding function pads with null. */ - default TriConstraintStream complement(Class otherClass) { + default @NonNull TriConstraintStream complement(@NonNull Class otherClass) { return complement(otherClass, uniConstantNull(), uniConstantNull()); } @@ -1410,13 +1287,11 @@ default TriConstraintStream complement(Class otherClass) { * The rest of the tuple will be padded with the results of the padding functions, * applied on the new instance. * - * @param otherClass never null - * @param paddingFunctionB never null, function to find the padding for the second fact - * @param paddingFunctionC never null, function to find the padding for the third fact - * @return never null + * @param paddingFunctionB function to find the padding for the second fact + * @param paddingFunctionC function to find the padding for the third fact */ - default TriConstraintStream complement(Class otherClass, Function paddingFunctionB, - Function paddingFunctionC) { + default @NonNull TriConstraintStream complement(@NonNull Class otherClass, + @NonNull Function paddingFunctionB, @NonNull Function paddingFunctionC) { var firstStream = this; var remapped = firstStream.map(ConstantLambdaUtils.triPickFirst()); var secondStream = getConstraintFactory().forEach(otherClass) @@ -1430,28 +1305,27 @@ default TriConstraintStream complement(Class otherClass, Function> TriConstraintBuilder penalize(Score_ constraintWeight) { + default > @NonNull TriConstraintBuilder + penalize(@NonNull Score_ constraintWeight) { return penalize(constraintWeight, triConstantOne()); } /** * As defined by {@link #penalizeLong(Score, ToLongTriFunction)}, where the match weight is one (1). * - * @return never null */ - default > TriConstraintBuilder penalizeLong(Score_ constraintWeight) { + default > @NonNull TriConstraintBuilder + penalizeLong(@NonNull Score_ constraintWeight) { return penalizeLong(constraintWeight, triConstantOneLong()); } /** * As defined by {@link #penalizeBigDecimal(Score, TriFunction)}, where the match weight is one (1). * - * @return never null */ - default > TriConstraintBuilder penalizeBigDecimal(Score_ constraintWeight) { + default > @NonNull TriConstraintBuilder + penalizeBigDecimal(@NonNull Score_ constraintWeight) { return penalizeBigDecimal(constraintWeight, triConstantOneBigDecimal()); } @@ -1466,24 +1340,22 @@ default > TriConstraintBuilder pen * For non-int {@link Score} types use {@link #penalizeLong(Score, ToLongTriFunction)} or * {@link #penalizeBigDecimal(Score, TriFunction)} instead. * - * @param constraintWeight never null - * @param matchWeigher never null, the result of this function (matchWeight) is multiplied by the constraintWeight - * @return never null + * @param matchWeigher the result of this function (matchWeight) is multiplied by the constraintWeight */ - > TriConstraintBuilder penalize(Score_ constraintWeight, - ToIntTriFunction matchWeigher); + > @NonNull TriConstraintBuilder penalize(@NonNull Score_ constraintWeight, + @NonNull ToIntTriFunction matchWeigher); /** * As defined by {@link #penalize(Score, ToIntTriFunction)}, with a penalty of type long. */ - > TriConstraintBuilder penalizeLong(Score_ constraintWeight, - ToLongTriFunction matchWeigher); + > @NonNull TriConstraintBuilder penalizeLong(@NonNull Score_ constraintWeight, + @NonNull ToLongTriFunction matchWeigher); /** * As defined by {@link #penalize(Score, ToIntTriFunction)}, with a penalty of type {@link BigDecimal}. */ - > TriConstraintBuilder penalizeBigDecimal(Score_ constraintWeight, - TriFunction matchWeigher); + > @NonNull TriConstraintBuilder penalizeBigDecimal( + @NonNull Score_ constraintWeight, @NonNull TriFunction matchWeigher); /** * Negatively impacts the {@link Score}, @@ -1520,7 +1392,7 @@ > TriConstraintBuilder penalizeBig /** * As defined by {@link #penalizeConfigurable(ToIntTriFunction)}, with a penalty of type long. - * + * * @deprecated Prefer {@link #penalizeLong(Score, ToLongTriFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -1528,7 +1400,7 @@ > TriConstraintBuilder penalizeBig /** * As defined by {@link #penalizeConfigurable(ToIntTriFunction)}, with a penalty of type {@link BigDecimal}. - * + * * @deprecated Prefer {@link #penalizeBigDecimal(Score, TriFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -1536,10 +1408,9 @@ > TriConstraintBuilder penalizeBig /** * As defined by {@link #reward(Score, ToIntTriFunction)}, where the match weight is one (1). - * - * @return never null */ - default > TriConstraintBuilder reward(Score_ constraintWeight) { + default > @NonNull TriConstraintBuilder + reward(@NonNull Score_ constraintWeight) { return reward(constraintWeight, triConstantOne()); } @@ -1554,24 +1425,22 @@ default > TriConstraintBuilder rew * For non-int {@link Score} types use {@link #rewardLong(Score, ToLongTriFunction)} or * {@link #rewardBigDecimal(Score, TriFunction)} instead. * - * @param constraintWeight never null - * @param matchWeigher never null, the result of this function (matchWeight) is multiplied by the constraintWeight - * @return never null + * @param matchWeigher the result of this function (matchWeight) is multiplied by the constraintWeight */ - > TriConstraintBuilder reward(Score_ constraintWeight, - ToIntTriFunction matchWeigher); + > @NonNull TriConstraintBuilder reward(@NonNull Score_ constraintWeight, + @NonNull ToIntTriFunction matchWeigher); /** * As defined by {@link #reward(Score, ToIntTriFunction)}, with a penalty of type long. */ - > TriConstraintBuilder rewardLong(Score_ constraintWeight, - ToLongTriFunction matchWeigher); + > @NonNull TriConstraintBuilder rewardLong(@NonNull Score_ constraintWeight, + @NonNull ToLongTriFunction matchWeigher); /** * As defined by {@link #reward(Score, ToIntTriFunction)}, with a penalty of type {@link BigDecimal}. */ - > TriConstraintBuilder rewardBigDecimal(Score_ constraintWeight, - TriFunction matchWeigher); + > @NonNull TriConstraintBuilder rewardBigDecimal( + @NonNull Score_ constraintWeight, @NonNull TriFunction matchWeigher); /** * Positively impacts the {@link Score}, @@ -1608,7 +1477,7 @@ > TriConstraintBuilder rewardBigDe /** * As defined by {@link #rewardConfigurable(ToIntTriFunction)}, with a penalty of type long. - * + * * @deprecated Prefer {@link #rewardLong(Score, ToLongTriFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -1616,7 +1485,7 @@ > TriConstraintBuilder rewardBigDe /** * As defined by {@link #rewardConfigurable(ToIntTriFunction)}, with a penalty of type {@link BigDecimal}. - * + * * @deprecated Prefer {@link #rewardBigDecimal(Score, TriFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -1628,11 +1497,9 @@ > TriConstraintBuilder rewardBigDe *

    * Use {@code penalize(...)} or {@code reward(...)} instead, unless this constraint can both have positive and * negative weights. - * - * @param constraintWeight never null - * @return never null */ - default > TriConstraintBuilder impact(Score_ constraintWeight) { + default > @NonNull TriConstraintBuilder + impact(@NonNull Score_ constraintWeight) { return impact(constraintWeight, triConstantOne()); } @@ -1646,24 +1513,22 @@ default > TriConstraintBuilder imp * Use {@code penalize(...)} or {@code reward(...)} instead, unless this constraint can both have positive and * negative weights. * - * @param constraintWeight never null - * @param matchWeigher never null, the result of this function (matchWeight) is multiplied by the constraintWeight - * @return never null + * @param matchWeigher the result of this function (matchWeight) is multiplied by the constraintWeight */ - > TriConstraintBuilder impact(Score_ constraintWeight, - ToIntTriFunction matchWeigher); + > @NonNull TriConstraintBuilder impact(@NonNull Score_ constraintWeight, + @NonNull ToIntTriFunction matchWeigher); /** * As defined by {@link #impact(Score, ToIntTriFunction)}, with an impact of type long. */ - > TriConstraintBuilder impactLong(Score_ constraintWeight, - ToLongTriFunction matchWeigher); + > @NonNull TriConstraintBuilder impactLong(@NonNull Score_ constraintWeight, + @NonNull ToLongTriFunction matchWeigher); /** * As defined by {@link #impact(Score, ToIntTriFunction)}, with an impact of type {@link BigDecimal}. */ - > TriConstraintBuilder impactBigDecimal(Score_ constraintWeight, - TriFunction matchWeigher); + > @NonNull TriConstraintBuilder impactBigDecimal( + @NonNull Score_ constraintWeight, @NonNull TriFunction matchWeigher); /** * Positively impacts the {@link Score} by the {@link ConstraintWeight} for each match, @@ -1697,7 +1562,7 @@ > TriConstraintBuilder impactBigDe /** * As defined by {@link #impactConfigurable(ToIntTriFunction)}, with an impact of type long. - * + * * @deprecated Prefer {@link #impactLong(Score, ToLongTriFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -1705,7 +1570,7 @@ > TriConstraintBuilder impactBigDe /** * As defined by {@link #impactConfigurable(ToIntTriFunction)}, with an impact of type BigDecimal. - * + * * @deprecated Prefer {@link #impactBigDecimal(Score, TriFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriJoiner.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriJoiner.java index 8339c1608e..91161c551a 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriJoiner.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/tri/TriJoiner.java @@ -3,6 +3,8 @@ import ai.timefold.solver.core.api.score.stream.Joiners; import ai.timefold.solver.core.api.score.stream.bi.BiConstraintStream; +import org.jspecify.annotations.NonNull; + /** * Created with {@link Joiners}. * Used by {@link BiConstraintStream#join(Class, TriJoiner)}, ... @@ -11,6 +13,7 @@ */ public interface TriJoiner { - TriJoiner and(TriJoiner otherJoiner); + @NonNull + TriJoiner and(@NonNull TriJoiner otherJoiner); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/uni/UniConstraintBuilder.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/uni/UniConstraintBuilder.java index 4167745a6e..6cde633444 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/uni/UniConstraintBuilder.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/uni/UniConstraintBuilder.java @@ -12,6 +12,8 @@ import ai.timefold.solver.core.api.score.stream.ConstraintBuilder; import ai.timefold.solver.core.api.score.stream.ConstraintJustification; +import org.jspecify.annotations.NonNull; + /** * Used to build a {@link Constraint} out of a {@link UniConstraintStream}, applying optional configuration. * To build the constraint, use one of the terminal operations, such as {@link #asConstraint(String)}. @@ -29,21 +31,20 @@ public interface UniConstraintBuilder> extends C * That function must not return a {@link java.util.Collection}, * else {@link IllegalStateException} will be thrown during score calculation. * - * @see ConstraintMatch - * @param justificationMapping never null * @return this + * @see ConstraintMatch */ - UniConstraintBuilder justifyWith( - BiFunction justificationMapping); + @NonNull UniConstraintBuilder justifyWith( + @NonNull BiFunction justificationMapping); /** * Sets a custom function to mark any object returned by it as responsible for causing the constraint to match. * Each object in the collection returned by this function will become an {@link Indictment} * and be available as a key in {@link ScoreExplanation#getIndictmentMap()}. * - * @param indictedObjectsMapping never null * @return this */ - UniConstraintBuilder indictWith(Function> indictedObjectsMapping); + @NonNull + UniConstraintBuilder indictWith(@NonNull Function> indictedObjectsMapping); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/uni/UniConstraintCollector.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/uni/UniConstraintCollector.java index 9546d8aa74..121e59315f 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/uni/UniConstraintCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/uni/UniConstraintCollector.java @@ -8,6 +8,9 @@ import ai.timefold.solver.core.api.score.stream.ConstraintCollectors; import ai.timefold.solver.core.api.score.stream.ConstraintStream; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Usually created with {@link ConstraintCollectors}. * Used by {@link UniConstraintStream#groupBy(Function, UniConstraintCollector)}, ... @@ -34,9 +37,8 @@ public interface UniConstraintCollector { /** * A lambda that creates the result container, one for each group key combination. - * - * @return never null */ + @NonNull Supplier supplier(); /** @@ -44,8 +46,9 @@ public interface UniConstraintCollector { * accumulates it in the result container * and returns an undo operation for that accumulation. * - * @return never null, the undo operation. This lambda is called when the fact no longer matches. + * @return the undo operation. This lambda is called when the fact no longer matches. */ + @NonNull BiFunction accumulator(); /** @@ -53,6 +56,7 @@ public interface UniConstraintCollector { * * @return null when the result would be invalid, such as maximum value from an empty container. */ + @Nullable Function finisher(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/score/stream/uni/UniConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/api/score/stream/uni/UniConstraintStream.java index b29c8db2d2..9d31a52e14 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/score/stream/uni/UniConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/api/score/stream/uni/UniConstraintStream.java @@ -34,6 +34,8 @@ import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintStream; import ai.timefold.solver.core.api.score.stream.tri.TriConstraintStream; +import org.jspecify.annotations.NonNull; + /** * A {@link ConstraintStream} that matches one fact. * @@ -48,11 +50,9 @@ public interface UniConstraintStream extends ConstraintStream { /** * Exhaustively test each fact against the {@link Predicate} * and match if {@link Predicate#test(Object)} returns true. - * - * @param predicate never null - * @return never null */ - UniConstraintStream filter(Predicate predicate); + @NonNull + UniConstraintStream filter(@NonNull Predicate predicate); // ************************************************************************ // Join @@ -66,11 +66,10 @@ public interface UniConstraintStream extends ConstraintStream { * because it doesn't apply hashing and/or indexing on the properties, * so it creates and checks every combination of A and B. * - * @param otherStream never null * @param the type of the second matched fact - * @return never null, a stream that matches every combination of A and B + * @return a stream that matches every combination of A and B */ - default BiConstraintStream join(UniConstraintStream otherStream) { + default @NonNull BiConstraintStream join(@NonNull UniConstraintStream otherStream) { return join(otherStream, new BiJoiner[0]); } @@ -83,12 +82,11 @@ default BiConstraintStream join(UniConstraintStream otherStream) { * because it applies hashing and/or indexing on the properties, * so it doesn't create nor checks every combination of A and B. * - * @param otherStream never null - * @param joiner never null * @param the type of the second matched fact - * @return never null, a stream that matches every combination of A and B for which the {@link BiJoiner} is true + * @return a stream that matches every combination of A and B for which the {@link BiJoiner} is true */ - default BiConstraintStream join(UniConstraintStream otherStream, BiJoiner joiner) { + default @NonNull BiConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner joiner) { return join(otherStream, new BiJoiner[] { joiner }); } @@ -96,15 +94,13 @@ default BiConstraintStream join(UniConstraintStream otherStream, Bi * As defined by {@link #join(UniConstraintStream, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the second matched fact - * @return never null, a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} + * @return a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} * are true */ - default BiConstraintStream join(UniConstraintStream otherStream, BiJoiner joiner1, - BiJoiner joiner2) { + default @NonNull BiConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2) { return join(otherStream, new BiJoiner[] { joiner1, joiner2 }); } @@ -112,16 +108,13 @@ default BiConstraintStream join(UniConstraintStream otherStream, Bi * As defined by {@link #join(UniConstraintStream, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the second matched fact - * @return never null, a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} + * @return a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} * are true */ - default BiConstraintStream join(UniConstraintStream otherStream, BiJoiner joiner1, - BiJoiner joiner2, BiJoiner joiner3) { + default @NonNull BiConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3) { return join(otherStream, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -129,17 +122,13 @@ default BiConstraintStream join(UniConstraintStream otherStream, Bi * As defined by {@link #join(UniConstraintStream, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the second matched fact - * @return never null, a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} + * @return a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} * are true */ - default BiConstraintStream join(UniConstraintStream otherStream, BiJoiner joiner1, - BiJoiner joiner2, BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull BiConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3, @NonNull BiJoiner joiner4) { return join(otherStream, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -152,13 +141,10 @@ default BiConstraintStream join(UniConstraintStream otherStream, Bi * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link BiJoiner} parameters. * - * @param otherStream never null - * @param joiners never null * @param the type of the second matched fact - * @return never null, a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} - * are true + * @return a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} are true */ - BiConstraintStream join(UniConstraintStream otherStream, BiJoiner... joiners); + @NonNull BiConstraintStream join(@NonNull UniConstraintStream otherStream, @NonNull BiJoiner... joiners); /** * Create a new {@link BiConstraintStream} for every combination of A and B. @@ -180,11 +166,10 @@ default BiConstraintStream join(UniConstraintStream otherStream, Bi *

    * This method is syntactic sugar for {@link #join(UniConstraintStream)}. * - * @param otherClass never null * @param the type of the second matched fact - * @return never null, a stream that matches every combination of A and B + * @return a stream that matches every combination of A and B */ - default BiConstraintStream join(Class otherClass) { + default @NonNull BiConstraintStream join(@NonNull Class otherClass) { return join(otherClass, new BiJoiner[0]); } @@ -206,12 +191,10 @@ default BiConstraintStream join(Class otherClass) { *

    * This method has overloaded methods with multiple {@link BiJoiner} parameters. * - * @param otherClass never null - * @param joiner never null * @param the type of the second matched fact - * @return never null, a stream that matches every combination of A and B for which the {@link BiJoiner} is true + * @return a stream that matches every combination of A and B for which the {@link BiJoiner} is true */ - default BiConstraintStream join(Class otherClass, BiJoiner joiner) { + default @NonNull BiConstraintStream join(@NonNull Class otherClass, @NonNull BiJoiner joiner) { return join(otherClass, new BiJoiner[] { joiner }); } @@ -219,14 +202,12 @@ default BiConstraintStream join(Class otherClass, BiJoiner jo * As defined by {@link #join(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the second matched fact - * @return never null, a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} + * @return a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} * are true */ - default BiConstraintStream join(Class otherClass, BiJoiner joiner1, BiJoiner joiner2) { + default @NonNull BiConstraintStream join(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2) { return join(otherClass, new BiJoiner[] { joiner1, joiner2 }); } @@ -234,16 +215,12 @@ default BiConstraintStream join(Class otherClass, BiJoiner jo * As defined by {@link #join(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the second matched fact - * @return never null, a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} + * @return a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} * are true */ - default BiConstraintStream join(Class otherClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3) { + default @NonNull BiConstraintStream join(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3) { return join(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -251,17 +228,12 @@ default BiConstraintStream join(Class otherClass, BiJoiner jo * As defined by {@link #join(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the second matched fact - * @return never null, a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} + * @return a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} * are true */ - default BiConstraintStream join(Class otherClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull BiConstraintStream join(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3, @NonNull BiJoiner joiner4) { return join(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -273,13 +245,10 @@ default BiConstraintStream join(Class otherClass, BiJoiner jo * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link BiJoiner} parameters. * - * @param otherClass never null - * @param joiners never null * @param the type of the second matched fact - * @return never null, a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} - * are true + * @return a stream that matches every combination of A and B for which all the {@link BiJoiner joiners} are true */ - BiConstraintStream join(Class otherClass, BiJoiner... joiners); + @NonNull BiConstraintStream join(@NonNull Class otherClass, @NonNull BiJoiner... joiners); // ************************************************************************ // If (not) exists @@ -296,12 +265,10 @@ default BiConstraintStream join(Class otherClass, BiJoiner jo * a different definition of exists applies. * (See {@link ConstraintFactory#from(Class)} Javadoc.) * - * @param otherClass never null - * @param joiner never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which the {@link BiJoiner} is true + * @return a stream that matches every A where B exists for which the {@link BiJoiner} is true */ - default UniConstraintStream ifExists(Class otherClass, BiJoiner joiner) { + default @NonNull UniConstraintStream ifExists(@NonNull Class otherClass, @NonNull BiJoiner joiner) { return ifExists(otherClass, new BiJoiner[] { joiner }); } @@ -309,13 +276,11 @@ default UniConstraintStream ifExists(Class otherClass, BiJoiner * As defined by {@link #ifExists(Class, BiJoiner)}. For performance reasons, indexing joiners must be placed before * filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which all the {@link BiJoiner}s are true + * @return a stream that matches every A where B exists for which all the {@link BiJoiner}s are true */ - default UniConstraintStream ifExists(Class otherClass, BiJoiner joiner1, BiJoiner joiner2) { + default @NonNull UniConstraintStream ifExists(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2) { return ifExists(otherClass, new BiJoiner[] { joiner1, joiner2 }); } @@ -323,15 +288,11 @@ default UniConstraintStream ifExists(Class otherClass, BiJoiner * As defined by {@link #ifExists(Class, BiJoiner)}. For performance reasons, indexing joiners must be placed before * filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which all the {@link BiJoiner}s are true + * @return a stream that matches every A where B exists for which all the {@link BiJoiner}s are true */ - default UniConstraintStream ifExists(Class otherClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3) { + default @NonNull UniConstraintStream ifExists(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3) { return ifExists(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -339,16 +300,11 @@ default UniConstraintStream ifExists(Class otherClass, BiJoiner * As defined by {@link #ifExists(Class, BiJoiner)}. For performance reasons, indexing joiners must be placed before * filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which all the {@link BiJoiner}s are true + * @return a stream that matches every A where B exists for which all the {@link BiJoiner}s are true */ - default UniConstraintStream ifExists(Class otherClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull UniConstraintStream ifExists(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3, @NonNull BiJoiner joiner4) { return ifExists(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -360,12 +316,10 @@ default UniConstraintStream ifExists(Class otherClass, BiJoiner * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link BiJoiner} parameters. * - * @param otherClass never null - * @param joiners never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which all the {@link BiJoiner}s are true + * @return a stream that matches every A where B exists for which all the {@link BiJoiner}s are true */ - UniConstraintStream ifExists(Class otherClass, BiJoiner... joiners); + @NonNull UniConstraintStream ifExists(@NonNull Class otherClass, @NonNull BiJoiner... joiners); /** * Create a new {@link UniConstraintStream} for every A where B exists for which the {@link BiJoiner} is true @@ -373,12 +327,11 @@ default UniConstraintStream ifExists(Class otherClass, BiJoiner *

    * This method has overloaded methods with multiple {@link BiJoiner} parameters. * - * @param otherStream never null - * @param joiner never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which the {@link BiJoiner} is true + * @return a stream that matches every A where B exists for which the {@link BiJoiner} is true */ - default UniConstraintStream ifExists(UniConstraintStream otherStream, BiJoiner joiner) { + default @NonNull UniConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner joiner) { return ifExists(otherStream, new BiJoiner[] { joiner }); } @@ -386,14 +339,12 @@ default UniConstraintStream ifExists(UniConstraintStream otherStream, * As defined by {@link #ifExists(UniConstraintStream, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which all the {@link BiJoiner}s are true + * @return a stream that matches every A where B exists for which all the {@link BiJoiner}s are true */ - default UniConstraintStream ifExists(UniConstraintStream otherStream, BiJoiner joiner1, - BiJoiner joiner2) { + default @NonNull UniConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2) { return ifExists(otherStream, new BiJoiner[] { joiner1, joiner2 }); } @@ -401,15 +352,11 @@ default UniConstraintStream ifExists(UniConstraintStream otherStream, * As defined by {@link #ifExists(UniConstraintStream, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which all the {@link BiJoiner}s are true + * @return a stream that matches every A where B exists for which all the {@link BiJoiner}s are true */ - default UniConstraintStream ifExists(UniConstraintStream otherStream, BiJoiner joiner1, - BiJoiner joiner2, BiJoiner joiner3) { + default @NonNull UniConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3) { return ifExists(otherStream, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -417,16 +364,12 @@ default UniConstraintStream ifExists(UniConstraintStream otherStream, * As defined by {@link #ifExists(UniConstraintStream, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which all the {@link BiJoiner}s are true + * @return a stream that matches every A where B exists for which all the {@link BiJoiner}s are true */ - default UniConstraintStream ifExists(UniConstraintStream otherStream, BiJoiner joiner1, - BiJoiner joiner2, BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull UniConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3, + @NonNull BiJoiner joiner4) { return ifExists(otherStream, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -438,12 +381,11 @@ default UniConstraintStream ifExists(UniConstraintStream otherStream, * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link BiJoiner} parameters. * - * @param otherStream never null - * @param joiners never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which all the {@link BiJoiner}s are true + * @return a stream that matches every A where B exists for which all the {@link BiJoiner}s are true */ - UniConstraintStream ifExists(UniConstraintStream otherStream, BiJoiner... joiners); + @NonNull UniConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner... joiners); /** * Create a new {@link UniConstraintStream} for every A where B exists for which the {@link BiJoiner} is true @@ -454,12 +396,11 @@ default UniConstraintStream ifExists(UniConstraintStream otherStream, *

    * This method has overloaded methods with multiple {@link BiJoiner} parameters. * - * @param otherClass never null - * @param joiner never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which the {@link BiJoiner} is true + * @return a stream that matches every A where B exists for which the {@link BiJoiner} is true */ - default UniConstraintStream ifExistsIncludingUnassigned(Class otherClass, BiJoiner joiner) { + default @NonNull UniConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner) { return ifExistsIncludingUnassigned(otherClass, new BiJoiner[] { joiner }); } @@ -467,14 +408,11 @@ default UniConstraintStream ifExistsIncludingUnassigned(Class otherCla * As defined by {@link #ifExistsIncludingUnassigned(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which all the {@link BiJoiner}s are true + * @return a stream that matches every A where B exists for which all the {@link BiJoiner}s are true */ - default UniConstraintStream ifExistsIncludingUnassigned(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2) { + default @NonNull UniConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2) { return ifExistsIncludingUnassigned(otherClass, new BiJoiner[] { joiner1, joiner2 }); } @@ -482,16 +420,11 @@ default UniConstraintStream ifExistsIncludingUnassigned(Class otherCla * As defined by {@link #ifExistsIncludingUnassigned(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which all the {@link BiJoiner}s are true + * @return a stream that matches every A where B exists for which all the {@link BiJoiner}s are true */ - default UniConstraintStream ifExistsIncludingUnassigned(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2, - BiJoiner joiner3) { + default @NonNull UniConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3) { return ifExistsIncludingUnassigned(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -499,17 +432,12 @@ default UniConstraintStream ifExistsIncludingUnassigned(Class otherCla * As defined by {@link #ifExistsIncludingUnassigned(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which all the {@link BiJoiner}s are true + * @return a stream that matches every A where B exists for which all the {@link BiJoiner}s are true */ - default UniConstraintStream ifExistsIncludingUnassigned(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2, - BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull UniConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, + @NonNull BiJoiner joiner3, @NonNull BiJoiner joiner4) { return ifExistsIncludingUnassigned(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -521,12 +449,11 @@ default UniConstraintStream ifExistsIncludingUnassigned(Class otherCla * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link BiJoiner} parameters. * - * @param otherClass never null - * @param joiners never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B exists for which all the {@link BiJoiner}s are true + * @return a stream that matches every A where B exists for which all the {@link BiJoiner}s are true */ - UniConstraintStream ifExistsIncludingUnassigned(Class otherClass, BiJoiner... joiners); + @NonNull UniConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner... joiners); /** * Create a new {@link UniConstraintStream} for every A, if another A exists that does not {@link Object#equals(Object)} @@ -537,10 +464,9 @@ default UniConstraintStream ifExistsIncludingUnassigned(Class otherCla * a different definition of exists applies. * (See {@link ConstraintFactory#from(Class)} Javadoc.) * - * @param otherClass never null - * @return never null, a stream that matches every A where a different A exists + * @return a stream that matches every A where a different A exists */ - default UniConstraintStream ifExistsOther(Class otherClass) { + default @NonNull UniConstraintStream ifExistsOther(@NonNull Class otherClass) { return ifExists(otherClass, Joiners.filtering(notEquals())); } @@ -555,12 +481,10 @@ default UniConstraintStream ifExistsOther(Class otherClass) { * a different definition of exists applies. * (See {@link ConstraintFactory#from(Class)} Javadoc.) * - * @param otherClass never null - * @param joiner never null - * @return never null, a stream that matches every A where a different A exists for which the {@link BiJoiner} is + * @return a stream that matches every A where a different A exists for which the {@link BiJoiner} is * true */ - default UniConstraintStream ifExistsOther(Class otherClass, BiJoiner joiner) { + default @NonNull UniConstraintStream ifExistsOther(@NonNull Class otherClass, @NonNull BiJoiner joiner) { return ifExistsOther(otherClass, new BiJoiner[] { joiner }); } @@ -568,13 +492,11 @@ default UniConstraintStream ifExistsOther(Class otherClass, BiJoiner * As defined by {@link #ifExistsOther(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @return never null, a stream that matches every A where a different A exists for which all the {@link BiJoiner}s + * @return a stream that matches every A where a different A exists for which all the {@link BiJoiner}s * are true */ - default UniConstraintStream ifExistsOther(Class otherClass, BiJoiner joiner1, BiJoiner joiner2) { + default @NonNull UniConstraintStream ifExistsOther(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2) { return ifExistsOther(otherClass, new BiJoiner[] { joiner1, joiner2 }); } @@ -582,15 +504,12 @@ default UniConstraintStream ifExistsOther(Class otherClass, BiJoiner * As defined by {@link #ifExistsOther(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @return never null, a stream that matches every A where a different A exists for which all the {@link BiJoiner}s + * @return a stream that matches every A where a different A exists for which all the {@link BiJoiner}s * are true */ - default UniConstraintStream ifExistsOther(Class otherClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3) { + default @NonNull UniConstraintStream ifExistsOther(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, + @NonNull BiJoiner joiner3) { return ifExistsOther(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -598,16 +517,12 @@ default UniConstraintStream ifExistsOther(Class otherClass, BiJoiner * As defined by {@link #ifExistsOther(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null - * @return never null, a stream that matches every A where a different A exists for which all the {@link BiJoiner}s + * @return a stream that matches every A where a different A exists for which all the {@link BiJoiner}s * are true */ - default UniConstraintStream ifExistsOther(Class otherClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull UniConstraintStream ifExistsOther(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, + @NonNull BiJoiner joiner3, @NonNull BiJoiner joiner4) { return ifExistsOther(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -619,12 +534,10 @@ default UniConstraintStream ifExistsOther(Class otherClass, BiJoiner * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link BiJoiner} parameters. * - * @param otherClass never null - * @param joiners never null - * @return never null, a stream that matches every A where a different A exists for which all the {@link BiJoiner}s + * @return a stream that matches every A where a different A exists for which all the {@link BiJoiner}s * are true */ - default UniConstraintStream ifExistsOther(Class otherClass, BiJoiner... joiners) { + default @NonNull UniConstraintStream ifExistsOther(@NonNull Class otherClass, @NonNull BiJoiner... joiners) { BiJoiner otherness = Joiners.filtering(notEquals()); @SuppressWarnings("unchecked") @@ -640,10 +553,9 @@ default UniConstraintStream ifExistsOther(Class otherClass, BiJoiner * this method also includes entities with null variables, * or entities that are not assigned to any list variable. * - * @param otherClass never null - * @return never null, a stream that matches every A where a different A exists + * @return a stream that matches every A where a different A exists */ - default UniConstraintStream ifExistsOtherIncludingUnassigned(Class otherClass) { + default @NonNull UniConstraintStream ifExistsOtherIncludingUnassigned(@NonNull Class otherClass) { return ifExistsOtherIncludingUnassigned(otherClass, new BiJoiner[0]); } @@ -657,12 +569,11 @@ default UniConstraintStream ifExistsOtherIncludingUnassigned(Class otherCl *

    * This method has overloaded methods with multiple {@link BiJoiner} parameters. * - * @param otherClass never null - * @param joiner never null - * @return never null, a stream that matches every A where a different A exists for which the {@link BiJoiner} is + * @return a stream that matches every A where a different A exists for which the {@link BiJoiner} is * true */ - default UniConstraintStream ifExistsOtherIncludingUnassigned(Class otherClass, BiJoiner joiner) { + default @NonNull UniConstraintStream ifExistsOtherIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner) { return ifExistsOtherIncludingUnassigned(otherClass, new BiJoiner[] { joiner }); } @@ -670,14 +581,11 @@ default UniConstraintStream ifExistsOtherIncludingUnassigned(Class otherCl * As defined by {@link #ifExistsOtherIncludingUnassigned(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @return never null, a stream that matches every A where a different A exists for which all the {@link BiJoiner}s + * @return a stream that matches every A where a different A exists for which all the {@link BiJoiner}s * are true */ - default UniConstraintStream ifExistsOtherIncludingUnassigned(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2) { + default @NonNull UniConstraintStream ifExistsOtherIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2) { return ifExistsOtherIncludingUnassigned(otherClass, new BiJoiner[] { joiner1, joiner2 }); } @@ -685,15 +593,11 @@ default UniConstraintStream ifExistsOtherIncludingUnassigned(Class otherCl * As defined by {@link #ifExistsOtherIncludingUnassigned(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @return never null, a stream that matches every A where a different A exists for which all the {@link BiJoiner}s + * @return a stream that matches every A where a different A exists for which all the {@link BiJoiner}s * are true */ - default UniConstraintStream ifExistsOtherIncludingUnassigned(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2, BiJoiner joiner3) { + default @NonNull UniConstraintStream ifExistsOtherIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3) { return ifExistsOtherIncludingUnassigned(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -701,16 +605,12 @@ default UniConstraintStream ifExistsOtherIncludingUnassigned(Class otherCl * As defined by {@link #ifExistsOtherIncludingUnassigned(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null - * @return never null, a stream that matches every A where a different A exists for which all the {@link BiJoiner}s + * @return a stream that matches every A where a different A exists for which all the {@link BiJoiner}s * are true */ - default UniConstraintStream ifExistsOtherIncludingUnassigned(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2, BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull UniConstraintStream ifExistsOtherIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3, + @NonNull BiJoiner joiner4) { return ifExistsOtherIncludingUnassigned(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -723,12 +623,11 @@ default UniConstraintStream ifExistsOtherIncludingUnassigned(Class otherCl * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link BiJoiner} parameters. * - * @param otherClass never null - * @param joiners never null - * @return never null, a stream that matches every A where a different A exists for which all the {@link BiJoiner}s + * @return a stream that matches every A where a different A exists for which all the {@link BiJoiner}s * are true */ - default UniConstraintStream ifExistsOtherIncludingUnassigned(Class otherClass, BiJoiner... joiners) { + default @NonNull UniConstraintStream ifExistsOtherIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner... joiners) { BiJoiner otherness = Joiners.filtering(notEquals()); @SuppressWarnings("unchecked") @@ -748,12 +647,10 @@ default UniConstraintStream ifExistsOtherIncludingUnassigned(Class otherCl * a different definition of exists applies. * (See {@link ConstraintFactory#from(Class)} Javadoc.) * - * @param otherClass never null - * @param joiner never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which the {@link BiJoiner} is true + * @return a stream that matches every A where B does not exist for which the {@link BiJoiner} is true */ - default UniConstraintStream ifNotExists(Class otherClass, BiJoiner joiner) { + default @NonNull UniConstraintStream ifNotExists(@NonNull Class otherClass, @NonNull BiJoiner joiner) { return ifNotExists(otherClass, new BiJoiner[] { joiner }); } @@ -761,15 +658,12 @@ default UniConstraintStream ifNotExists(Class otherClass, BiJoiner the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are + * @return a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are * true */ - default UniConstraintStream ifNotExists(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2) { + default @NonNull UniConstraintStream ifNotExists(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2) { return ifNotExists(otherClass, new BiJoiner[] { joiner1, joiner2 }); } @@ -777,16 +671,12 @@ default UniConstraintStream ifNotExists(Class otherClass, BiJoiner the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are + * @return a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are * true */ - default UniConstraintStream ifNotExists(Class otherClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3) { + default @NonNull UniConstraintStream ifNotExists(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3) { return ifNotExists(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -794,17 +684,12 @@ default UniConstraintStream ifNotExists(Class otherClass, BiJoiner the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are + * @return a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are * true */ - default UniConstraintStream ifNotExists(Class otherClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull UniConstraintStream ifNotExists(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3, @NonNull BiJoiner joiner4) { return ifNotExists(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -816,13 +701,10 @@ default UniConstraintStream ifNotExists(Class otherClass, BiJoiner the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are - * true + * @return a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are true */ - UniConstraintStream ifNotExists(Class otherClass, BiJoiner... joiners); + @NonNull UniConstraintStream ifNotExists(@NonNull Class otherClass, @NonNull BiJoiner... joiners); /** * Create a new {@link UniConstraintStream} for every A where B does not exist for which the {@link BiJoiner} is @@ -830,12 +712,11 @@ default UniConstraintStream ifNotExists(Class otherClass, BiJoiner * This method has overloaded methods with multiple {@link BiJoiner} parameters. * - * @param otherStream never null - * @param joiner never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which the {@link BiJoiner} is true + * @return a stream that matches every A where B does not exist for which the {@link BiJoiner} is true */ - default UniConstraintStream ifNotExists(UniConstraintStream otherStream, BiJoiner joiner) { + default @NonNull UniConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner joiner) { return ifNotExists(otherStream, new BiJoiner[] { joiner }); } @@ -843,15 +724,11 @@ default UniConstraintStream ifNotExists(UniConstraintStream otherStrea * As defined by {@link #ifNotExists(UniConstraintStream, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are - * true + * @return a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are true */ - default UniConstraintStream ifNotExists(UniConstraintStream otherStream, BiJoiner joiner1, - BiJoiner joiner2) { + default @NonNull UniConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2) { return ifNotExists(otherStream, new BiJoiner[] { joiner1, joiner2 }); } @@ -859,16 +736,12 @@ default UniConstraintStream ifNotExists(UniConstraintStream otherStrea * As defined by {@link #ifNotExists(UniConstraintStream, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are + * @return a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are * true */ - default UniConstraintStream ifNotExists(UniConstraintStream otherStream, BiJoiner joiner1, - BiJoiner joiner2, BiJoiner joiner3) { + default @NonNull UniConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3) { return ifNotExists(otherStream, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -876,17 +749,13 @@ default UniConstraintStream ifNotExists(UniConstraintStream otherStrea * As defined by {@link #ifNotExists(UniConstraintStream, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherStream never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the second matched fact * @return never null, a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are * true */ - default UniConstraintStream ifNotExists(UniConstraintStream otherStream, BiJoiner joiner1, - BiJoiner joiner2, BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull UniConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3, + @NonNull BiJoiner joiner4) { return ifNotExists(otherStream, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -904,7 +773,8 @@ default UniConstraintStream ifNotExists(UniConstraintStream otherStrea * @return never null, a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are * true */ - UniConstraintStream ifNotExists(UniConstraintStream otherStream, BiJoiner... joiners); + @NonNull UniConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner... joiners); /** * Create a new {@link UniConstraintStream} for every A where B does not exist for which the {@link BiJoiner} is @@ -915,12 +785,11 @@ default UniConstraintStream ifNotExists(UniConstraintStream otherStrea *

    * This method has overloaded methods with multiple {@link BiJoiner} parameters. * - * @param otherClass never null - * @param joiner never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which the {@link BiJoiner} is true + * @return a stream that matches every A where B does not exist for which the {@link BiJoiner} is true */ - default UniConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, BiJoiner joiner) { + default @NonNull UniConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner) { return ifNotExistsIncludingUnassigned(otherClass, new BiJoiner[] { joiner }); } @@ -928,15 +797,13 @@ default UniConstraintStream ifNotExistsIncludingUnassigned(Class other * As defined by {@link #ifNotExistsIncludingUnassigned(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are + * @return a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are * true */ - default UniConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2) { + default @NonNull UniConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2) { return ifNotExistsIncludingUnassigned(otherClass, new BiJoiner[] { joiner1, joiner2 }); } @@ -944,16 +811,13 @@ default UniConstraintStream ifNotExistsIncludingUnassigned(Class other * As defined by {@link #ifNotExistsIncludingUnassigned(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are + * @return a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are * true */ - default UniConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2, BiJoiner joiner3) { + default @NonNull UniConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3) { return ifNotExistsIncludingUnassigned(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -961,17 +825,13 @@ default UniConstraintStream ifNotExistsIncludingUnassigned(Class other * As defined by {@link #ifNotExistsIncludingUnassigned(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are + * @return a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are * true */ - default UniConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2, BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull UniConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3, + @NonNull BiJoiner joiner4) { return ifNotExistsIncludingUnassigned(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -983,13 +843,12 @@ default UniConstraintStream ifNotExistsIncludingUnassigned(Class other * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link BiJoiner} parameters. * - * @param otherClass never null - * @param joiners never null * @param the type of the second matched fact - * @return never null, a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are + * @return a stream that matches every A where B does not exist for which all the {@link BiJoiner}s are * true */ - UniConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, BiJoiner... joiners); + @NonNull UniConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner... joiners); /** * Create a new {@link UniConstraintStream} for every A, if no other A exists that does not {@link Object#equals(Object)} @@ -1000,10 +859,9 @@ default UniConstraintStream ifNotExistsIncludingUnassigned(Class other * a different definition of exists applies. * (See {@link ConstraintFactory#from(Class)} Javadoc.) * - * @param otherClass never null - * @return never null, a stream that matches every A where a different A does not exist + * @return a stream that matches every A where a different A does not exist */ - default UniConstraintStream ifNotExistsOther(Class otherClass) { + default @NonNull UniConstraintStream ifNotExistsOther(@NonNull Class otherClass) { return ifNotExists(otherClass, Joiners.filtering(notEquals())); } @@ -1018,12 +876,10 @@ default UniConstraintStream ifNotExistsOther(Class otherClass) { * a different definition of exists applies. * (See {@link ConstraintFactory#from(Class)} Javadoc.) * - * @param otherClass never null - * @param joiner never null - * @return never null, a stream that matches every A where a different A does not exist for which the + * @return a stream that matches every A where a different A does not exist for which the * {@link BiJoiner} is true */ - default UniConstraintStream ifNotExistsOther(Class otherClass, BiJoiner joiner) { + default @NonNull UniConstraintStream ifNotExistsOther(@NonNull Class otherClass, @NonNull BiJoiner joiner) { return ifNotExistsOther(otherClass, new BiJoiner[] { joiner }); } @@ -1031,14 +887,11 @@ default UniConstraintStream ifNotExistsOther(Class otherClass, BiJoiner ifNotExistsOther(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2) { + default @NonNull UniConstraintStream ifNotExistsOther(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2) { return ifNotExistsOther(otherClass, new BiJoiner[] { joiner1, joiner2 }); } @@ -1046,15 +899,11 @@ default UniConstraintStream ifNotExistsOther(Class otherClass, BiJoiner ifNotExistsOther(Class otherClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3) { + default @NonNull UniConstraintStream ifNotExistsOther(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3) { return ifNotExistsOther(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -1062,16 +911,11 @@ default UniConstraintStream ifNotExistsOther(Class otherClass, BiJoiner ifNotExistsOther(Class otherClass, BiJoiner joiner1, BiJoiner joiner2, - BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull UniConstraintStream ifNotExistsOther(@NonNull Class otherClass, @NonNull BiJoiner joiner1, + @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3, @NonNull BiJoiner joiner4) { return ifNotExistsOther(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -1083,12 +927,10 @@ default UniConstraintStream ifNotExistsOther(Class otherClass, BiJoiner ifNotExistsOther(Class otherClass, BiJoiner... joiners) { + default @NonNull UniConstraintStream ifNotExistsOther(@NonNull Class otherClass, @NonNull BiJoiner... joiners) { BiJoiner otherness = Joiners.filtering(notEquals()); @SuppressWarnings("unchecked") @@ -1104,10 +946,9 @@ default UniConstraintStream ifNotExistsOther(Class otherClass, BiJoiner ifNotExistsOtherIncludingUnassigned(Class otherClass) { + default @NonNull UniConstraintStream ifNotExistsOtherIncludingUnassigned(@NonNull Class otherClass) { return ifNotExistsOtherIncludingUnassigned(otherClass, new BiJoiner[0]); } @@ -1121,12 +962,11 @@ default UniConstraintStream ifNotExistsOtherIncludingUnassigned(Class othe *

    * This method has overloaded methods with multiple {@link BiJoiner} parameters. * - * @param otherClass never null - * @param joiner never null - * @return never null, a stream that matches every A where a different A does not exist for which the + * @return a stream that matches every A where a different A does not exist for which the * {@link BiJoiner} is true */ - default UniConstraintStream ifNotExistsOtherIncludingUnassigned(Class otherClass, BiJoiner joiner) { + default @NonNull UniConstraintStream ifNotExistsOtherIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner) { return ifNotExistsOtherIncludingUnassigned(otherClass, new BiJoiner[] { joiner }); } @@ -1134,14 +974,11 @@ default UniConstraintStream ifNotExistsOtherIncludingUnassigned(Class othe * As defined by {@link #ifNotExistsOtherIncludingUnassigned(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @return never null, a stream that matches every A where a different A does not exist for which all the + * @return a stream that matches every A where a different A does not exist for which all the * {@link BiJoiner}s are true */ - default UniConstraintStream ifNotExistsOtherIncludingUnassigned(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2) { + default @NonNull UniConstraintStream ifNotExistsOtherIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2) { return ifNotExistsOtherIncludingUnassigned(otherClass, new BiJoiner[] { joiner1, joiner2 }); } @@ -1149,15 +986,11 @@ default UniConstraintStream ifNotExistsOtherIncludingUnassigned(Class othe * As defined by {@link #ifNotExistsOtherIncludingUnassigned(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @return never null, a stream that matches every A where a different A does not exist for which all the + * @return a stream that matches every A where a different A does not exist for which all the * {@link BiJoiner}s are true */ - default UniConstraintStream ifNotExistsOtherIncludingUnassigned(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2, BiJoiner joiner3) { + default @NonNull UniConstraintStream ifNotExistsOtherIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3) { return ifNotExistsOtherIncludingUnassigned(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3 }); } @@ -1165,16 +998,12 @@ default UniConstraintStream ifNotExistsOtherIncludingUnassigned(Class othe * As defined by {@link #ifNotExistsOtherIncludingUnassigned(Class, BiJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null - * @return never null, a stream that matches every A where a different A does not exist for which all the + * @return a stream that matches every A where a different A does not exist for which all the * {@link BiJoiner}s are true */ - default UniConstraintStream ifNotExistsOtherIncludingUnassigned(Class otherClass, BiJoiner joiner1, - BiJoiner joiner2, BiJoiner joiner3, BiJoiner joiner4) { + default @NonNull UniConstraintStream ifNotExistsOtherIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner joiner1, @NonNull BiJoiner joiner2, @NonNull BiJoiner joiner3, + @NonNull BiJoiner joiner4) { return ifNotExistsOtherIncludingUnassigned(otherClass, new BiJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -1187,12 +1016,11 @@ default UniConstraintStream ifNotExistsOtherIncludingUnassigned(Class othe * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link BiJoiner} parameters. * - * @param otherClass never null - * @param joiners never null - * @return never null, a stream that matches every A where a different A does not exist for which all the + * @return a stream that matches every A where a different A does not exist for which all the * {@link BiJoiner}s are true */ - default UniConstraintStream ifNotExistsOtherIncludingUnassigned(Class otherClass, BiJoiner... joiners) { + default @NonNull UniConstraintStream ifNotExistsOtherIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner... joiners) { BiJoiner otherness = Joiners.filtering(notEquals()); @SuppressWarnings("unchecked") @@ -1256,46 +1084,46 @@ default UniConstraintStream ifNotExistsOtherIncludingNullVars(Class otherC // Group by // ************************************************************************ + // TODO: Continue here + /** * Convert the {@link UniConstraintStream} to a different {@link UniConstraintStream}, containing only a single * tuple, the result of applying {@link UniConstraintCollector}. * - * @param collector never null, the collector to perform the grouping operation with + * @param collector the collector to perform the grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of a fact in the destination {@link UniConstraintStream}'s tuple - * @return never null */ - UniConstraintStream groupBy( - UniConstraintCollector collector); + @NonNull UniConstraintStream groupBy( + @NonNull UniConstraintCollector collector); /** * Convert the {@link UniConstraintStream} to a {@link BiConstraintStream}, containing only a single tuple, * the result of applying two {@link UniConstraintCollector}s. * - * @param collectorA never null, the collector to perform the first grouping operation with + * @param collectorA the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorB never null, the collector to perform the second grouping operation with + * @param collectorB the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the first fact in the destination {@link BiConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the second fact in the destination {@link BiConstraintStream}'s tuple - * @return never null */ - BiConstraintStream groupBy( - UniConstraintCollector collectorA, - UniConstraintCollector collectorB); + @NonNull BiConstraintStream groupBy( + @NonNull UniConstraintCollector collectorA, + @NonNull UniConstraintCollector collectorB); /** * Convert the {@link UniConstraintStream} to a {@link TriConstraintStream}, containing only a single tuple, * the result of applying three {@link UniConstraintCollector}s. * - * @param collectorA never null, the collector to perform the first grouping operation with + * @param collectorA the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorB never null, the collector to perform the second grouping operation with + * @param collectorB the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorC never null, the collector to perform the third grouping operation with + * @param collectorC the collector to perform the third grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the first fact in the destination {@link TriConstraintStream}'s tuple @@ -1303,25 +1131,24 @@ BiConstraintStream the type of the second fact in the destination {@link TriConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the third fact in the destination {@link TriConstraintStream}'s tuple - * @return never null */ - TriConstraintStream groupBy( - UniConstraintCollector collectorA, - UniConstraintCollector collectorB, - UniConstraintCollector collectorC); + @NonNull TriConstraintStream groupBy( + @NonNull UniConstraintCollector collectorA, + @NonNull UniConstraintCollector collectorB, + @NonNull UniConstraintCollector collectorC); /** * Convert the {@link UniConstraintStream} to a {@link QuadConstraintStream}, containing only a single tuple, * the result of applying four {@link UniConstraintCollector}s. * - * @param collectorA never null, the collector to perform the first grouping operation with + * @param collectorA the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorB never null, the collector to perform the second grouping operation with + * @param collectorB the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorC never null, the collector to perform the third grouping operation with + * @param collectorC the collector to perform the third grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorD never null, the collector to perform the fourth grouping operation with + * @param collectorD the collector to perform the fourth grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the first fact in the destination {@link QuadConstraintStream}'s tuple @@ -1331,26 +1158,24 @@ TriConstraintStream groupBy( * @param the type of the third fact in the destination {@link QuadConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream groupBy( - UniConstraintCollector collectorA, - UniConstraintCollector collectorB, - UniConstraintCollector collectorC, - UniConstraintCollector collectorD); + @NonNull QuadConstraintStream groupBy( + @NonNull UniConstraintCollector collectorA, + @NonNull UniConstraintCollector collectorB, + @NonNull UniConstraintCollector collectorC, + @NonNull UniConstraintCollector collectorD); /** * Convert the {@link UniConstraintStream} to a different {@link UniConstraintStream}, containing the set of tuples * resulting from applying the group key mapping function on all tuples of the original stream. * Neither tuple of the new stream {@link Objects#equals(Object, Object)} any other. * - * @param groupKeyMapping never null, mapping function to convert each element in the stream to a different element + * @param groupKeyMapping mapping function to convert each element in the stream to a different element * @param the type of a fact in the destination {@link UniConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. - * @return never null */ - UniConstraintStream groupBy(Function groupKeyMapping); + @NonNull UniConstraintStream groupBy(@NonNull Function groupKeyMapping); /** * Convert the {@link UniConstraintStream} to a {@link BiConstraintStream}, consisting of unique tuples with two @@ -1360,18 +1185,17 @@ QuadConstraintStream groupBy( * The second fact is the return value of a given {@link UniConstraintCollector} applied on all incoming tuples with * the same first fact. * - * @param groupKeyMapping never null, function to convert the fact in the original tuple to a different fact - * @param collector never null, the collector to perform the grouping operation with + * @param groupKeyMapping function to convert the fact in the original tuple to a different fact + * @param collector the collector to perform the grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the type of the first fact in the destination {@link BiConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the second fact in the destination {@link BiConstraintStream}'s tuple - * @return never null */ - BiConstraintStream groupBy( - Function groupKeyMapping, - UniConstraintCollector collector); + @NonNull BiConstraintStream groupBy( + @NonNull Function groupKeyMapping, + @NonNull UniConstraintCollector collector); /** * Convert the {@link UniConstraintStream} to a {@link TriConstraintStream}, consisting of unique tuples with three @@ -1381,10 +1205,10 @@ BiConstraintStream gr * The remaining facts are the return value of the respective {@link UniConstraintCollector} applied on all * incoming tuples with the same first fact. * - * @param groupKeyMapping never null, function to convert the fact in the original tuple to a different fact - * @param collectorB never null, the collector to perform the first grouping operation with + * @param groupKeyMapping function to convert the fact in the original tuple to a different fact + * @param collectorB the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorC never null, the collector to perform the second grouping operation with + * @param collectorC the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the type of the first fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -1392,12 +1216,12 @@ BiConstraintStream gr * @param the type of the second fact in the destination {@link TriConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the third fact in the destination {@link TriConstraintStream}'s tuple - * @return never null */ - TriConstraintStream groupBy( - Function groupKeyMapping, UniConstraintCollector collectorB, - UniConstraintCollector collectorC); + @NonNull TriConstraintStream groupBy( + @NonNull Function groupKeyMapping, + @NonNull UniConstraintCollector collectorB, + @NonNull UniConstraintCollector collectorC); /** * Convert the {@link UniConstraintStream} to a {@link QuadConstraintStream}, consisting of unique tuples with four @@ -1407,12 +1231,12 @@ TriConstraintStream groupBy( * The remaining facts are the return value of the respective {@link UniConstraintCollector} applied on all * incoming tuples with the same first fact. * - * @param groupKeyMapping never null, function to convert the fact in the original tuple to a different fact - * @param collectorB never null, the collector to perform the first grouping operation with + * @param groupKeyMapping function to convert the fact in the original tuple to a different fact + * @param collectorB the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorC never null, the collector to perform the second grouping operation with + * @param collectorC the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorD never null, the collector to perform the third grouping operation with + * @param collectorD the collector to perform the third grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the type of the first fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -1422,13 +1246,13 @@ TriConstraintStream groupBy( * @param the type of the third fact in the destination {@link QuadConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream groupBy( - Function groupKeyMapping, UniConstraintCollector collectorB, - UniConstraintCollector collectorC, - UniConstraintCollector collectorD); + @NonNull QuadConstraintStream groupBy( + @NonNull Function groupKeyMapping, + @NonNull UniConstraintCollector collectorB, + @NonNull UniConstraintCollector collectorC, + @NonNull UniConstraintCollector collectorD); /** * Convert the {@link UniConstraintStream} to a {@link BiConstraintStream}, consisting of unique tuples with two @@ -1438,16 +1262,15 @@ QuadConstraintStream groupBy( * The second fact is the return value of the second group key mapping function, applied on all incoming tuples with * the same first fact. * - * @param groupKeyAMapping never null, function to convert the original tuple into a first fact - * @param groupKeyBMapping never null, function to convert the original tuple into a second fact + * @param groupKeyAMapping function to convert the original tuple into a first fact + * @param groupKeyBMapping function to convert the original tuple into a second fact * @param the type of the first fact in the destination {@link BiConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the second fact in the destination {@link BiConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. - * @return never null */ - BiConstraintStream groupBy( - Function groupKeyAMapping, Function groupKeyBMapping); + @NonNull BiConstraintStream groupBy( + @NonNull Function groupKeyAMapping, @NonNull Function groupKeyBMapping); /** * Combines the semantics of {@link #groupBy(Function, Function)} and {@link #groupBy(UniConstraintCollector)}. @@ -1455,9 +1278,9 @@ BiConstraintStream groupBy( * the third fact is the result of applying {@link UniConstraintCollector#finisher()} on all the tuples of the * original {@link UniConstraintStream} that belong to the group. * - * @param groupKeyAMapping never null, function to convert the original tuple into a first fact - * @param groupKeyBMapping never null, function to convert the original tuple into a second fact - * @param collector never null, the collector to perform the grouping operation with + * @param groupKeyAMapping function to convert the original tuple into a first fact + * @param groupKeyBMapping function to convert the original tuple into a second fact + * @param collector the collector to perform the grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the type of the first fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -1465,11 +1288,10 @@ BiConstraintStream groupBy( * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the third fact in the destination {@link TriConstraintStream}'s tuple - * @return never null */ - TriConstraintStream groupBy( - Function groupKeyAMapping, Function groupKeyBMapping, - UniConstraintCollector collector); + @NonNull TriConstraintStream groupBy( + @NonNull Function groupKeyAMapping, @NonNull Function groupKeyBMapping, + @NonNull UniConstraintCollector collector); /** * Combines the semantics of {@link #groupBy(Function, Function)} and {@link #groupBy(UniConstraintCollector)}. @@ -1479,11 +1301,11 @@ TriConstraintStream the type of the first fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -1493,13 +1315,12 @@ TriConstraintStream the type of the third fact in the destination {@link QuadConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream groupBy( - Function groupKeyAMapping, Function groupKeyBMapping, - UniConstraintCollector collectorC, - UniConstraintCollector collectorD); + @NonNull QuadConstraintStream groupBy( + @NonNull Function groupKeyAMapping, @NonNull Function groupKeyBMapping, + @NonNull UniConstraintCollector collectorC, + @NonNull UniConstraintCollector collectorD); /** * Convert the {@link UniConstraintStream} to a {@link TriConstraintStream}, consisting of unique tuples with three @@ -1511,20 +1332,19 @@ QuadConstraintStream groupBy( * The third fact is the return value of the third group key mapping function, applied on all incoming tuples with * the same first fact. * - * @param groupKeyAMapping never null, function to convert the original tuple into a first fact - * @param groupKeyBMapping never null, function to convert the original tuple into a second fact - * @param groupKeyCMapping never null, function to convert the original tuple into a third fact + * @param groupKeyAMapping function to convert the original tuple into a first fact + * @param groupKeyBMapping function to convert the original tuple into a second fact + * @param groupKeyCMapping function to convert the original tuple into a third fact * @param the type of the first fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the second fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the third fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. - * @return never null */ - TriConstraintStream groupBy( - Function groupKeyAMapping, Function groupKeyBMapping, - Function groupKeyCMapping); + @NonNull TriConstraintStream groupBy( + @NonNull Function groupKeyAMapping, @NonNull Function groupKeyBMapping, + @NonNull Function groupKeyCMapping); /** * Combines the semantics of {@link #groupBy(Function, Function)} and {@link #groupBy(UniConstraintCollector)}. @@ -1532,10 +1352,10 @@ TriConstraintStream the type of the first fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -1545,13 +1365,12 @@ TriConstraintStream the mutable accumulation type (often hidden as an implementation detail) * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream groupBy( - Function groupKeyAMapping, Function groupKeyBMapping, - Function groupKeyCMapping, - UniConstraintCollector collectorD); + @NonNull QuadConstraintStream groupBy( + @NonNull Function groupKeyAMapping, @NonNull Function groupKeyBMapping, + @NonNull Function groupKeyCMapping, + @NonNull UniConstraintCollector collectorD); /** * Convert the {@link UniConstraintStream} to a {@link QuadConstraintStream}, consisting of unique tuples with four @@ -1567,9 +1386,9 @@ QuadConstraintStream groupBy( * * @param groupKeyAMapping * calling {@code map(Person::getAge)} on such stream will produce a stream of {@link Integer}s * * {@code [20, 25, 30]}, - * @param groupKeyBMapping never null, function to convert the original tuple into a second fact - * @param groupKeyCMapping never null, function to convert the original tuple into a third fact - * @param groupKeyDMapping never null, function to convert the original tuple into a fourth fact + * @param groupKeyBMapping function to convert the original tuple into a second fact + * @param groupKeyCMapping function to convert the original tuple into a third fact + * @param groupKeyDMapping function to convert the original tuple into a fourth fact * @param the type of the first fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the second fact in the destination {@link QuadConstraintStream}'s tuple; @@ -1578,12 +1397,11 @@ QuadConstraintStream groupBy( * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. - * @return never null */ - QuadConstraintStream groupBy( - Function groupKeyAMapping, Function groupKeyBMapping, - Function groupKeyCMapping, Function groupKeyDMapping); + @NonNull QuadConstraintStream groupBy( + @NonNull Function groupKeyAMapping, @NonNull Function groupKeyBMapping, + @NonNull Function groupKeyCMapping, @NonNull Function groupKeyDMapping); // ************************************************************************ // Operations with duplicate tuple possibility @@ -1629,54 +1447,52 @@ QuadConstraintStream groupBy( * Use with caution, * as the increased memory allocation rates coming from tuple creation may negatively affect performance. * - * @param mapping never null, function to convert the original tuple into the new tuple + * @param mapping function to convert the original tuple into the new tuple * @param the type of the only fact in the resulting {@link UniConstraintStream}'s tuple - * @return never null */ - UniConstraintStream map(Function mapping); + @NonNull UniConstraintStream map(@NonNull Function mapping); /** * As defined by {@link #map(Function)}, only resulting in {@link BiConstraintStream}. * - * @param mappingA never null, function to convert the original tuple into the first fact of a new tuple - * @param mappingB never null, function to convert the original tuple into the second fact of a new tuple + * @param mappingA function to convert the original tuple into the first fact of a new tuple + * @param mappingB function to convert the original tuple into the second fact of a new tuple * @param the type of the first fact in the resulting {@link BiConstraintStream}'s tuple * @param the type of the first fact in the resulting {@link BiConstraintStream}'s tuple - * @return never null */ - BiConstraintStream map(Function mappingA, - Function mappingB); + @NonNull BiConstraintStream map(@NonNull Function mappingA, + @NonNull Function mappingB); /** * As defined by {@link #map(Function)}, only resulting in {@link TriConstraintStream}. * - * @param mappingA never null, function to convert the original tuple into the first fact of a new tuple - * @param mappingB never null, function to convert the original tuple into the second fact of a new tuple - * @param mappingC never null, function to convert the original tuple into the third fact of a new tuple + * @param mappingA function to convert the original tuple into the first fact of a new tuple + * @param mappingB function to convert the original tuple into the second fact of a new tuple + * @param mappingC function to convert the original tuple into the third fact of a new tuple * @param the type of the first fact in the resulting {@link TriConstraintStream}'s tuple * @param the type of the first fact in the resulting {@link TriConstraintStream}'s tuple * @param the type of the third fact in the resulting {@link TriConstraintStream}'s tuple - * @return never null */ - TriConstraintStream map(Function mappingA, - Function mappingB, Function mappingC); + @NonNull TriConstraintStream map( + @NonNull Function mappingA, + @NonNull Function mappingB, @NonNull Function mappingC); /** * As defined by {@link #map(Function)}, only resulting in {@link QuadConstraintStream}. * - * @param mappingA never null, function to convert the original tuple into the first fact of a new tuple - * @param mappingB never null, function to convert the original tuple into the second fact of a new tuple - * @param mappingC never null, function to convert the original tuple into the third fact of a new tuple - * @param mappingD never null, function to convert the original tuple into the fourth fact of a new tuple + * @param mappingA function to convert the original tuple into the first fact of a new tuple + * @param mappingB function to convert the original tuple into the second fact of a new tuple + * @param mappingC function to convert the original tuple into the third fact of a new tuple + * @param mappingD function to convert the original tuple into the fourth fact of a new tuple * @param the type of the first fact in the resulting {@link QuadConstraintStream}'s tuple * @param the type of the first fact in the resulting {@link QuadConstraintStream}'s tuple * @param the type of the third fact in the resulting {@link QuadConstraintStream}'s tuple * @param the type of the third fact in the resulting {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream map( - Function mappingA, Function mappingB, Function mappingC, - Function mappingD); + @NonNull QuadConstraintStream map( + @NonNull Function mappingA, @NonNull Function mappingB, + @NonNull Function mappingC, + @NonNull Function mappingD); /** * Takes each tuple and applies a mapping on it, which turns the tuple into a {@link Iterable}. @@ -1694,15 +1510,14 @@ QuadConstraintStream the type of facts in the resulting tuples. * It is recommended that this type be deeply immutable. * Not following this recommendation may lead to hard-to-debug hashing issues down the stream, * especially if this value is ever used as a group key. - * @return never null */ - UniConstraintStream flattenLast(Function> mapping); + @NonNull UniConstraintStream flattenLast(@NonNull Function> mapping); /** * Transforms the stream in such a way that all the tuples going through it are distinct. @@ -1713,9 +1528,8 @@ QuadConstraintStream distinct(); /** @@ -1729,11 +1543,9 @@ QuadConstraintStream concat(UniConstraintStream otherStream); + @NonNull + UniConstraintStream concat(@NonNull UniConstraintStream otherStream); /** * Returns a new {@link BiConstraintStream} containing all the tuples of both this {@link UniConstraintStream} @@ -1747,11 +1559,8 @@ QuadConstraintStream * This operation can be thought of as an or between streams. - * - * @param otherStream never null - * @return never null */ - default BiConstraintStream concat(BiConstraintStream otherStream) { + default @NonNull BiConstraintStream concat(@NonNull BiConstraintStream otherStream) { return concat(otherStream, uniConstantNull()); } @@ -1768,11 +1577,10 @@ default BiConstraintStream concat(BiConstraintStream otherStream *

    * This operation can be thought of as an or between streams. * - * @param otherStream never null - * @param paddingFunctionB never null, function to find the padding for the second fact - * @return never null + * @param paddingFunctionB function to find the padding for the second fact */ - BiConstraintStream concat(BiConstraintStream otherStream, Function paddingFunctionB); + @NonNull BiConstraintStream concat(@NonNull BiConstraintStream otherStream, + @NonNull Function paddingFunctionB); /** * Returns a new {@link TriConstraintStream} containing all the tuples of both this {@link UniConstraintStream} @@ -1786,11 +1594,8 @@ default BiConstraintStream concat(BiConstraintStream otherStream * {@code [(A, null), (B, null), (C, null), (C1, C2, C3), (D1, D2, D3), (E1, E2, E3)]}. *

    * This operation can be thought of as an or between streams. - * - * @param otherStream never null - * @return never null */ - default TriConstraintStream concat(TriConstraintStream otherStream) { + default @NonNull TriConstraintStream concat(@NonNull TriConstraintStream otherStream) { return concat(otherStream, uniConstantNull(), uniConstantNull()); } @@ -1807,13 +1612,12 @@ default TriConstraintStream concat(TriConstraintStream *

    * This operation can be thought of as an or between streams. * - * @param otherStream never null - * @param paddingFunctionB never null, function to find the padding for the second fact - * @param paddingFunctionC never null, function to find the padding for the third fact - * @return never null + * @param paddingFunctionB function to find the padding for the second fact + * @param paddingFunctionC function to find the padding for the third fact */ - TriConstraintStream concat(TriConstraintStream otherStream, Function paddingFunctionB, - Function paddingFunctionC); + @NonNull TriConstraintStream concat(@NonNull TriConstraintStream otherStream, + @NonNull Function paddingFunctionB, + @NonNull Function paddingFunctionC); /** * Returns a new {@link QuadConstraintStream} containing all the tuples of both this {@link UniConstraintStream} @@ -1827,11 +1631,8 @@ TriConstraintStream concat(TriConstraintStream otherStr * {@code [(A, null), (B, null), (C, null), (C1, C2, C3, C4), (D1, D2, D3, D4), (E1, E2, E3, E4)]}. *

    * This operation can be thought of as an or between streams. - * - * @param otherStream never null - * @return never null */ - default QuadConstraintStream concat(QuadConstraintStream otherStream) { + default @NonNull QuadConstraintStream concat(@NonNull QuadConstraintStream otherStream) { return concat(otherStream, uniConstantNull(), uniConstantNull(), uniConstantNull()); } @@ -1848,14 +1649,13 @@ default QuadConstraintStream concat(QuadConstraintStream * This operation can be thought of as an or between streams. * - * @param otherStream never null - * @param paddingFunctionB never null, function to find the padding for the second fact - * @param paddingFunctionC never null, function to find the padding for the third fact - * @param paddingFunctionD never null, function to find the padding for the fourth fact - * @return never null + * @param paddingFunctionB function to find the padding for the second fact + * @param paddingFunctionC function to find the padding for the third fact + * @param paddingFunctionD function to find the padding for the fourth fact */ - QuadConstraintStream concat(QuadConstraintStream otherStream, - Function paddingFunctionB, Function paddingFunctionC, Function paddingFunctionD); + @NonNull QuadConstraintStream concat(@NonNull QuadConstraintStream otherStream, + @NonNull Function paddingFunctionB, @NonNull Function paddingFunctionC, + @NonNull Function paddingFunctionD); // ************************************************************************ // expand @@ -1873,10 +1673,9 @@ QuadConstraintStream concat(QuadConstraintStream type of the final fact of the new tuple */ - BiConstraintStream expand(Function mapping); + @NonNull BiConstraintStream expand(@NonNull Function mapping); /** * Adds two facts to the end of the tuple, increasing the cardinality of the stream. @@ -1891,12 +1690,11 @@ QuadConstraintStream concat(QuadConstraintStream type of the second fact of the new tuple * @param type of the third fact of the new tuple */ - TriConstraintStream expand(Function mappingB, - Function mappingC); + @NonNull TriConstraintStream expand(@NonNull Function mappingB, + @NonNull Function mappingC); /** * Adds three facts to the end of the tuple, increasing the cardinality of the stream. @@ -1910,13 +1708,13 @@ TriConstraintStream expand(Function< * @param mappingB function to produce the new second fact from the original tuple * @param mappingC function to produce the new third fact from the original tuple * @param mappingD function to produce the new final fact from the original tuple - * @return never null * @param type of the second fact of the new tuple * @param type of the third fact of the new tuple * @param type of the final fact of the new tuple */ - QuadConstraintStream expand(Function mappingB, - Function mappingC, Function mappingD); + @NonNull QuadConstraintStream expand( + @NonNull Function mappingB, + @NonNull Function mappingC, @NonNull Function mappingD); // ************************************************************************ // complement @@ -1926,11 +1724,8 @@ QuadConstraintStream complement(Class otherClass) { + default @NonNull UniConstraintStream complement(@NonNull Class otherClass) { var firstStream = this; var secondStream = getConstraintFactory().forEach(otherClass) .ifNotExists(firstStream, Joiners.equal()); @@ -1944,27 +1739,26 @@ default UniConstraintStream complement(Class otherClass) { /** * As defined by {@link #penalize(Score, ToIntFunction)}, where the match weight is one (1). * - * @return never null */ - default > UniConstraintBuilder penalize(Score_ constraintWeight) { + default > @NonNull UniConstraintBuilder penalize(@NonNull Score_ constraintWeight) { return penalize(constraintWeight, uniConstantOne()); } /** * As defined by {@link #penalizeLong(Score, ToLongFunction)}, where the match weight is one (1). * - * @return never null */ - default > UniConstraintBuilder penalizeLong(Score_ constraintWeight) { + default > @NonNull UniConstraintBuilder + penalizeLong(@NonNull Score_ constraintWeight) { return penalizeLong(constraintWeight, uniConstantOneLong()); } /** * As defined by {@link #penalizeBigDecimal(Score, Function)}, where the match weight is one (1). * - * @return never null */ - default > UniConstraintBuilder penalizeBigDecimal(Score_ constraintWeight) { + default > @NonNull UniConstraintBuilder + penalizeBigDecimal(@NonNull Score_ constraintWeight) { return penalizeBigDecimal(constraintWeight, uniConstantOneBigDecimal()); } @@ -1979,24 +1773,22 @@ default > UniConstraintBuilder penalizeB * For non-int {@link Score} types use {@link #penalizeLong(Score, ToLongFunction)} or * {@link #penalizeBigDecimal(Score, Function)} instead. * - * @param constraintWeight never null - * @param matchWeigher never null, the result of this function (matchWeight) is multiplied by the constraintWeight - * @return never null + * @param matchWeigher the result of this function (matchWeight) is multiplied by the constraintWeight */ - > UniConstraintBuilder penalize(Score_ constraintWeight, - ToIntFunction matchWeigher); + > @NonNull UniConstraintBuilder penalize(@NonNull Score_ constraintWeight, + @NonNull ToIntFunction matchWeigher); /** * As defined by {@link #penalize(Score, ToIntFunction)}, with a penalty of type long. */ - > UniConstraintBuilder penalizeLong(Score_ constraintWeight, - ToLongFunction matchWeigher); + > @NonNull UniConstraintBuilder penalizeLong(@NonNull Score_ constraintWeight, + @NonNull ToLongFunction matchWeigher); /** * As defined by {@link #penalize(Score, ToIntFunction)}, with a penalty of type {@link BigDecimal}. */ - > UniConstraintBuilder penalizeBigDecimal(Score_ constraintWeight, - Function matchWeigher); + > @NonNull UniConstraintBuilder penalizeBigDecimal(@NonNull Score_ constraintWeight, + @NonNull Function matchWeigher); /** * Negatively impacts the {@link Score}, @@ -2034,7 +1826,7 @@ > UniConstraintBuilder penalizeBigDecima /** * As defined by {@link #penalizeConfigurable(ToIntFunction)}, with a penalty of type long. *

    - * + * * @deprecated Prefer {@link #penalizeLong(Score, ToLongFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -2043,7 +1835,7 @@ > UniConstraintBuilder penalizeBigDecima /** * As defined by {@link #penalizeConfigurable(ToIntFunction)}, with a penalty of type {@link BigDecimal}. *

    - * + * * @deprecated Prefer {@link #penalizeBigDecimal(Score, Function)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") @@ -2051,10 +1843,8 @@ > UniConstraintBuilder penalizeBigDecima /** * As defined by {@link #reward(Score, ToIntFunction)}, where the match weight is one (1). - * - * @return never null */ - default > UniConstraintBuilder reward(Score_ constraintWeight) { + default > @NonNull UniConstraintBuilder reward(@NonNull Score_ constraintWeight) { return reward(constraintWeight, uniConstantOne()); } @@ -2069,24 +1859,24 @@ default > UniConstraintBuilder reward(Sc * For non-int {@link Score} types use {@link #rewardLong(Score, ToLongFunction)} or * {@link #rewardBigDecimal(Score, Function)} instead. * - * @param constraintWeight never null - * @param matchWeigher never null, the result of this function (matchWeight) is multiplied by the constraintWeight - * @return never null + * @param matchWeigher the result of this function (matchWeight) is multiplied by the constraintWeight */ - > UniConstraintBuilder reward(Score_ constraintWeight, - ToIntFunction matchWeigher); + > @NonNull UniConstraintBuilder reward(@NonNull Score_ constraintWeight, + @NonNull ToIntFunction matchWeigher); /** * As defined by {@link #reward(Score, ToIntFunction)}, with a penalty of type long. */ - > UniConstraintBuilder rewardLong(Score_ constraintWeight, - ToLongFunction matchWeigher); + @NonNull + > UniConstraintBuilder rewardLong(@NonNull Score_ constraintWeight, + @NonNull ToLongFunction matchWeigher); /** * As defined by {@link #reward(Score, ToIntFunction)}, with a penalty of type {@link BigDecimal}. */ - > UniConstraintBuilder rewardBigDecimal(Score_ constraintWeight, - Function matchWeigher); + @NonNull + > UniConstraintBuilder rewardBigDecimal(@NonNull Score_ constraintWeight, + @NonNull Function matchWeigher); /** * Positively impacts the {@link Score}, @@ -2143,11 +1933,8 @@ > UniConstraintBuilder rewardBigDecimal( *

    * Use {@code penalize(...)} or {@code reward(...)} instead, unless this constraint can both have positive and * negative weights. - * - * @param constraintWeight never null - * @return never null */ - default > UniConstraintBuilder impact(Score_ constraintWeight) { + default > @NonNull UniConstraintBuilder impact(@NonNull Score_ constraintWeight) { return impact(constraintWeight, uniConstantOne()); } @@ -2161,24 +1948,22 @@ default > UniConstraintBuilder impact(Sc * Use {@code penalize(...)} or {@code reward(...)} instead, unless this constraint can both have positive and * negative weights. * - * @param constraintWeight never null - * @param matchWeigher never null, the result of this function (matchWeight) is multiplied by the constraintWeight - * @return never null + * @param matchWeigher the result of this function (matchWeight) is multiplied by the constraintWeight */ - > UniConstraintBuilder impact(Score_ constraintWeight, - ToIntFunction matchWeigher); + > @NonNull UniConstraintBuilder impact(@NonNull Score_ constraintWeight, + @NonNull ToIntFunction matchWeigher); /** * As defined by {@link #impact(Score, ToIntFunction)}, with an impact of type long. */ - > UniConstraintBuilder impactLong(Score_ constraintWeight, - ToLongFunction matchWeigher); + > @NonNull UniConstraintBuilder impactLong(@NonNull Score_ constraintWeight, + @NonNull ToLongFunction matchWeigher); /** * As defined by {@link #impact(Score, ToIntFunction)}, with an impact of type {@link BigDecimal}. */ - > UniConstraintBuilder impactBigDecimal(Score_ constraintWeight, - Function matchWeigher); + > @NonNull UniConstraintBuilder impactBigDecimal(@NonNull Score_ constraintWeight, + @NonNull Function matchWeigher); /** * Positively impacts the {@link Score} by the {@link ConstraintWeight} for each match, @@ -2212,7 +1997,7 @@ > UniConstraintBuilder impactBigDecimal( /** * As defined by {@link #impactConfigurable(ToIntFunction)}, with an impact of type long. - * + * * @deprecated Prefer {@link #impactLong(Score, ToLongFunction)} and {@link ConstraintWeightOverrides}. */ @Deprecated(forRemoval = true, since = "1.13.0") diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/ProblemFactChange.java b/core/src/main/java/ai/timefold/solver/core/api/solver/ProblemFactChange.java index c2db0b118d..210ad8fb6c 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/ProblemFactChange.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/ProblemFactChange.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.api.score.director.ScoreDirector; import ai.timefold.solver.core.api.solver.change.ProblemChange; +import org.jspecify.annotations.NonNull; + /** * This interface is deprecated. * A ProblemFactChange represents a change in 1 or more problem facts of a {@link PlanningSolution}. @@ -29,11 +31,11 @@ public interface ProblemFactChange { * Every modification to the {@link PlanningSolution}, must be correctly notified to the {@link ScoreDirector}, * otherwise the {@link Score} calculation will be corrupted. * - * @param scoreDirector never null + * @param scoreDirector * Contains the {@link PlanningSolution working solution} which contains the problem facts * (and {@link PlanningEntity planning entities}) to change. * Also needs to get notified of those changes. */ - void doChange(ScoreDirector scoreDirector); + void doChange(@NonNull ScoreDirector scoreDirector); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/ProblemSizeStatistics.java b/core/src/main/java/ai/timefold/solver/core/api/solver/ProblemSizeStatistics.java index 5794f8567f..213e113ff6 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/ProblemSizeStatistics.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/ProblemSizeStatistics.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.impl.util.MathUtils; +import org.jspecify.annotations.NonNull; + /** * The statistics of a given problem submitted to a {@link Solver}. * @@ -65,12 +67,9 @@ String approximateProblemScaleAsFormattedString(Locale locale) { * we cannot expect them to be in the locale that the test expects them to be in. * This method exists to allow for an override. * - * @param number never null - * @param decimalFormat never null - * @param locale never null * @return the given decimalFormat with the given locale */ - private static String format(double number, DecimalFormat decimalFormat, Locale locale) { + private static @NonNull String format(double number, @NonNull DecimalFormat decimalFormat, @NonNull Locale locale) { if (locale.equals(FORMATTER_LOCALE)) { return decimalFormat.format(number); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/RecommendedAssignment.java b/core/src/main/java/ai/timefold/solver/core/api/solver/RecommendedAssignment.java index 0c0d396342..cf611acb38 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/RecommendedAssignment.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/RecommendedAssignment.java @@ -7,6 +7,9 @@ import ai.timefold.solver.core.api.score.analysis.MatchAnalysis; import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Represents the result of the Assignment Recommendation API, * see {@link SolutionManager#recommendFit(Object, Object, Function)}. @@ -31,6 +34,7 @@ public interface RecommendedAssignment scoreAnalysisDiff(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/SolutionManager.java b/core/src/main/java/ai/timefold/solver/core/api/solver/SolutionManager.java index 8f75b71cf1..52a15e05c4 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/SolutionManager.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/SolutionManager.java @@ -17,6 +17,9 @@ import ai.timefold.solver.core.api.score.constraint.Indictment; import ai.timefold.solver.core.impl.solver.DefaultSolutionManager; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * A stateless service to help calculate {@link Score}, {@link ConstraintMatchTotal}, * {@link Indictment}, etc. @@ -37,27 +40,23 @@ public interface SolutionManager> { /** * Uses a {@link SolverFactory} to build a {@link SolutionManager}. * - * @param solverFactory never null - * @return never null * @param the solution type, the class with the {@link PlanningSolution} annotation * @param the actual score type */ - static > SolutionManager create( - SolverFactory solverFactory) { + static > @NonNull SolutionManager create( + @NonNull SolverFactory solverFactory) { return new DefaultSolutionManager<>(solverFactory); } /** * Uses a {@link SolverManager} to build a {@link SolutionManager}. * - * @param solverManager never null - * @return never null * @param the solution type, the class with the {@link PlanningSolution} annotation * @param the actual score type * @param the ID type of a submitted problem, such as {@link Long} or {@link UUID} */ - static , ProblemId_> SolutionManager create( - SolverManager solverManager) { + static , ProblemId_> @NonNull SolutionManager create( + @NonNull SolverManager solverManager) { return new DefaultSolutionManager<>(solverManager); } @@ -70,25 +69,25 @@ static , ProblemId_> SolutionManager explain(Solution_ solution) { + default @NonNull ScoreExplanation explain(@NonNull Solution_ solution) { return explain(solution, UPDATE_ALL); } @@ -97,20 +96,20 @@ default ScoreExplanation explain(Solution_ solution) { * quality of a particular solution. * For a simplified, faster and JSON-friendly alternative, see {@link #analyze(Object)}}. * - * @param solution never null - * @param solutionUpdatePolicy never null; if unsure, pick {@link SolutionUpdatePolicy#UPDATE_ALL} - * @return never null + * @param solutionUpdatePolicy if unsure, pick {@link SolutionUpdatePolicy#UPDATE_ALL} * @throws IllegalStateException when constraint matching is disabled or not supported by the underlying score * calculator, such as {@link EasyScoreCalculator}. * @see SolutionUpdatePolicy Description of individual policies with respect to performance trade-offs. */ - ScoreExplanation explain(Solution_ solution, SolutionUpdatePolicy solutionUpdatePolicy); + @NonNull + ScoreExplanation explain(@NonNull Solution_ solution, + @NonNull SolutionUpdatePolicy solutionUpdatePolicy); /** * As defined by {@link #analyze(Object, ScoreAnalysisFetchPolicy, SolutionUpdatePolicy)}, * using {@link SolutionUpdatePolicy#UPDATE_ALL} and {@link ScoreAnalysisFetchPolicy#FETCH_ALL}. */ - default ScoreAnalysis analyze(Solution_ solution) { + default @NonNull ScoreAnalysis analyze(@NonNull Solution_ solution) { return analyze(solution, FETCH_ALL, UPDATE_ALL); } @@ -118,7 +117,7 @@ default ScoreAnalysis analyze(Solution_ solution) { * As defined by {@link #analyze(Object, ScoreAnalysisFetchPolicy, SolutionUpdatePolicy)}, * using {@link SolutionUpdatePolicy#UPDATE_ALL}. */ - default ScoreAnalysis analyze(Solution_ solution, ScoreAnalysisFetchPolicy fetchPolicy) { + default @NonNull ScoreAnalysis analyze(@NonNull Solution_ solution, @NonNull ScoreAnalysisFetchPolicy fetchPolicy) { return analyze(solution, fetchPolicy, UPDATE_ALL); } @@ -126,24 +125,24 @@ default ScoreAnalysis analyze(Solution_ solution, ScoreAnalysisFetchPoli * Calculates and retrieves information about which constraints contributed to the solution's score. * This is a faster, JSON-friendly version of {@link #explain(Object)}. * - * @param solution never null, must be fully initialized otherwise an exception is thrown - * @param fetchPolicy never null; if unsure, pick {@link ScoreAnalysisFetchPolicy#FETCH_ALL} - * @param solutionUpdatePolicy never null; if unsure, pick {@link SolutionUpdatePolicy#UPDATE_ALL} - * @return never null + * @param solution must be fully initialized otherwise an exception is thrown + * @param fetchPolicy if unsure, pick {@link ScoreAnalysisFetchPolicy#FETCH_ALL} + * @param solutionUpdatePolicy if unsure, pick {@link SolutionUpdatePolicy#UPDATE_ALL} * @throws IllegalStateException when constraint matching is disabled or not supported by the underlying score * calculator, such as {@link EasyScoreCalculator}. * @see SolutionUpdatePolicy Description of individual policies with respect to performance trade-offs. */ - ScoreAnalysis analyze(Solution_ solution, ScoreAnalysisFetchPolicy fetchPolicy, - SolutionUpdatePolicy solutionUpdatePolicy); + @NonNull + ScoreAnalysis analyze(@NonNull Solution_ solution, @NonNull ScoreAnalysisFetchPolicy fetchPolicy, + @NonNull SolutionUpdatePolicy solutionUpdatePolicy); /** * As defined by {@link #recommendAssignment(Object, Object, Function, ScoreAnalysisFetchPolicy)}, * with {@link ScoreAnalysisFetchPolicy#FETCH_ALL}. */ - default List> recommendAssignment( - Solution_ solution, EntityOrElement_ evaluatedEntityOrElement, - Function propositionFunction) { + default @NonNull List> recommendAssignment( + @NonNull Solution_ solution, EntityOrElement_ evaluatedEntityOrElement, + @NonNull Function propositionFunction) { return recommendAssignment(solution, evaluatedEntityOrElement, propositionFunction, FETCH_ALL); } @@ -223,36 +222,35 @@ default List * - * + *

    * If instead the proposition function returned Ann and Bob directly, the immutable planning variables, * this problem would have been avoided. * Alternatively, the proposition function could have returned a defensive copy of the Shift. * - * @param solution never null; for basic variable, must be fully initialized or have a single entity unassigned. + * @param solution for basic variable, must be fully initialized or have a single entity unassigned. * For list variable, all values must be assigned to some list, with the optional exception of one. - * @param evaluatedEntityOrElement never null; must be part of the solution. + * @param evaluatedEntityOrElement must be part of the solution. * For basic variable, it is a planning entity and may have one or more variables unassigned. * For list variable, it is a shadow entity and need not be present in any list variable. - * @param propositionFunction never null - * @param fetchPolicy never null; * {@link ScoreAnalysisFetchPolicy#FETCH_ALL} will include more data within {@link RecommendedAssignment}, * but will also take more time to gather that data. - * @return never null, sorted from best to worst; - * designed to be JSON-friendly, see {@link RecommendedAssignment} Javadoc for more. * @param generic type of the evaluated entity or element * @param generic type of the user-provided proposition; * if it is a planning entity, it is recommended * to make a defensive copy inside the proposition function. + * @return sorted from best to worst; + * designed to be JSON-friendly, see {@link RecommendedAssignment} Javadoc for more. * @see PlanningEntity More information about genuine and shadow planning entities. */ - List> recommendAssignment(Solution_ solution, - EntityOrElement_ evaluatedEntityOrElement, Function propositionFunction, - ScoreAnalysisFetchPolicy fetchPolicy); + @NonNull List> recommendAssignment( + @NonNull Solution_ solution, @NonNull EntityOrElement_ evaluatedEntityOrElement, + @NonNull Function propositionFunction, + @NonNull ScoreAnalysisFetchPolicy fetchPolicy); /** * As defined by {@link #recommendAssignment(Object, Object, Function, ScoreAnalysisFetchPolicy)}, * with {@link ScoreAnalysisFetchPolicy#FETCH_ALL}. - * + * * @deprecated Prefer {@link #recommendAssignment(Object, Object, Function, ScoreAnalysisFetchPolicy)}. */ @Deprecated(forRemoval = true, since = "1.15.0") @@ -263,7 +261,7 @@ default List { * depending on the termination configuration. * To terminate a {@link Solver} early, call {@link #terminateEarly()}. * - * @param problem never null, a {@link PlanningSolution}, usually its planning variables are uninitialized - * @return never null, but it can return the original, uninitialized {@link PlanningSolution} with a null {@link Score}. + * @param problem a {@link PlanningSolution}, usually its planning variables are uninitialized + * @return can return the original, uninitialized {@link PlanningSolution} with a null {@link Score}. * @see #terminateEarly() */ - Solution_ solve(Solution_ problem); + @NonNull + Solution_ solve(@NonNull Solution_ problem); /** * Notifies the solver that it should stop at its earliest convenience. @@ -86,10 +89,9 @@ public interface Solver { *

    * To learn more about problem change semantics, please refer to the {@link ProblemChange} Javadoc. * - * @param problemChange never null * @see #addProblemChanges(List) */ - void addProblemChange(ProblemChange problemChange); + void addProblemChange(@NonNull ProblemChange problemChange); /** * Schedules multiple {@link ProblemChange}s to be processed. @@ -103,10 +105,9 @@ public interface Solver { *

    * To learn more about problem change semantics, please refer to the {@link ProblemChange} Javadoc. * - * @param problemChangeList never null * @see #addProblemChange(ProblemChange) */ - void addProblemChanges(List> problemChangeList); + void addProblemChanges(@NonNull List> problemChangeList); /** * Checks if all scheduled {@link ProblemChange}s have been processed. @@ -129,12 +130,11 @@ public interface Solver { * a capacity of {@link Integer#MAX_VALUE}. * * @deprecated Prefer {@link #addProblemChange(ProblemChange)}. - * @param problemFactChange never null * @return true (as specified by {@link Collection#add}) * @see #addProblemFactChanges(List) */ @Deprecated(forRemoval = true) - boolean addProblemFactChange(ProblemFactChange problemFactChange); + boolean addProblemFactChange(@NonNull ProblemFactChange problemFactChange); /** * This method is deprecated. @@ -148,12 +148,11 @@ public interface Solver { * a capacity of {@link Integer#MAX_VALUE}. * * @deprecated Prefer {@link #addProblemChanges(List)}. - * @param problemFactChangeList never null * @return true (as specified by {@link Collection#add}) * @see #addProblemFactChange(ProblemFactChange) */ @Deprecated(forRemoval = true) - boolean addProblemFactChanges(List> problemFactChangeList); + boolean addProblemFactChanges(@NonNull List> problemFactChangeList); /** * This method is deprecated. @@ -167,14 +166,8 @@ public interface Solver { @Deprecated(forRemoval = true) boolean isEveryProblemFactChangeProcessed(); - /** - * @param eventListener never null - */ - void addEventListener(SolverEventListener eventListener); + void addEventListener(@NonNull SolverEventListener eventListener); - /** - * @param eventListener never null - */ - void removeEventListener(SolverEventListener eventListener); + void removeEventListener(@NonNull SolverEventListener eventListener); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/SolverConfigOverride.java b/core/src/main/java/ai/timefold/solver/core/api/solver/SolverConfigOverride.java index 932fbbf174..da88ba7b75 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/SolverConfigOverride.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/SolverConfigOverride.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.domain.solution.PlanningSolution; import ai.timefold.solver.core.config.solver.termination.TerminationConfig; +import org.jspecify.annotations.NonNull; + /** * Includes settings to override default {@link ai.timefold.solver.core.api.solver.Solver} configuration. * @@ -22,9 +24,9 @@ public TerminationConfig getTerminationConfig() { * Sets the solver {@link TerminationConfig}. * * @param terminationConfig allows overriding the default termination config of {@link Solver} - * @return this, never null + * @return this */ - public SolverConfigOverride withTerminationConfig(TerminationConfig terminationConfig) { + public @NonNull SolverConfigOverride withTerminationConfig(@NonNull TerminationConfig terminationConfig) { this.terminationConfig = Objects.requireNonNull(terminationConfig, "Invalid terminationConfig (null) given to SolverConfigOverride."); return this; diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/SolverFactory.java b/core/src/main/java/ai/timefold/solver/core/api/solver/SolverFactory.java index 898404f191..93ed9178c6 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/SolverFactory.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/SolverFactory.java @@ -7,6 +7,9 @@ import ai.timefold.solver.core.config.solver.SolverConfig; import ai.timefold.solver.core.impl.solver.DefaultSolverFactory; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Creates {@link Solver} instances. * Most applications only need one SolverFactory. @@ -30,12 +33,12 @@ public interface SolverFactory { * and uses that {@link SolverConfig} to build a {@link SolverFactory}. * The XML root element must be {@code }. * - * @param solverConfigResource never null, a classpath resource + * @param solverConfigResource a classpath resource * as defined by {@link ClassLoader#getResource(String)} - * @return never null, subsequent changes to the config have no effect on the returned instance + * @return subsequent changes to the config have no effect on the returned instance * @param the solution type, the class with the {@link PlanningSolution} annotation */ - static SolverFactory createFromXmlResource(String solverConfigResource) { + static @NonNull SolverFactory createFromXmlResource(@NonNull String solverConfigResource) { SolverConfig solverConfig = SolverConfig.createFromXmlResource(solverConfigResource); return new DefaultSolverFactory<>(solverConfig); } @@ -43,15 +46,15 @@ static SolverFactory createFromXmlResource(String solverC /** * As defined by {@link #createFromXmlResource(String)}. * - * @param solverConfigResource never null, a classpath resource + * @param solverConfigResource na classpath resource * as defined by {@link ClassLoader#getResource(String)} - * @param classLoader sometimes null, the {@link ClassLoader} to use for loading all resources and {@link Class}es, + * @param classLoader the {@link ClassLoader} to use for loading all resources and {@link Class}es, * null to use the default {@link ClassLoader} - * @return never null, subsequent changes to the config have no effect on the returned instance + * @return subsequent changes to the config have no effect on the returned instance * @param the solution type, the class with the {@link PlanningSolution} annotation */ - static SolverFactory createFromXmlResource(String solverConfigResource, - ClassLoader classLoader) { + static @NonNull SolverFactory createFromXmlResource(@NonNull String solverConfigResource, + @Nullable ClassLoader classLoader) { SolverConfig solverConfig = SolverConfig.createFromXmlResource(solverConfigResource, classLoader); return new DefaultSolverFactory<>(solverConfig); } @@ -63,11 +66,10 @@ static SolverFactory createFromXmlResource(String solverC * Warning: this leads to platform dependent code, * it's recommend to use {@link #createFromXmlResource(String)} instead. * - * @param solverConfigFile never null - * @return never null, subsequent changes to the config have no effect on the returned instance + * @return subsequent changes to the config have no effect on the returned instance * @param the solution type, the class with the {@link PlanningSolution} annotation */ - static SolverFactory createFromXmlFile(File solverConfigFile) { + static @NonNull SolverFactory createFromXmlFile(@NonNull File solverConfigFile) { SolverConfig solverConfig = SolverConfig.createFromXmlFile(solverConfigFile); return new DefaultSolverFactory<>(solverConfig); } @@ -75,13 +77,13 @@ static SolverFactory createFromXmlFile(File solverConfigF /** * As defined by {@link #createFromXmlFile(File)}. * - * @param solverConfigFile never null - * @param classLoader sometimes null, the {@link ClassLoader} to use for loading all resources and {@link Class}es, + * @param classLoader the {@link ClassLoader} to use for loading all resources and {@link Class}es, * null to use the default {@link ClassLoader} - * @return never null, subsequent changes to the config have no effect on the returned instance + * @return subsequent changes to the config have no effect on the returned instance * @param the solution type, the class with the {@link PlanningSolution} annotation */ - static SolverFactory createFromXmlFile(File solverConfigFile, ClassLoader classLoader) { + static @NonNull SolverFactory createFromXmlFile(@NonNull File solverConfigFile, + @Nullable ClassLoader classLoader) { SolverConfig solverConfig = SolverConfig.createFromXmlFile(solverConfigFile, classLoader); return new DefaultSolverFactory<>(solverConfig); } @@ -95,11 +97,10 @@ static SolverFactory createFromXmlFile(File solverConfigF * If you don't need to manipulate the {@link SolverConfig} programmatically, * use {@link #createFromXmlResource(String)} instead. * - * @param solverConfig never null - * @return never null, subsequent changes to the config have no effect on the returned instance + * @return subsequent changes to the config have no effect on the returned instance * @param the solution type, the class with the {@link PlanningSolution} annotation */ - static SolverFactory create(SolverConfig solverConfig) { + static @NonNull SolverFactory create(@NonNull SolverConfig solverConfig) { Objects.requireNonNull(solverConfig); // Defensive copy of solverConfig, because the DefaultSolverFactory doesn't internalize it yet solverConfig = new SolverConfig(solverConfig); @@ -112,18 +113,16 @@ static SolverFactory create(SolverConfig solverConfig) { /** * Creates a new {@link Solver} instance. - * - * @return never null */ - default Solver buildSolver() { + default @NonNull Solver buildSolver() { return this.buildSolver(new SolverConfigOverride<>()); } /** * As defined by {@link #buildSolver()}. * - * @param configOverride never null, includes settings that override the default configuration - * @return never null + * @param configOverride includes settings that override the default configuration */ - Solver buildSolver(SolverConfigOverride configOverride); + @NonNull + Solver buildSolver(@NonNull SolverConfigOverride configOverride); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/SolverJob.java b/core/src/main/java/ai/timefold/solver/core/api/solver/SolverJob.java index dd4cfbcdbb..24a15c366a 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/SolverJob.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/SolverJob.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.api.domain.solution.PlanningSolution; import ai.timefold.solver.core.api.solver.change.ProblemChange; +import org.jspecify.annotations.NonNull; + /** * Represents a {@link PlanningSolution problem} that has been submitted to solve on the {@link SolverManager}. * @@ -18,9 +20,10 @@ public interface SolverJob { /** - * @return never null, a value given to {@link SolverManager#solve(Object, Object, Consumer)} + * @return a value given to {@link SolverManager#solve(Object, Object, Consumer)} * or {@link SolverManager#solveAndListen(Object, Object, Consumer)} */ + @NonNull ProblemId_ getProblemId(); /** @@ -28,8 +31,8 @@ public interface SolverJob { *

    * Returns {@link SolverStatus#NOT_SOLVING} if the solver already terminated. * - * @return never null */ + @NonNull SolverStatus getSolverStatus(); // TODO Future features @@ -40,12 +43,12 @@ public interface SolverJob { *

    * To learn more about problem change semantics, please refer to the {@link ProblemChange} Javadoc. * - * @param problemChange never null * @return completes after the best solution containing this change has been consumed. * @throws IllegalStateException if the underlying {@link Solver} is not in the {@link SolverStatus#SOLVING_ACTIVE} * state */ - CompletableFuture addProblemChange(ProblemChange problemChange); + @NonNull + CompletableFuture addProblemChange(@NonNull ProblemChange problemChange); /** * Terminates the solver or cancels the solver job if it hasn't (re)started yet. @@ -73,6 +76,7 @@ public interface SolverJob { * @throws InterruptedException if the current thread was interrupted while waiting * @throws ExecutionException if the computation threw an exception */ + @NonNull Solution_ getFinalBestSolution() throws InterruptedException, ExecutionException; /** @@ -83,6 +87,7 @@ public interface SolverJob { * * @return the {@link Duration} spent solving since the last (re)start, at least 0 */ + @NonNull Duration getSolvingDuration(); /** @@ -109,8 +114,8 @@ public interface SolverJob { * Return the {@link ProblemSizeStatistics} for the {@link PlanningSolution problem} submitted to the * {@link SolverManager}. * - * @return never null */ + @NonNull ProblemSizeStatistics getProblemSizeStatistics(); /** diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/SolverJobBuilder.java b/core/src/main/java/ai/timefold/solver/core/api/solver/SolverJobBuilder.java index 6a3f9dcba8..7b58f8b5fa 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/SolverJobBuilder.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/SolverJobBuilder.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.domain.solution.PlanningSolution; +import org.jspecify.annotations.NonNull; + /** * Provides a fluent contract that allows customization and submission of planning problems to solve. *

    @@ -28,58 +30,63 @@ public interface SolverJobBuilder { /** * Sets the problem id. * - * @param problemId never null, a ID for each planning problem. This must be unique. - * @return this, never null + * @param problemId a ID for each planning problem. This must be unique. + * @return this */ - SolverJobBuilder withProblemId(ProblemId_ problemId); + @NonNull + SolverJobBuilder withProblemId(@NonNull ProblemId_ problemId); /** * Sets the problem definition. * - * @param problem never null, a {@link PlanningSolution} usually with uninitialized planning variables - * @return this, never null + * @param problem a {@link PlanningSolution} usually with uninitialized planning variables + * @return this */ - default SolverJobBuilder withProblem(Solution_ problem) { + default @NonNull SolverJobBuilder withProblem(@NonNull Solution_ problem) { return withProblemFinder(id -> problem); } /** * Sets the mapping function to the problem definition. * - * @param problemFinder never null, a function that returns a {@link PlanningSolution}, usually with uninitialized - * planning variables - * @return this, never null + * @param problemFinder a function that returns a {@link PlanningSolution}, usually with uninitialized planning variables + * @return this */ - SolverJobBuilder withProblemFinder(Function problemFinder); + @NonNull + SolverJobBuilder + withProblemFinder(@NonNull Function problemFinder); /** * Sets the best solution consumer, which may be called multiple times during the solving process. * - * @param bestSolutionConsumer never null, called multiple times for each new best solution on a consumer thread - * @return this, never null + * @param bestSolutionConsumer called multiple times for each new best solution on a consumer thread + * @return this */ - SolverJobBuilder withBestSolutionConsumer(Consumer bestSolutionConsumer); + @NonNull + SolverJobBuilder withBestSolutionConsumer(@NonNull Consumer bestSolutionConsumer); /** * Sets the final best solution consumer, which is called at the end of the solving process and returns the final * best solution. * - * @param finalBestSolutionConsumer never null, called only once at the end of the solving process on a consumer thread - * @return this, never null + * @param finalBestSolutionConsumer called only once at the end of the solving process on a consumer thread + * @return this */ + @NonNull SolverJobBuilder - withFinalBestSolutionConsumer(Consumer finalBestSolutionConsumer); + withFinalBestSolutionConsumer(@NonNull Consumer finalBestSolutionConsumer); /** * Sets the consumer of the first initialized solution. First initialized solution is the solution at the end of * the last phase that immediately precedes the first local search phase. This solution marks the beginning of actual * optimization process. * - * @param firstInitializedSolutionConsumer never null, called only once before starting the first Local Search phase - * @return this, never null + * @param firstInitializedSolutionConsumer called only once before starting the first Local Search phase + * @return this */ + @NonNull SolverJobBuilder - withFirstInitializedSolutionConsumer(Consumer firstInitializedSolutionConsumer); + withFirstInitializedSolutionConsumer(@NonNull Consumer firstInitializedSolutionConsumer); /** * Sets the consumer for when the solver starts its solving process. @@ -92,26 +99,27 @@ default SolverJobBuilder withProblem(Solution_ problem) { /** * Sets the custom exception handler. * - * @param exceptionHandler never null, called if an exception or error occurs. If null it defaults to logging the + * @param exceptionHandler called if an exception or error occurs. If null it defaults to logging the * exception as an error. - * @return this, never null + * @return this */ + @NonNull SolverJobBuilder - withExceptionHandler(BiConsumer exceptionHandler); + withExceptionHandler(@NonNull BiConsumer exceptionHandler); /** * Sets the solver config override. * - * @param solverConfigOverride never null, allows overriding the default behavior of {@link Solver} - * @return this, never null + * @param solverConfigOverride allows overriding the default behavior of {@link Solver} + * @return this */ - SolverJobBuilder withConfigOverride(SolverConfigOverride solverConfigOverride); + @NonNull + SolverJobBuilder withConfigOverride(@NonNull SolverConfigOverride solverConfigOverride); /** * Submits a planning problem to solve and returns immediately. The planning problem is solved on a solver {@link Thread}, * as soon as one is available. - * - * @return never null */ + @NonNull SolverJob run(); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/SolverManager.java b/core/src/main/java/ai/timefold/solver/core/api/solver/SolverManager.java index ea243d40cc..6cc986097c 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/SolverManager.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/SolverManager.java @@ -14,6 +14,9 @@ import ai.timefold.solver.core.config.solver.SolverManagerConfig; import ai.timefold.solver.core.impl.solver.DefaultSolverManager; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * A SolverManager solves multiple planning problems of the same domain, * asynchronously without blocking the calling thread. @@ -44,13 +47,11 @@ public interface SolverManager extends AutoCloseable { * When using {@link SolutionManager} too, use {@link #create(SolverFactory)} instead * so they reuse the same {@link SolverFactory} instance. * - * @param solverConfig never null - * @return never null * @param the solution type, the class with the {@link PlanningSolution} annotation * @param the ID type of a submitted problem, such as {@link Long} or {@link UUID} */ - static SolverManager create( - SolverConfig solverConfig) { + static @NonNull SolverManager create( + @NonNull SolverConfig solverConfig) { return create(solverConfig, new SolverManagerConfig()); } @@ -60,41 +61,33 @@ static SolverManager create( * When using {@link SolutionManager} too, use {@link #create(SolverFactory, SolverManagerConfig)} instead * so they reuse the same {@link SolverFactory} instance. * - * @param solverConfig never null - * @param solverManagerConfig never null - * @return never null * @param the solution type, the class with the {@link PlanningSolution} annotation * @param the ID type of a submitted problem, such as {@link Long} or {@link UUID}. */ - static SolverManager create( - SolverConfig solverConfig, SolverManagerConfig solverManagerConfig) { + static @NonNull SolverManager create( + @NonNull SolverConfig solverConfig, @NonNull SolverManagerConfig solverManagerConfig) { return create(SolverFactory.create(solverConfig), solverManagerConfig); } /** * Use a {@link SolverFactory} to build a {@link SolverManager}. * - * @param solverFactory never null - * @return never null * @param the solution type, the class with the {@link PlanningSolution} annotation * @param the ID type of a submitted problem, such as {@link Long} or {@link UUID} */ - static SolverManager create( - SolverFactory solverFactory) { + static @NonNull SolverManager create( + @NonNull SolverFactory solverFactory) { return create(solverFactory, new SolverManagerConfig()); } /** * Use a {@link SolverFactory} and a {@link SolverManagerConfig} to build a {@link SolverManager}. * - * @param solverFactory never null - * @param solverManagerConfig never null - * @return never null * @param the solution type, the class with the {@link PlanningSolution} annotation * @param the ID type of a submitted problem, such as {@link Long} or {@link UUID}. */ - static SolverManager create( - SolverFactory solverFactory, SolverManagerConfig solverManagerConfig) { + static @NonNull SolverManager create( + @NonNull SolverFactory solverFactory, @NonNull SolverManagerConfig solverManagerConfig) { return new DefaultSolverManager<>(solverFactory, solverManagerConfig); } @@ -105,8 +98,8 @@ static SolverManager create( /** * Creates a Builder that allows to customize and submit a planning problem to solve. * - * @return never null */ + @NonNull SolverJobBuilder solveBuilder(); // ************************************************************************ @@ -126,12 +119,11 @@ static SolverManager create( *

    * To stop a solver job before it naturally terminates, call {@link SolverJob#terminateEarly()}. * - * @param problemId never null, a ID for each planning problem. This must be unique. + * @param problemId a ID for each planning problem. This must be unique. * Use this problemId to {@link #terminateEarly(Object) terminate} the solver early, - * @param problem never null, a {@link PlanningSolution} usually with uninitialized planning variables - * @return never null + * @param problem a {@link PlanningSolution} usually with uninitialized planning variables */ - default SolverJob solve(ProblemId_ problemId, Solution_ problem) { + default @NonNull SolverJob solve(@NonNull ProblemId_ problemId, @NonNull Solution_ problem) { return solveBuilder() .withProblemId(problemId) .withProblem(problem) @@ -141,15 +133,14 @@ default SolverJob solve(ProblemId_ problemId, Solution_ p /** * As defined by {@link #solve(Object, Object)}. * - * @param problemId never null, a ID for each planning problem. This must be unique. + * @param problemId a ID for each planning problem. This must be unique. * Use this problemId to {@link #terminateEarly(Object) terminate} the solver early, * {@link #getSolverStatus(Object) to get the status} or if the problem changes while solving. - * @param problem never null, a {@link PlanningSolution} usually with uninitialized planning variables - * @param finalBestSolutionConsumer sometimes null, called only once, at the end, on a consumer thread - * @return never null + * @param problem a {@link PlanningSolution} usually with uninitialized planning variables + * @param finalBestSolutionConsumer called only once, at the end, on a consumer thread */ - default SolverJob solve(ProblemId_ problemId, - Solution_ problem, Consumer finalBestSolutionConsumer) { + default @NonNull SolverJob solve(@NonNull ProblemId_ problemId, + @NonNull Solution_ problem, @Nullable Consumer finalBestSolutionConsumer) { SolverJobBuilder builder = solveBuilder() .withProblemId(problemId) .withProblem(problem); @@ -162,20 +153,19 @@ default SolverJob solve(ProblemId_ problemId, /** * As defined by {@link #solve(Object, Object)}. * - * @param problemId never null, a ID for each planning problem. This must be unique. + * @param problemId a ID for each planning problem. This must be unique. * Use this problemId to {@link #terminateEarly(Object) terminate} the solver early, * {@link #getSolverStatus(Object) to get the status} or if the problem changes while solving. - * @param problem never null, a {@link PlanningSolution} usually with uninitialized planning variables - * @param finalBestSolutionConsumer sometimes null, called only once, at the end, on a consumer thread - * @param exceptionHandler sometimes null, called if an exception or error occurs. + * @param problem a {@link PlanningSolution} usually with uninitialized planning variables + * @param finalBestSolutionConsumer called only once, at the end, on a consumer thread + * @param exceptionHandler called if an exception or error occurs. * If null it defaults to logging the exception as an error. * @deprecated It is recommended to use {@link #solveBuilder()} - * @return never null */ @Deprecated(forRemoval = true, since = "1.6.0") - default SolverJob solve(ProblemId_ problemId, - Solution_ problem, Consumer finalBestSolutionConsumer, - BiConsumer exceptionHandler) { + default @NonNull SolverJob solve(@NonNull ProblemId_ problemId, + @NonNull Solution_ problem, @Nullable Consumer finalBestSolutionConsumer, + @Nullable BiConsumer exceptionHandler) { SolverJobBuilder builder = solveBuilder() .withProblemId(problemId) .withProblem(problem); @@ -200,19 +190,18 @@ default SolverJob solve(ProblemId_ problemId, *

    * To stop a solver job before it naturally terminates, call {@link #terminateEarly(Object)}. * - * @param problemId never null, a ID for each planning problem. This must be unique. + * @param problemId an ID for each planning problem. This must be unique. * Use this problemId to {@link #terminateEarly(Object) terminate} the solver early, * {@link #getSolverStatus(Object) to get the status} or if the problem changes while solving. - * @param problemFinder never null, a function that returns a {@link PlanningSolution}, usually with uninitialized planning + * @param problemFinder a function that returns a {@link PlanningSolution}, usually with uninitialized planning * variables - * @param finalBestSolutionConsumer sometimes null, called only once, at the end, on a consumer thread + * @param finalBestSolutionConsumer called only once, at the end, on a consumer thread * @deprecated It is recommended to use {@link #solveBuilder()} - * @return never null */ @Deprecated(forRemoval = true, since = "1.6.0") - default SolverJob solve(ProblemId_ problemId, - Function problemFinder, - Consumer finalBestSolutionConsumer) { + default @NonNull SolverJob solve(@NonNull ProblemId_ problemId, + @NonNull Function problemFinder, + @Nullable Consumer finalBestSolutionConsumer) { SolverJobBuilder builder = solveBuilder() .withProblemId(problemId) .withProblemFinder(problemFinder); @@ -225,22 +214,21 @@ default SolverJob solve(ProblemId_ problemId, /** * As defined by {@link #solve(Object, Function, Consumer)}. * - * @param problemId never null, a ID for each planning problem. This must be unique. + * @param problemId a ID for each planning problem. This must be unique. * Use this problemId to {@link #terminateEarly(Object) terminate} the solver early, * {@link #getSolverStatus(Object) to get the status} or if the problem changes while solving. - * @param problemFinder never null, function that returns a {@link PlanningSolution}, usually with uninitialized planning + * @param problemFinder function that returns a {@link PlanningSolution}, usually with uninitialized planning * variables - * @param finalBestSolutionConsumer sometimes null, called only once, at the end, on a consumer thread - * @param exceptionHandler sometimes null, called if an exception or error occurs. + * @param finalBestSolutionConsumer called only once, at the end, on a consumer thread + * @param exceptionHandler called if an exception or error occurs. * If null it defaults to logging the exception as an error. * @deprecated It is recommended to use {@link #solveBuilder()} - * @return never null */ @Deprecated(forRemoval = true, since = "1.6.0") - default SolverJob solve(ProblemId_ problemId, - Function problemFinder, - Consumer finalBestSolutionConsumer, - BiConsumer exceptionHandler) { + default @NonNull SolverJob solve(@NonNull ProblemId_ problemId, + @NonNull Function problemFinder, + @Nullable Consumer finalBestSolutionConsumer, + @Nullable BiConsumer exceptionHandler) { SolverJobBuilder builder = solveBuilder() .withProblemId(problemId) .withProblemFinder(problemFinder); @@ -265,22 +253,22 @@ default SolverJob solve(ProblemId_ problemId, *

    * To stop a solver job before it naturally terminates, call {@link #terminateEarly(Object)}. * - * @param problemId never null, a ID for each planning problem. This must be unique. + * @param problemId a ID for each planning problem. This must be unique. * Use this problemId to {@link #terminateEarly(Object) terminate} the solver early, * {@link #getSolverStatus(Object) to get the status} or if the problem changes while solving. - * @param problemFinder never null, a function that returns a {@link PlanningSolution}, usually with uninitialized planning + * @param problemFinder a function that returns a {@link PlanningSolution}, usually with uninitialized planning * variables - * @param bestSolutionConsumer never null, called multiple times, on a consumer thread + * @param bestSolutionConsumer called multiple times, on a consumer thread * @deprecated It is recommended to use {@link #solveBuilder()} while also providing a consumer for the best solution - * @return never null */ @Deprecated(forRemoval = true, since = "1.6.0") - default SolverJob solveAndListen(ProblemId_ problemId, - Function problemFinder, Consumer bestSolutionConsumer) { + default @NonNull SolverJob solveAndListen(@NonNull ProblemId_ problemId, + @NonNull Function problemFinder, + @NonNull Consumer bestSolutionConsumer) { SolverJobBuilder builder = solveBuilder() .withProblemId(problemId) .withProblemFinder(problemFinder); - if (bestSolutionConsumer != null) { + if (bestSolutionConsumer != null) { // TODO - never null builder.withBestSolutionConsumer(bestSolutionConsumer); } return builder.run(); @@ -298,15 +286,14 @@ default SolverJob solveAndListen(ProblemId_ problemId, *

    * To stop a solver job before it naturally terminates, call {@link #terminateEarly(Object)}. * - * @param problemId never null, a ID for each planning problem. This must be unique. + * @param problemId a ID for each planning problem. This must be unique. * Use this problemId to {@link #terminateEarly(Object) terminate} the solver early, * {@link #getSolverStatus(Object) to get the status} or if the problem changes while solving. - * @param problem never null, a {@link PlanningSolution} usually with uninitialized planning variables - * @param bestSolutionConsumer never null, called multiple times, on a consumer thread - * @return never null + * @param problem a {@link PlanningSolution} usually with uninitialized planning variables + * @param bestSolutionConsumer called multiple times, on a consumer thread */ - default SolverJob solveAndListen(ProblemId_ problemId, Solution_ problem, - Consumer bestSolutionConsumer) { + default @NonNull SolverJob solveAndListen(@NonNull ProblemId_ problemId, @NonNull Solution_ problem, + @NonNull Consumer bestSolutionConsumer) { return solveBuilder() .withProblemId(problemId) .withProblem(problem) @@ -317,22 +304,21 @@ default SolverJob solveAndListen(ProblemId_ problemId, So /** * As defined by {@link #solveAndListen(Object, Function, Consumer)}. * - * @param problemId never null, a ID for each planning problem. This must be unique. + * @param problemId an ID for each planning problem. This must be unique. * Use this problemId to {@link #terminateEarly(Object) terminate} the solver early, * {@link #getSolverStatus(Object) to get the status} or if the problem changes while solving. - * @param problemFinder never null, function that returns a {@link PlanningSolution}, usually with uninitialized planning + * @param problemFinder function that returns a {@link PlanningSolution}, usually with uninitialized planning * variables - * @param bestSolutionConsumer never null, called multiple times, on a consumer thread - * @param exceptionHandler sometimes null, called if an exception or error occurs. + * @param bestSolutionConsumer called multiple times, on a consumer thread + * @param exceptionHandler called if an exception or error occurs. * If null it defaults to logging the exception as an error. * @deprecated It is recommended to use {@link #solveBuilder()} while also providing a consumer for the best solution - * @return never null */ @Deprecated(forRemoval = true, since = "1.6.0") - default SolverJob solveAndListen(ProblemId_ problemId, - Function problemFinder, - Consumer bestSolutionConsumer, - BiConsumer exceptionHandler) { + default @NonNull SolverJob solveAndListen(@NonNull ProblemId_ problemId, + @NonNull Function problemFinder, + @NonNull Consumer bestSolutionConsumer, + @Nullable BiConsumer exceptionHandler) { SolverJobBuilder builder = solveBuilder() .withProblemId(problemId) .withProblemFinder(problemFinder) @@ -353,25 +339,24 @@ default SolverJob solveAndListen(ProblemId_ problemId, * This allows for use cases that only process the {@link Score} first (during best solution changed events) * and then store the solution upon termination. * - * @param problemId never null, an ID for each planning problem. This must be unique. + * @param problemId an ID for each planning problem. This must be unique. * Use this problemId to {@link #terminateEarly(Object) terminate} the solver early, * {@link #getSolverStatus(Object) to get the status} or if the problem changes while solving. - * @param problemFinder never null, function that returns a {@link PlanningSolution}, usually with uninitialized planning + * @param problemFinder function that returns a {@link PlanningSolution}, usually with uninitialized planning * variables - * @param bestSolutionConsumer never null, called multiple times, on a consumer thread - * @param finalBestSolutionConsumer sometimes null, called only once, at the end, on a consumer thread. + * @param bestSolutionConsumer called multiple times, on a consumer thread + * @param finalBestSolutionConsumer called only once, at the end, on a consumer thread. * That final best solution is already consumed by the bestSolutionConsumer earlier. - * @param exceptionHandler sometimes null, called if an exception or error occurs. + * @param exceptionHandler called if an exception or error occurs. * If null it defaults to logging the exception as an error. * @deprecated It is recommended to use {@link #solveBuilder()} while also providing a consumer for the best solution - * @return never null */ @Deprecated(forRemoval = true, since = "1.6.0") - default SolverJob solveAndListen(ProblemId_ problemId, - Function problemFinder, - Consumer bestSolutionConsumer, - Consumer finalBestSolutionConsumer, - BiConsumer exceptionHandler) { + default @NonNull SolverJob solveAndListen(@NonNull ProblemId_ problemId, + @NonNull Function problemFinder, + @NonNull Consumer bestSolutionConsumer, + @Nullable Consumer finalBestSolutionConsumer, + @Nullable BiConsumer exceptionHandler) { SolverJobBuilder builder = solveBuilder() .withProblemId(problemId) .withProblemFinder(problemFinder) @@ -392,11 +377,11 @@ default SolverJob solveAndListen(ProblemId_ problemId, * To distinguish between both cases, use {@link SolverJob#getSolverStatus()} instead. * Here, that distinction is not supported because it would cause a memory leak. * - * @param problemId never null, a value given to {@link #solve(Object, Object, Consumer)} + * @param problemId a value given to {@link #solve(Object, Object, Consumer)} * or {@link #solveAndListen(Object, Object, Consumer)} - * @return never null */ - SolverStatus getSolverStatus(ProblemId_ problemId); + @NonNull + SolverStatus getSolverStatus(@NonNull ProblemId_ problemId); // TODO Future features // void reloadProblem(ProblemId_ problemId, Function problemFinder); @@ -406,13 +391,13 @@ default SolverJob solveAndListen(ProblemId_ problemId, * If the solver already terminated or the problemId was never added, throws an exception. * The same applies if the underlying {@link Solver} is not in the {@link SolverStatus#SOLVING_ACTIVE} state. * - * @param problemId never null, a value given to {@link #solve(Object, Object, Consumer)} + * @param problemId a value given to {@link #solve(Object, Object, Consumer)} * or {@link #solveAndListen(Object, Object, Consumer)} - * @param problemChange never null * @return completes after the best solution containing this change has been consumed. * @throws IllegalStateException if there is no solver actively solving the problem associated with the problemId */ - CompletableFuture addProblemChange(ProblemId_ problemId, ProblemChange problemChange); + @NonNull + CompletableFuture addProblemChange(@NonNull ProblemId_ problemId, @NonNull ProblemChange problemChange); /** * Terminates the solver or cancels the solver job if it hasn't (re)started yet. @@ -427,10 +412,10 @@ default SolverJob solveAndListen(ProblemId_ problemId, * These consumers run on a consumer thread independently of the termination and may still run even after * this method returns. * - * @param problemId never null, a value given to {@link #solve(Object, Object, Consumer)} + * @param problemId a value given to {@link #solve(Object, Object, Consumer)} * or {@link #solveAndListen(Object, Object, Consumer)} */ - void terminateEarly(ProblemId_ problemId); + void terminateEarly(@NonNull ProblemId_ problemId); /** * Terminates all solvers, cancels all solver jobs that haven't (re)started yet diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/change/ProblemChange.java b/core/src/main/java/ai/timefold/solver/core/api/solver/change/ProblemChange.java index f20da8d869..01d6106694 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/change/ProblemChange.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/change/ProblemChange.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.api.solver.Solver; +import org.jspecify.annotations.NonNull; + /** * A ProblemChange represents a change in one or more {@link PlanningEntity planning entities} or problem facts * of a {@link PlanningSolution}. @@ -69,9 +71,9 @@ public interface ProblemChange { * Do the change on the {@link PlanningSolution}. Every modification to the {@link PlanningSolution} must * be done via the {@link ProblemChangeDirector}, otherwise the {@link Score} calculation will be corrupted. * - * @param workingSolution never null; the {@link PlanningSolution working solution} which contains the problem facts + * @param workingSolution the {@link PlanningSolution working solution} which contains the problem facts * (and {@link PlanningEntity planning entities}) to change - * @param problemChangeDirector never null; {@link ProblemChangeDirector} to perform the change through + * @param problemChangeDirector {@link ProblemChangeDirector} to perform the change through */ - void doChange(Solution_ workingSolution, ProblemChangeDirector problemChangeDirector); + void doChange(@NonNull Solution_ workingSolution, @NonNull ProblemChangeDirector problemChangeDirector); } diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/change/ProblemChangeDirector.java b/core/src/main/java/ai/timefold/solver/core/api/solver/change/ProblemChangeDirector.java index deafa65503..d9ca41004e 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/change/ProblemChangeDirector.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/change/ProblemChangeDirector.java @@ -9,6 +9,9 @@ import ai.timefold.solver.core.api.domain.solution.PlanningSolution; import ai.timefold.solver.core.api.domain.variable.PlanningVariable; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Allows external changes to the {@link PlanningSolution working solution}. If the changes are not applied through * the ProblemChangeDirector, @@ -22,67 +25,68 @@ public interface ProblemChangeDirector { /** * Add a new {@link PlanningEntity} instance into the {@link PlanningSolution working solution}. * - * @param entity never null; the {@link PlanningEntity} instance - * @param entityConsumer never null; adds the entity to the {@link PlanningSolution working solution} + * @param entity the {@link PlanningEntity} instance + * @param entityConsumer adds the entity to the {@link PlanningSolution working solution} * @param the planning entity object type */ - void addEntity(Entity entity, Consumer entityConsumer); + void addEntity(@NonNull Entity entity, @NonNull Consumer entityConsumer); /** * Remove an existing {@link PlanningEntity} instance from the {@link PlanningSolution working solution}. * Translates the entity to a working planning entity by performing a lookup as defined by * {@link #lookUpWorkingObjectOrFail(Object)}. * - * @param entity never null; the {@link PlanningEntity} instance - * @param entityConsumer never null; removes the working entity from the {@link PlanningSolution working solution} + * @param entity the {@link PlanningEntity} instance + * @param entityConsumer removes the working entity from the {@link PlanningSolution working solution} * @param the planning entity object type */ - void removeEntity(Entity entity, Consumer entityConsumer); + void removeEntity(@NonNull Entity entity, @NonNull Consumer entityConsumer); /** * Change a {@link PlanningVariable} value of a {@link PlanningEntity}. Translates the entity to a working * planning entity by performing a lookup as defined by {@link #lookUpWorkingObjectOrFail(Object)}. * - * @param entity never null; the {@link PlanningEntity} instance - * @param variableName never null; name of the {@link PlanningVariable} - * @param entityConsumer never null; updates the value of the {@link PlanningVariable} inside the {@link PlanningEntity} + * @param entity the {@link PlanningEntity} instance + * @param variableName name of the {@link PlanningVariable} + * @param entityConsumer updates the value of the {@link PlanningVariable} inside the {@link PlanningEntity} * @param the planning entity object type */ - void changeVariable(Entity entity, String variableName, Consumer entityConsumer); + void changeVariable(@NonNull Entity entity, @NonNull String variableName, + @NonNull Consumer entityConsumer); /** * Add a new problem fact into the {@link PlanningSolution working solution}. * - * @param problemFact never null; the problem fact instance - * @param problemFactConsumer never null; removes the working problem fact from the + * @param problemFact the problem fact instance + * @param problemFactConsumer removes the working problem fact from the * {@link PlanningSolution working solution} * @param the problem fact object type */ - void addProblemFact(ProblemFact problemFact, Consumer problemFactConsumer); + void addProblemFact(@NonNull ProblemFact problemFact, @NonNull Consumer problemFactConsumer); /** * Remove an existing problem fact from the {@link PlanningSolution working solution}. Translates the problem fact * to a working problem fact by performing a lookup as defined by {@link #lookUpWorkingObjectOrFail(Object)}. * - * @param problemFact never null; the problem fact instance - * @param problemFactConsumer never null; removes the working problem fact from the + * @param problemFact the problem fact instance + * @param problemFactConsumer removes the working problem fact from the * {@link PlanningSolution working solution} * @param the problem fact object type */ - void removeProblemFact(ProblemFact problemFact, Consumer problemFactConsumer); + void removeProblemFact(@NonNull ProblemFact problemFact, @NonNull Consumer problemFactConsumer); /** * Change a property of either a {@link PlanningEntity} or a problem fact. Translates the entity or the problem fact * to its {@link PlanningSolution working solution} counterpart by performing a lookup as defined by * {@link #lookUpWorkingObjectOrFail(Object)}. * - * @param problemFactOrEntity never null; the {@link PlanningEntity} or the problem fact instance - * @param problemFactOrEntityConsumer never null; updates the property of the {@link PlanningEntity} + * @param problemFactOrEntity the {@link PlanningEntity} or the problem fact instance + * @param problemFactOrEntityConsumer updates the property of the {@link PlanningEntity} * or the problem fact * @param the planning entity or problem fact object type */ - void changeProblemProperty(EntityOrProblemFact problemFactOrEntity, - Consumer problemFactOrEntityConsumer); + void changeProblemProperty(@NonNull EntityOrProblemFact problemFactOrEntity, + @NonNull Consumer problemFactOrEntityConsumer); /** * Translate an entity or fact instance (often from another {@link Thread} or JVM) @@ -91,27 +95,25 @@ void changeProblemProperty(EntityOrProblemFact problemFact * Matching is determined by the {@link LookUpStrategyType} on {@link PlanningSolution}. * Matching uses a {@link PlanningId} by default. * - * @param externalObject sometimes null * @return null if externalObject is null * @throws IllegalArgumentException if there is no workingObject for externalObject, if it cannot be looked up * or if the externalObject's class is not supported * @throws IllegalStateException if it cannot be looked up * @param the object type */ - EntityOrProblemFact lookUpWorkingObjectOrFail(EntityOrProblemFact externalObject); + @Nullable EntityOrProblemFact lookUpWorkingObjectOrFail(@Nullable EntityOrProblemFact externalObject); /** * As defined by {@link #lookUpWorkingObjectOrFail(Object)}, * but doesn't fail fast if no workingObject was ever added for the externalObject. * It's recommended to use {@link #lookUpWorkingObjectOrFail(Object)} instead. * - * @param externalObject sometimes null * @return {@link Optional#empty()} if externalObject is null or if there is no workingObject for externalObject * @throws IllegalArgumentException if it cannot be looked up or if the externalObject's class is not supported * @throws IllegalStateException if it cannot be looked up * @param the object type */ - Optional lookUpWorkingObject(EntityOrProblemFact externalObject); + Optional lookUpWorkingObject(@Nullable EntityOrProblemFact externalObject); /** * Calls variable listeners on the external changes submitted so far. diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/event/BestSolutionChangedEvent.java b/core/src/main/java/ai/timefold/solver/core/api/solver/event/BestSolutionChangedEvent.java index 651e865243..45c48ef51c 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/event/BestSolutionChangedEvent.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/event/BestSolutionChangedEvent.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.solver.Solver; import ai.timefold.solver.core.api.solver.change.ProblemChange; +import org.jspecify.annotations.NonNull; + /** * Delivered when the {@link PlanningSolution best solution} changes during solving. * Delivered in the solver thread (which is the thread that calls {@link Solver#solve}). @@ -21,12 +23,10 @@ public class BestSolutionChangedEvent extends EventObject { private final Score newBestScore; /** - * @param solver never null * @param timeMillisSpent {@code >= 0L} - * @param newBestSolution never null */ - public BestSolutionChangedEvent(Solver solver, long timeMillisSpent, - Solution_ newBestSolution, Score newBestScore) { + public BestSolutionChangedEvent(@NonNull Solver solver, long timeMillisSpent, + @NonNull Solution_ newBestSolution, @NonNull Score newBestScore) { super(solver); this.solver = solver; this.timeMillisSpent = timeMillisSpent; @@ -51,9 +51,8 @@ public long getTimeMillisSpent() { *

  • this {@link PlanningSolution} might be infeasible: check {@link Score#isFeasible()}.
  • * * - * @return never null */ - public Solution_ getNewBestSolution() { + public @NonNull Solution_ getNewBestSolution() { return newBestSolution; } @@ -62,10 +61,8 @@ public Solution_ getNewBestSolution() { *

    * This is useful for generic code, which doesn't know the type of the {@link PlanningSolution} * to retrieve the {@link Score} from the {@link #getNewBestSolution()} easily. - * - * @return never null, because at this point it's always already calculated */ - public Score getNewBestScore() { + public @NonNull Score getNewBestScore() { return newBestScore; } diff --git a/core/src/main/java/ai/timefold/solver/core/api/solver/event/SolverEventListener.java b/core/src/main/java/ai/timefold/solver/core/api/solver/event/SolverEventListener.java index a0db909508..7e448dc804 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/solver/event/SolverEventListener.java +++ b/core/src/main/java/ai/timefold/solver/core/api/solver/event/SolverEventListener.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.solver.Solver; import ai.timefold.solver.core.api.solver.change.ProblemChange; +import org.jspecify.annotations.NonNull; + /** * @param the solution type, the class with the {@link PlanningSolution} annotation */ @@ -26,9 +28,7 @@ public interface SolverEventListener extends EventListener { * all {@link ProblemChange}s in the queue will be processed and this method is called only once. * In that case, the former best {@link PlanningSolution} is considered stale, * so it doesn't matter whether the new {@link Score} is better than that or not. - * - * @param event never null */ - void bestSolutionChanged(BestSolutionChangedEvent event); + void bestSolutionChanged(@NonNull BestSolutionChangedEvent event); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/DefaultConstraintWeightOverrides.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/DefaultConstraintWeightOverrides.java index 3590ee0299..88154126cd 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/DefaultConstraintWeightOverrides.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/DefaultConstraintWeightOverrides.java @@ -8,6 +8,9 @@ import ai.timefold.solver.core.api.domain.solution.ConstraintWeightOverrides; import ai.timefold.solver.core.api.score.Score; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + public record DefaultConstraintWeightOverrides>(Map constraintWeightMap) implements ConstraintWeightOverrides { @@ -17,12 +20,12 @@ public DefaultConstraintWeightOverrides(Map constraintWeightMap) } @Override - public Score_ getConstraintWeight(String constraintName) { + public @Nullable Score_ getConstraintWeight(@NonNull String constraintName) { return constraintWeightMap.get(constraintName); } @Override - public Set getKnownConstraintNames() { + public @NonNull Set getKnownConstraintNames() { return Collections.unmodifiableSet(constraintWeightMap.keySet()); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/cloner/FieldAccessingSolutionCloner.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/cloner/FieldAccessingSolutionCloner.java index 0066c5ac2e..49adc0f90c 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/cloner/FieldAccessingSolutionCloner.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/cloner/FieldAccessingSolutionCloner.java @@ -30,6 +30,8 @@ import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; import ai.timefold.solver.core.impl.util.ConcurrentMemoization; +import org.jspecify.annotations.NonNull; + /** * This class is thread-safe. */ @@ -48,7 +50,7 @@ public FieldAccessingSolutionCloner(SolutionDescriptor solutionDescri // ************************************************************************ @Override - public Solution_ cloneSolution(Solution_ originalSolution) { + public @NonNull Solution_ cloneSolution(@NonNull Solution_ originalSolution) { Map originalToCloneMap = new IdentityHashMap<>(); Queue unprocessedQueue = new ArrayDeque<>(); Solution_ cloneSolution = clone(originalSolution, originalToCloneMap, unprocessedQueue, diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/bigdecimal/BigDecimalValueRange.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/bigdecimal/BigDecimalValueRange.java index e94b6e9bb5..0a972810ff 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/bigdecimal/BigDecimalValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/bigdecimal/BigDecimalValueRange.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.domain.valuerange.util.ValueRangeIterator; import ai.timefold.solver.core.impl.solver.random.RandomUtils; +import org.jspecify.annotations.NonNull; + public final class BigDecimalValueRange extends AbstractCountableValueRange { private final BigDecimal from; @@ -88,7 +90,7 @@ public boolean contains(BigDecimal value) { } @Override - public Iterator createOriginalIterator() { + public @NonNull Iterator createOriginalIterator() { return new OriginalBigDecimalValueRangeIterator(); } @@ -114,7 +116,7 @@ public BigDecimal next() { } @Override - public Iterator createRandomIterator(Random workingRandom) { + public @NonNull Iterator createRandomIterator(@NonNull Random workingRandom) { return new RandomBigDecimalValueRangeIterator(workingRandom); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/biginteger/BigIntegerValueRange.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/biginteger/BigIntegerValueRange.java index 9f2fb7790e..fc7e6408f4 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/biginteger/BigIntegerValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/biginteger/BigIntegerValueRange.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.domain.valuerange.util.ValueRangeIterator; import ai.timefold.solver.core.impl.solver.random.RandomUtils; +import org.jspecify.annotations.NonNull; + public final class BigIntegerValueRange extends AbstractCountableValueRange { private final BigInteger from; @@ -71,7 +73,7 @@ public boolean contains(BigInteger value) { } @Override - public Iterator createOriginalIterator() { + public @NonNull Iterator createOriginalIterator() { return new OriginalBigIntegerValueRangeIterator(); } @@ -97,7 +99,7 @@ public BigInteger next() { } @Override - public Iterator createRandomIterator(Random workingRandom) { + public @NonNull Iterator createRandomIterator(@NonNull Random workingRandom) { return new RandomBigIntegerValueRangeIterator(workingRandom); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/collection/ListValueRange.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/collection/ListValueRange.java index e1190b8acf..7621d8ce51 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/collection/ListValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/collection/ListValueRange.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.domain.valuerange.AbstractCountableValueRange; import ai.timefold.solver.core.impl.heuristic.selector.common.iterator.CachedListRandomIterator; +import org.jspecify.annotations.NonNull; + public final class ListValueRange extends AbstractCountableValueRange { private final List list; @@ -34,12 +36,12 @@ public boolean contains(T value) { } @Override - public Iterator createOriginalIterator() { + public @NonNull Iterator createOriginalIterator() { return list.iterator(); } @Override - public Iterator createRandomIterator(Random workingRandom) { + public @NonNull Iterator createRandomIterator(@NonNull Random workingRandom) { return new CachedListRandomIterator<>(list, workingRandom); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/composite/CompositeCountableValueRange.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/composite/CompositeCountableValueRange.java index 6120b8159d..80fb196267 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/composite/CompositeCountableValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/composite/CompositeCountableValueRange.java @@ -14,6 +14,8 @@ import ai.timefold.solver.core.impl.domain.valuerange.util.ValueRangeIterator; import ai.timefold.solver.core.impl.solver.random.RandomUtils; +import org.jspecify.annotations.NonNull; + public final class CompositeCountableValueRange extends AbstractCountableValueRange { private final List> childValueRangeList; @@ -57,7 +59,7 @@ public boolean contains(T value) { } @Override - public Iterator createOriginalIterator() { + public @NonNull Iterator createOriginalIterator() { Stream stream = Stream.empty(); for (CountableValueRange childValueRange : childValueRangeList) { stream = Stream.concat(stream, originalIteratorToStream(childValueRange)); @@ -72,7 +74,7 @@ private static Stream originalIteratorToStream(CountableValueRange val } @Override - public Iterator createRandomIterator(Random workingRandom) { + public @NonNull Iterator createRandomIterator(@NonNull Random workingRandom) { return new RandomCompositeValueRangeIterator(workingRandom); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/composite/EmptyValueRange.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/composite/EmptyValueRange.java index 65a0b1529e..6ed842499f 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/composite/EmptyValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/composite/EmptyValueRange.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.domain.valuerange.AbstractCountableValueRange; import ai.timefold.solver.core.impl.domain.valuerange.util.ValueRangeIterator; +import org.jspecify.annotations.NonNull; + public final class EmptyValueRange extends AbstractCountableValueRange { @Override @@ -26,12 +28,12 @@ public boolean contains(T value) { } @Override - public Iterator createOriginalIterator() { + public @NonNull Iterator createOriginalIterator() { return new EmptyValueRangeIterator(); } @Override - public Iterator createRandomIterator(Random workingRandom) { + public @NonNull Iterator createRandomIterator(@NonNull Random workingRandom) { return new EmptyValueRangeIterator(); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/composite/NullAllowingCountableValueRange.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/composite/NullAllowingCountableValueRange.java index bacedad1d2..35bc387dd2 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/composite/NullAllowingCountableValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/composite/NullAllowingCountableValueRange.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.domain.valuerange.util.ValueRangeIterator; import ai.timefold.solver.core.impl.solver.random.RandomUtils; +import org.jspecify.annotations.NonNull; + public final class NullAllowingCountableValueRange extends AbstractCountableValueRange { private final CountableValueRange childValueRange; @@ -41,7 +43,7 @@ public boolean contains(T value) { } @Override - public Iterator createOriginalIterator() { + public @NonNull Iterator createOriginalIterator() { return new OriginalNullValueRangeIterator(childValueRange.createOriginalIterator()); } @@ -71,7 +73,7 @@ public T next() { } @Override - public Iterator createRandomIterator(Random workingRandom) { + public @NonNull Iterator createRandomIterator(@NonNull Random workingRandom) { return new RandomNullValueRangeIterator(workingRandom); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primboolean/BooleanValueRange.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primboolean/BooleanValueRange.java index 0a9018d818..1f5767f699 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primboolean/BooleanValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primboolean/BooleanValueRange.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.domain.valuerange.AbstractCountableValueRange; import ai.timefold.solver.core.impl.domain.valuerange.util.ValueRangeIterator; +import org.jspecify.annotations.NonNull; + public final class BooleanValueRange extends AbstractCountableValueRange { @Override @@ -31,7 +33,7 @@ public Boolean get(long index) { } @Override - public Iterator createOriginalIterator() { + public @NonNull Iterator createOriginalIterator() { return new OriginalBooleanValueRangeIterator(); } @@ -62,7 +64,7 @@ public Boolean next() { } @Override - public Iterator createRandomIterator(Random workingRandom) { + public @NonNull Iterator createRandomIterator(@NonNull Random workingRandom) { return new RandomBooleanValueRangeIterator(workingRandom); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primdouble/DoubleValueRange.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primdouble/DoubleValueRange.java index 037ce4d093..2cac8e1291 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primdouble/DoubleValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primdouble/DoubleValueRange.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.domain.valuerange.buildin.bigdecimal.BigDecimalValueRange; import ai.timefold.solver.core.impl.domain.valuerange.util.ValueRangeIterator; +import org.jspecify.annotations.NonNull; + /** * Note: Floating point numbers (float, double) cannot represent a decimal number correctly. * If floating point numbers leak into the scoring function, they are likely to cause score corruptions. @@ -51,7 +53,7 @@ public boolean contains(Double value) { // But in practice, no one could use it. @Override - public Iterator createRandomIterator(Random workingRandom) { + public @NonNull Iterator createRandomIterator(@NonNull Random workingRandom) { return new RandomDoubleValueRangeIterator(workingRandom); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primint/IntValueRange.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primint/IntValueRange.java index bcc680b12d..617187822a 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primint/IntValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primint/IntValueRange.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.domain.valuerange.util.ValueRangeIterator; import ai.timefold.solver.core.impl.solver.random.RandomUtils; +import org.jspecify.annotations.NonNull; + public final class IntValueRange extends AbstractCountableValueRange { private final int from; @@ -72,7 +74,7 @@ public Integer get(long index) { } @Override - public Iterator createOriginalIterator() { + public @NonNull Iterator createOriginalIterator() { return new OriginalIntValueRangeIterator(); } @@ -98,7 +100,7 @@ public Integer next() { } @Override - public Iterator createRandomIterator(Random workingRandom) { + public @NonNull Iterator createRandomIterator(@NonNull Random workingRandom) { return new RandomIntValueRangeIterator(workingRandom); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primlong/LongValueRange.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primlong/LongValueRange.java index 50aea52f7c..2247c3b90e 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primlong/LongValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/primlong/LongValueRange.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.domain.valuerange.util.ValueRangeIterator; import ai.timefold.solver.core.impl.solver.random.RandomUtils; +import org.jspecify.annotations.NonNull; + public final class LongValueRange extends AbstractCountableValueRange { private final long from; @@ -77,7 +79,7 @@ public Long get(long index) { } @Override - public Iterator createOriginalIterator() { + public @NonNull Iterator createOriginalIterator() { return new OriginalLongValueRangeIterator(); } @@ -103,7 +105,7 @@ public Long next() { } @Override - public Iterator createRandomIterator(Random workingRandom) { + public @NonNull Iterator createRandomIterator(@NonNull Random workingRandom) { return new RandomLongValueRangeIterator(workingRandom); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/temporal/TemporalValueRange.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/temporal/TemporalValueRange.java index da85967a48..e2b1b1c9ef 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/temporal/TemporalValueRange.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/valuerange/buildin/temporal/TemporalValueRange.java @@ -12,6 +12,8 @@ import ai.timefold.solver.core.impl.domain.valuerange.util.ValueRangeIterator; import ai.timefold.solver.core.impl.solver.random.RandomUtils; +import org.jspecify.annotations.NonNull; + public final class TemporalValueRange> extends AbstractCountableValueRange { @@ -126,7 +128,7 @@ public boolean contains(Temporal_ value) { } @Override - public Iterator createOriginalIterator() { + public @NonNull Iterator createOriginalIterator() { return new OriginalTemporalValueRangeIterator(); } @@ -154,7 +156,7 @@ public Temporal_ next() { } @Override - public Iterator createRandomIterator(Random workingRandom) { + public @NonNull Iterator createRandomIterator(@NonNull Random workingRandom) { return new RandomTemporalValueRangeIterator(workingRandom); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/ExternalizedListVariableStateSupply.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/ExternalizedListVariableStateSupply.java index d8f452d1c1..846d4b01f0 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/ExternalizedListVariableStateSupply.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/ExternalizedListVariableStateSupply.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.heuristic.selector.list.ElementLocation; import ai.timefold.solver.core.impl.heuristic.selector.list.LocationInList; +import org.jspecify.annotations.NonNull; + final class ExternalizedListVariableStateSupply implements ListVariableStateSupply { @@ -21,7 +23,7 @@ public ExternalizedListVariableStateSupply(ListVariableDescriptor sou } @Override - public void resetWorkingSolution(ScoreDirector scoreDirector) { + public void resetWorkingSolution(@NonNull ScoreDirector scoreDirector) { var workingSolution = scoreDirector.getWorkingSolution(); if (elementLocationMap == null) { elementLocationMap = new IdentityHashMap<>((int) sourceVariableDescriptor.getValueRangeSize(workingSolution, null)); @@ -55,22 +57,22 @@ public void close() { } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object o) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { // No need to do anything. } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object o) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { insert(o); } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object o) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { // No need to do anything. } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object o) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { // When the entity is removed, its values become unassigned. // An unassigned value has no inverse entity and no index. retract(o); @@ -97,7 +99,7 @@ private void retract(Object entity) { } @Override - public void afterListVariableElementUnassigned(ScoreDirector scoreDirector, Object element) { + public void afterListVariableElementUnassigned(@NonNull ScoreDirector scoreDirector, @NonNull Object element) { var oldLocation = elementLocationMap.remove(element); if (oldLocation == null) { throw new IllegalStateException( @@ -108,12 +110,14 @@ public void afterListVariableElementUnassigned(ScoreDirector scoreDir } @Override - public void beforeListVariableChanged(ScoreDirector scoreDirector, Object o, int fromIndex, int toIndex) { + public void beforeListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object o, int fromIndex, + int toIndex) { // No need to do anything. } @Override - public void afterListVariableChanged(ScoreDirector scoreDirector, Object o, int fromIndex, int toIndex) { + public void afterListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object o, int fromIndex, + int toIndex) { updateIndexes(o, fromIndex, toIndex); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/anchor/AnchorVariableListener.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/anchor/AnchorVariableListener.java index da69e1c315..744d931069 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/anchor/AnchorVariableListener.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/anchor/AnchorVariableListener.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.domain.variable.inverserelation.SingletonInverseVariableSupply; import ai.timefold.solver.core.impl.score.director.InnerScoreDirector; +import org.jspecify.annotations.NonNull; + /** * @param the solution type, the class with the {@link PlanningSolution} annotation */ @@ -25,32 +27,32 @@ public AnchorVariableListener(AnchorShadowVariableDescriptor anchorSh } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { insert((InnerScoreDirector) scoreDirector, entity); } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // No need to retract() because the insert (which is guaranteed to be called later) affects the same trailing entities. } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { insert((InnerScoreDirector) scoreDirector, entity); } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // No need to retract() because the trailing entities will be removed too or change their previousVariable } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/anchor/ExternalizedAnchorVariableSupply.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/anchor/ExternalizedAnchorVariableSupply.java index c9dca3d6a1..8f8d1ca2aa 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/anchor/ExternalizedAnchorVariableSupply.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/anchor/ExternalizedAnchorVariableSupply.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.domain.variable.inverserelation.SingletonInverseVariableSupply; import ai.timefold.solver.core.impl.domain.variable.listener.SourcedVariableListener; +import org.jspecify.annotations.NonNull; + /** * Alternative to {@link AnchorVariableListener}. */ @@ -34,7 +36,7 @@ public VariableDescriptor getSourceVariableDescriptor() { } @Override - public void resetWorkingSolution(ScoreDirector scoreDirector) { + public void resetWorkingSolution(@NonNull ScoreDirector scoreDirector) { anchorMap = new IdentityHashMap<>(); previousVariableDescriptor.getEntityDescriptor().visitAllEntities(scoreDirector.getWorkingSolution(), this::insert); } @@ -45,27 +47,27 @@ public void close() { } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { insert(entity); } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // No need to retract() because the insert (which is guaranteed to be called later) affects the same trailing entities. } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { insert(entity); } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { boolean removeSucceeded = anchorMap.remove(entity) != null; if (!removeSucceeded) { throw new IllegalStateException("The supply (" + this + ") is corrupted," @@ -77,7 +79,7 @@ public void beforeEntityRemoved(ScoreDirector scoreDirector, Object e } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/index/IndexVariableListener.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/index/IndexVariableListener.java index 03d1dee5aa..6e7a7df48f 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/index/IndexVariableListener.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/index/IndexVariableListener.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.domain.variable.descriptor.ListVariableDescriptor; import ai.timefold.solver.core.impl.score.director.InnerScoreDirector; +import org.jspecify.annotations.NonNull; + public class IndexVariableListener implements ListVariableListener, IndexVariableSupply { protected final IndexShadowVariableDescriptor shadowVariableDescriptor; @@ -23,22 +25,22 @@ public IndexVariableListener( } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { updateIndexes((InnerScoreDirector) scoreDirector, entity, 0, NEVER_QUIT_EARLY); } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { InnerScoreDirector innerScoreDirector = (InnerScoreDirector) scoreDirector; List listVariable = sourceVariableDescriptor.getValue(entity); for (Object element : listVariable) { @@ -49,7 +51,7 @@ public void afterEntityRemoved(ScoreDirector scoreDirector, Object en } @Override - public void afterListVariableElementUnassigned(ScoreDirector scoreDirector, Object element) { + public void afterListVariableElementUnassigned(@NonNull ScoreDirector scoreDirector, @NonNull Object element) { InnerScoreDirector innerScoreDirector = (InnerScoreDirector) scoreDirector; innerScoreDirector.beforeVariableChanged(shadowVariableDescriptor, element); shadowVariableDescriptor.setValue(element, null); @@ -57,12 +59,14 @@ public void afterListVariableElementUnassigned(ScoreDirector scoreDir } @Override - public void beforeListVariableChanged(ScoreDirector scoreDirector, Object entity, int fromIndex, int toIndex) { + public void beforeListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity, + int fromIndex, int toIndex) { // Do nothing } @Override - public void afterListVariableChanged(ScoreDirector scoreDirector, Object entity, int fromIndex, int toIndex) { + public void afterListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity, int fromIndex, + int toIndex) { InnerScoreDirector innerScoreDirector = (InnerScoreDirector) scoreDirector; updateIndexes(innerScoreDirector, entity, fromIndex, toIndex); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/CollectionInverseVariableListener.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/CollectionInverseVariableListener.java index fc56a4975b..c6885f2764 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/CollectionInverseVariableListener.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/CollectionInverseVariableListener.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.domain.variable.descriptor.VariableDescriptor; import ai.timefold.solver.core.impl.score.director.InnerScoreDirector; +import org.jspecify.annotations.NonNull; + public class CollectionInverseVariableListener implements VariableListener, CollectionInverseVariableSupply { @@ -20,32 +22,32 @@ public CollectionInverseVariableListener(InverseRelationShadowVariableDescriptor } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { insert((InnerScoreDirector) scoreDirector, entity); } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { retract((InnerScoreDirector) scoreDirector, entity); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { insert((InnerScoreDirector) scoreDirector, entity); } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { retract((InnerScoreDirector) scoreDirector, entity); } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/ExternalizedCollectionInverseVariableSupply.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/ExternalizedCollectionInverseVariableSupply.java index abf12fca88..2305d85c5a 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/ExternalizedCollectionInverseVariableSupply.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/ExternalizedCollectionInverseVariableSupply.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.impl.domain.variable.descriptor.VariableDescriptor; import ai.timefold.solver.core.impl.domain.variable.listener.SourcedVariableListener; +import org.jspecify.annotations.NonNull; + /** * Alternative to {@link CollectionInverseVariableListener}. */ @@ -33,7 +35,7 @@ public VariableDescriptor getSourceVariableDescriptor() { } @Override - public void resetWorkingSolution(ScoreDirector scoreDirector) { + public void resetWorkingSolution(@NonNull ScoreDirector scoreDirector) { inverseEntitySetMap = new IdentityHashMap<>(); sourceVariableDescriptor.getEntityDescriptor().visitAllEntities(scoreDirector.getWorkingSolution(), this::insert); } @@ -44,32 +46,32 @@ public void close() { } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { insert(entity); } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { retract(entity); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { insert(entity); } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { retract(entity); } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/ExternalizedSingletonInverseVariableSupply.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/ExternalizedSingletonInverseVariableSupply.java index 89fa29a797..c4cbbfdf56 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/ExternalizedSingletonInverseVariableSupply.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/ExternalizedSingletonInverseVariableSupply.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.domain.variable.descriptor.VariableDescriptor; import ai.timefold.solver.core.impl.domain.variable.listener.SourcedVariableListener; +import org.jspecify.annotations.NonNull; + /** * Alternative to {@link SingletonInverseVariableListener}. */ @@ -30,7 +32,7 @@ public VariableDescriptor getSourceVariableDescriptor() { } @Override - public void resetWorkingSolution(ScoreDirector scoreDirector) { + public void resetWorkingSolution(@NonNull ScoreDirector scoreDirector) { inverseEntityMap = new IdentityHashMap<>(); sourceVariableDescriptor.getEntityDescriptor().visitAllEntities(scoreDirector.getWorkingSolution(), this::insert); } @@ -41,32 +43,32 @@ public void close() { } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { insert(entity); } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { retract(entity); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { insert(entity); } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { retract(entity); } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/SingletonInverseVariableListener.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/SingletonInverseVariableListener.java index a6ebcc2b37..70da0f4b8f 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/SingletonInverseVariableListener.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/SingletonInverseVariableListener.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.impl.domain.variable.descriptor.VariableDescriptor; import ai.timefold.solver.core.impl.score.director.InnerScoreDirector; +import org.jspecify.annotations.NonNull; + public class SingletonInverseVariableListener implements VariableListener, SingletonInverseVariableSupply { @@ -18,32 +20,32 @@ public SingletonInverseVariableListener(InverseRelationShadowVariableDescriptor< } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { insert((InnerScoreDirector) scoreDirector, entity); } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { retract((InnerScoreDirector) scoreDirector, entity); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { insert((InnerScoreDirector) scoreDirector, entity); } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { retract((InnerScoreDirector) scoreDirector, entity); } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/SingletonListInverseVariableListener.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/SingletonListInverseVariableListener.java index e601ff7e51..b9158a47ca 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/SingletonListInverseVariableListener.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/inverserelation/SingletonListInverseVariableListener.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.impl.domain.variable.descriptor.ListVariableDescriptor; import ai.timefold.solver.core.impl.score.director.InnerScoreDirector; +import org.jspecify.annotations.NonNull; + public class SingletonListInverseVariableListener implements ListVariableListener, SingletonInverseVariableSupply { @@ -19,7 +21,7 @@ public SingletonListInverseVariableListener( } @Override - public void resetWorkingSolution(ScoreDirector scoreDirector) { + public void resetWorkingSolution(@NonNull ScoreDirector scoreDirector) { if (sourceVariableDescriptor.supportsPinning()) { // Required for variable pinning, otherwise pinned values have their inverse set to null. var entityDescriptor = sourceVariableDescriptor.getEntityDescriptor(); @@ -34,24 +36,24 @@ public void resetWorkingSolution(ScoreDirector scoreDirector) { } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { for (var element : sourceVariableDescriptor.getValue(entity)) { setInverse((InnerScoreDirector) scoreDirector, element, entity, null); } } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { var innerScoreDirector = (InnerScoreDirector) scoreDirector; for (var element : sourceVariableDescriptor.getValue(entity)) { setInverse(innerScoreDirector, element, null, entity); @@ -59,7 +61,7 @@ public void afterEntityRemoved(ScoreDirector scoreDirector, Object en } @Override - public void afterListVariableElementUnassigned(ScoreDirector scoreDirector, Object element) { + public void afterListVariableElementUnassigned(@NonNull ScoreDirector scoreDirector, @NonNull Object element) { var innerScoreDirector = (InnerScoreDirector) scoreDirector; innerScoreDirector.beforeVariableChanged(shadowVariableDescriptor, element); shadowVariableDescriptor.setValue(element, null); @@ -67,12 +69,14 @@ public void afterListVariableElementUnassigned(ScoreDirector scoreDir } @Override - public void beforeListVariableChanged(ScoreDirector scoreDirector, Object entity, int fromIndex, int toIndex) { + public void beforeListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity, + int fromIndex, int toIndex) { // Do nothing } @Override - public void afterListVariableChanged(ScoreDirector scoreDirector, Object entity, int fromIndex, int toIndex) { + public void afterListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity, int fromIndex, + int toIndex) { var innerScoreDirector = (InnerScoreDirector) scoreDirector; var listVariable = sourceVariableDescriptor.getValue(entity); for (var i = fromIndex; i < toIndex; i++) { diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/listener/support/violation/ListVariableTracker.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/listener/support/violation/ListVariableTracker.java index 7e7160cda5..2e0e34e270 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/listener/support/violation/ListVariableTracker.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/listener/support/violation/ListVariableTracker.java @@ -13,6 +13,8 @@ import ai.timefold.solver.core.impl.domain.variable.supply.SupplyManager; import ai.timefold.solver.core.impl.score.director.InnerScoreDirector; +import org.jspecify.annotations.NonNull; + /** * Tracks variable listener events for a given {@link ai.timefold.solver.core.api.domain.variable.PlanningListVariable}. */ @@ -34,43 +36,45 @@ public VariableDescriptor getSourceVariableDescriptor() { } @Override - public void resetWorkingSolution(ScoreDirector scoreDirector) { + public void resetWorkingSolution(@NonNull ScoreDirector scoreDirector) { beforeVariableChangedEntityList.clear(); afterVariableChangedEntityList.clear(); } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { } @Override - public void afterListVariableElementUnassigned(ScoreDirector scoreDirector, Object element) { + public void afterListVariableElementUnassigned(@NonNull ScoreDirector scoreDirector, @NonNull Object element) { } @Override - public void beforeListVariableChanged(ScoreDirector scoreDirector, Object entity, int fromIndex, int toIndex) { + public void beforeListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity, + int fromIndex, int toIndex) { beforeVariableChangedEntityList.add(entity); } @Override - public void afterListVariableChanged(ScoreDirector scoreDirector, Object entity, int fromIndex, int toIndex) { + public void afterListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity, int fromIndex, + int toIndex) { afterVariableChangedEntityList.add(entity); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/listener/support/violation/VariableTracker.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/listener/support/violation/VariableTracker.java index 39fb7756d1..ce0fa847e3 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/listener/support/violation/VariableTracker.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/listener/support/violation/VariableTracker.java @@ -12,6 +12,8 @@ import ai.timefold.solver.core.impl.domain.variable.supply.SupplyManager; import ai.timefold.solver.core.impl.score.director.InnerScoreDirector; +import org.jspecify.annotations.NonNull; + /** * Tracks variable listener events for a given genuine or shadow variable * (except {@link ai.timefold.solver.core.api.domain.variable.PlanningListVariable}). @@ -34,38 +36,38 @@ public VariableDescriptor getSourceVariableDescriptor() { } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object object) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object object) { } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object object) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object object) { } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object object) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object object) { } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object object) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object object) { } @Override - public void resetWorkingSolution(ScoreDirector scoreDirector) { + public void resetWorkingSolution(@NonNull ScoreDirector scoreDirector) { beforeVariableChangedEntityList.clear(); afterVariableChangedEntityList.clear(); } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { beforeVariableChangedEntityList.add(entity); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, Object entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { afterVariableChangedEntityList.add(entity); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/nextprev/NextElementVariableListener.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/nextprev/NextElementVariableListener.java index f9464a62ee..51da259ee5 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/nextprev/NextElementVariableListener.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/nextprev/NextElementVariableListener.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.domain.variable.descriptor.ListVariableDescriptor; import ai.timefold.solver.core.impl.score.director.InnerScoreDirector; +import org.jspecify.annotations.NonNull; + public class NextElementVariableListener implements ListVariableListener { @@ -21,12 +23,12 @@ public NextElementVariableListener( } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { InnerScoreDirector innerScoreDirector = (InnerScoreDirector) scoreDirector; List listVariable = sourceVariableDescriptor.getValue(entity); for (int i = 0; i < listVariable.size() - 1; i++) { @@ -39,12 +41,12 @@ public void afterEntityAdded(ScoreDirector scoreDirector, Object enti } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { InnerScoreDirector innerScoreDirector = (InnerScoreDirector) scoreDirector; List listVariable = sourceVariableDescriptor.getValue(entity); for (int i = 0; i < listVariable.size() - 1; i++) { @@ -56,7 +58,7 @@ public void afterEntityRemoved(ScoreDirector scoreDirector, Object en } @Override - public void afterListVariableElementUnassigned(ScoreDirector scoreDirector, Object element) { + public void afterListVariableElementUnassigned(@NonNull ScoreDirector scoreDirector, @NonNull Object element) { InnerScoreDirector innerScoreDirector = (InnerScoreDirector) scoreDirector; if (shadowVariableDescriptor.getValue(element) != null) { innerScoreDirector.beforeVariableChanged(shadowVariableDescriptor, element); @@ -66,12 +68,14 @@ public void afterListVariableElementUnassigned(ScoreDirector scoreDir } @Override - public void beforeListVariableChanged(ScoreDirector scoreDirector, Object entity, int fromIndex, int toIndex) { + public void beforeListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity, + int fromIndex, int toIndex) { // Do nothing } @Override - public void afterListVariableChanged(ScoreDirector scoreDirector, Object entity, int fromIndex, int toIndex) { + public void afterListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity, int fromIndex, + int toIndex) { InnerScoreDirector innerScoreDirector = (InnerScoreDirector) scoreDirector; List listVariable = sourceVariableDescriptor.getValue(entity); Object next = toIndex < listVariable.size() ? listVariable.get(toIndex) : null; diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/nextprev/PreviousElementVariableListener.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/nextprev/PreviousElementVariableListener.java index 07e92c342e..bc8e9ae9a6 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/nextprev/PreviousElementVariableListener.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/variable/nextprev/PreviousElementVariableListener.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.domain.variable.descriptor.ListVariableDescriptor; import ai.timefold.solver.core.impl.score.director.InnerScoreDirector; +import org.jspecify.annotations.NonNull; + public class PreviousElementVariableListener implements ListVariableListener { protected final PreviousElementShadowVariableDescriptor shadowVariableDescriptor; @@ -20,12 +22,12 @@ public PreviousElementVariableListener( } @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { InnerScoreDirector innerScoreDirector = (InnerScoreDirector) scoreDirector; List listVariable = sourceVariableDescriptor.getValue(entity); for (int i = 1; i < listVariable.size(); i++) { @@ -38,12 +40,12 @@ public void afterEntityAdded(ScoreDirector scoreDirector, Object enti } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { // Do nothing } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object entity) { InnerScoreDirector innerScoreDirector = (InnerScoreDirector) scoreDirector; List listVariable = sourceVariableDescriptor.getValue(entity); for (int i = 1; i < listVariable.size(); i++) { @@ -55,7 +57,7 @@ public void afterEntityRemoved(ScoreDirector scoreDirector, Object en } @Override - public void afterListVariableElementUnassigned(ScoreDirector scoreDirector, Object element) { + public void afterListVariableElementUnassigned(@NonNull ScoreDirector scoreDirector, @NonNull Object element) { InnerScoreDirector innerScoreDirector = (InnerScoreDirector) scoreDirector; if (shadowVariableDescriptor.getValue(element) != null) { innerScoreDirector.beforeVariableChanged(shadowVariableDescriptor, element); @@ -65,12 +67,14 @@ public void afterListVariableElementUnassigned(ScoreDirector scoreDir } @Override - public void beforeListVariableChanged(ScoreDirector scoreDirector, Object entity, int fromIndex, int toIndex) { + public void beforeListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity, + int fromIndex, int toIndex) { // Do nothing } @Override - public void afterListVariableChanged(ScoreDirector scoreDirector, Object entity, int fromIndex, int toIndex) { + public void afterListVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object entity, int fromIndex, + int toIndex) { InnerScoreDirector innerScoreDirector = (InnerScoreDirector) scoreDirector; List listVariable = sourceVariableDescriptor.getValue(entity); Object previous = fromIndex > 0 ? listVariable.get(fromIndex - 1) : null; diff --git a/core/src/main/java/ai/timefold/solver/core/impl/heuristic/move/VariableChangeRecordingScoreDirector.java b/core/src/main/java/ai/timefold/solver/core/impl/heuristic/move/VariableChangeRecordingScoreDirector.java index b2af830593..1dc8de45b5 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/heuristic/move/VariableChangeRecordingScoreDirector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/heuristic/move/VariableChangeRecordingScoreDirector.java @@ -13,6 +13,9 @@ import ai.timefold.solver.core.impl.score.director.VariableDescriptorAwareScoreDirector; import ai.timefold.solver.core.impl.score.director.VariableDescriptorCache; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + final class VariableChangeRecordingScoreDirector implements VariableDescriptorAwareScoreDirector { private final AbstractScoreDirector delegate; @@ -116,7 +119,7 @@ public SolutionDescriptor getSolutionDescriptor() { } @Override - public Solution_ getWorkingSolution() { + public @NonNull Solution_ getWorkingSolution() { return delegate.getWorkingSolution(); } @@ -131,12 +134,12 @@ public void triggerVariableListeners() { } @Override - public E lookUpWorkingObject(E externalObject) { + public @Nullable E lookUpWorkingObject(@Nullable E externalObject) { return delegate.lookUpWorkingObject(externalObject); } @Override - public E lookUpWorkingObjectOrReturnNull(E externalObject) { + public @Nullable E lookUpWorkingObjectOrReturnNull(@Nullable E externalObject) { return delegate.lookUpWorkingObjectOrReturnNull(externalObject); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/DefaultScoreExplanation.java b/core/src/main/java/ai/timefold/solver/core/impl/score/DefaultScoreExplanation.java index b72cc266d9..e2732d2930 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/DefaultScoreExplanation.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/DefaultScoreExplanation.java @@ -18,6 +18,8 @@ import ai.timefold.solver.core.api.score.stream.ConstraintJustification; import ai.timefold.solver.core.impl.score.director.InnerScoreDirector; +import org.jspecify.annotations.NonNull; + public final class DefaultScoreExplanation> implements ScoreExplanation { @@ -137,32 +139,32 @@ public DefaultScoreExplanation(Solution_ solution, Score_ score, } @Override - public Solution_ getSolution() { + public @NonNull Solution_ getSolution() { return solution; } @Override - public Score_ getScore() { + public @NonNull Score_ getScore() { return score; } @Override - public Map> getConstraintMatchTotalMap() { + public @NonNull Map> getConstraintMatchTotalMap() { return constraintMatchTotalMap; } @Override - public List getJustificationList() { + public @NonNull List getJustificationList() { return constraintJustificationList; } @Override - public Map> getIndictmentMap() { + public @NonNull Map> getIndictmentMap() { return indictmentMap; } @Override - public String getSummary() { + public @NonNull String getSummary() { return summary.updateAndGet(currentSummary -> Objects.requireNonNullElseGet(currentSummary, () -> explainScore(score, constraintMatchTotalMap.values(), indictmentMap.values()))); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/director/AbstractScoreDirector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/director/AbstractScoreDirector.java index fc332e5f53..01e932130e 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/director/AbstractScoreDirector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/director/AbstractScoreDirector.java @@ -34,6 +34,8 @@ import ai.timefold.solver.core.impl.solver.exception.UndoScoreCorruptionException; import ai.timefold.solver.core.impl.solver.thread.ChildThreadType; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -123,7 +125,7 @@ public boolean expectShadowVariablesInCorrectState() { } @Override - public Solution_ getWorkingSolution() { + public @NonNull Solution_ getWorkingSolution() { return workingSolution; } @@ -491,7 +493,7 @@ public void afterProblemFactRemoved(Object problemFact) { } @Override - public E lookUpWorkingObject(E externalObject) { + public @Nullable E lookUpWorkingObject(@Nullable E externalObject) { if (!lookUpEnabled) { throw new IllegalStateException("When lookUpEnabled (" + lookUpEnabled + ") is disabled in the constructor, this method should not be called."); @@ -500,7 +502,7 @@ public E lookUpWorkingObject(E externalObject) { } @Override - public E lookUpWorkingObjectOrReturnNull(E externalObject) { + public @Nullable E lookUpWorkingObjectOrReturnNull(@Nullable E externalObject) { if (!lookUpEnabled) { throw new IllegalStateException("When lookUpEnabled (" + lookUpEnabled + ") is disabled in the constructor, this method should not be called."); @@ -694,6 +696,7 @@ or uncorrupted constraintMatchEnabled (%s) is disabled. uncorruptedAnalysis.constraintMap().forEach((constraintRef, uncorruptedConstraintAnalysis) -> { var corruptedConstraintAnalysis = corruptedAnalysis.constraintMap() .get(constraintRef); + // TODO: matches() is Nullable if (corruptedConstraintAnalysis == null || corruptedConstraintAnalysis.matches().isEmpty()) { missingSet.addAll(uncorruptedConstraintAnalysis.matches()); return; @@ -705,6 +708,7 @@ or uncorrupted constraintMatchEnabled (%s) is disabled. corruptedAnalysis.constraintMap().forEach((constraintRef, corruptedConstraintAnalysis) -> { var uncorruptedConstraintAnalysis = uncorruptedAnalysis.constraintMap() .get(constraintRef); + // TODO: matches() is Nullable if (uncorruptedConstraintAnalysis == null || uncorruptedConstraintAnalysis.matches().isEmpty()) { excessSet.addAll(corruptedConstraintAnalysis.matches()); return; diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/director/stream/DefaultConstraintMetaModel.java b/core/src/main/java/ai/timefold/solver/core/impl/score/director/stream/DefaultConstraintMetaModel.java index d31492ad72..a2854b0700 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/director/stream/DefaultConstraintMetaModel.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/director/stream/DefaultConstraintMetaModel.java @@ -13,6 +13,9 @@ import ai.timefold.solver.core.api.score.stream.ConstraintMetaModel; import ai.timefold.solver.core.impl.util.CollectionUtils; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + record DefaultConstraintMetaModel( Map constraintPerRefMap, Map> constraintPerGroupMap) implements ConstraintMetaModel { @@ -36,22 +39,22 @@ public static ConstraintMetaModel of(List constraints) { } @Override - public Constraint getConstraint(ConstraintRef constraintRef) { + public @Nullable Constraint getConstraint(@NonNull ConstraintRef constraintRef) { return constraintPerRefMap.get(constraintRef); } @Override - public Collection getConstraintsPerGroup(String constraintGroup) { + public @NonNull Collection getConstraintsPerGroup(@NonNull String constraintGroup) { return constraintPerGroupMap.getOrDefault(constraintGroup, Collections.emptyList()); } @Override - public Set getConstraintGroups() { + public @NonNull Set getConstraintGroups() { return constraintPerGroupMap.keySet(); } @Override - public Collection getConstraints() { + public @NonNull Collection getConstraints() { return constraintPerRefMap.values(); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/BavetConstraintFactory.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/BavetConstraintFactory.java index b3054bb6fd..74efab1007 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/BavetConstraintFactory.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/BavetConstraintFactory.java @@ -11,11 +11,12 @@ import ai.timefold.solver.core.config.solver.EnvironmentMode; import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; import ai.timefold.solver.core.impl.score.stream.bavet.common.BavetAbstractConstraintStream; -import ai.timefold.solver.core.impl.score.stream.bavet.uni.BavetAbstractUniConstraintStream; import ai.timefold.solver.core.impl.score.stream.bavet.uni.BavetForEachUniConstraintStream; import ai.timefold.solver.core.impl.score.stream.common.InnerConstraintFactory; import ai.timefold.solver.core.impl.score.stream.common.RetrievalSemantics; +import org.jspecify.annotations.NonNull; + public final class BavetConstraintFactory extends InnerConstraintFactory> { @@ -90,7 +91,7 @@ public > Stream_ share( // ************************************************************************ @Override - public UniConstraintStream forEach(Class sourceClass) { + public @NonNull UniConstraintStream forEach(@NonNull Class sourceClass) { assertValidFromType(sourceClass); var entityDescriptor = solutionDescriptor.findEntityDescriptor(sourceClass); if (entityDescriptor == null) { @@ -123,13 +124,13 @@ public UniConstraintStream forEach(Class sourceClass) { } @Override - public UniConstraintStream forEachIncludingUnassigned(Class sourceClass) { + public @NonNull UniConstraintStream forEachIncludingUnassigned(@NonNull Class sourceClass) { assertValidFromType(sourceClass); return share(new BavetForEachUniConstraintStream<>(this, sourceClass, null, RetrievalSemantics.STANDARD)); } @Override - public UniConstraintStream from(Class fromClass) { + public @NonNull UniConstraintStream from(@NonNull Class fromClass) { assertValidFromType(fromClass); var entityDescriptor = solutionDescriptor.findEntityDescriptor(fromClass); if (entityDescriptor != null && entityDescriptor.hasAnyGenuineVariables()) { @@ -141,7 +142,7 @@ public UniConstraintStream from(Class fromClass) { } @Override - public BavetAbstractUniConstraintStream fromUnfiltered(Class fromClass) { + public @NonNull UniConstraintStream fromUnfiltered(@NonNull Class fromClass) { assertValidFromType(fromClass); return share(new BavetForEachUniConstraintStream<>(this, fromClass, null, RetrievalSemantics.LEGACY)); } @@ -160,7 +161,7 @@ public EnvironmentMode getEnvironmentMode() { } @Override - public String getDefaultConstraintPackage() { + public @NonNull String getDefaultConstraintPackage() { return defaultConstraintPackage; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/bi/BavetAbstractBiConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/bi/BavetAbstractBiConstraintStream.java index d54e003d24..441daef664 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/bi/BavetAbstractBiConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/bi/BavetAbstractBiConstraintStream.java @@ -50,6 +50,8 @@ import ai.timefold.solver.core.impl.score.stream.common.tri.TriJoinerComber; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + public abstract class BavetAbstractBiConstraintStream extends BavetAbstractConstraintStream implements InnerBiConstraintStream { @@ -68,7 +70,7 @@ protected BavetAbstractBiConstraintStream(BavetConstraintFactory cons // ************************************************************************ @Override - public BavetAbstractBiConstraintStream filter(BiPredicate predicate) { + public @NonNull BavetAbstractBiConstraintStream filter(@NonNull BiPredicate predicate) { return shareAndAddChild(new BavetFilterBiConstraintStream<>(constraintFactory, this, predicate)); } @@ -78,8 +80,8 @@ public BavetAbstractBiConstraintStream filter(BiPredicate @Override @SafeVarargs - public final TriConstraintStream join(UniConstraintStream otherStream, - TriJoiner... joiners) { + public final @NonNull TriConstraintStream join(@NonNull UniConstraintStream otherStream, + TriJoiner @NonNull... joiners) { var other = (BavetAbstractUniConstraintStream) otherStream; var joinerComber = TriJoinerComber.comb(joiners); var leftBridge = new BavetForeBridgeBiConstraintStream<>(constraintFactory, this); @@ -99,13 +101,15 @@ public final TriConstraintStream join(UniConstraintStream otherS @SafeVarargs @Override - public final BiConstraintStream ifExists(UniConstraintStream otherStream, TriJoiner... joiners) { + public final @NonNull BiConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull TriJoiner @NonNull... joiners) { return ifExistsOrNot(true, otherStream, joiners); } @SafeVarargs @Override - public final BiConstraintStream ifNotExists(UniConstraintStream otherStream, TriJoiner... joiners) { + public final @NonNull BiConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + TriJoiner... joiners) { return ifExistsOrNot(false, otherStream, joiners); } @@ -125,8 +129,8 @@ private BiConstraintStream ifExistsOrNot(boolean shouldExist, UniConst // ************************************************************************ @Override - public UniConstraintStream groupBy( - BiConstraintCollector collector) { + public @NonNull UniConstraintStream groupBy( + @NonNull BiConstraintCollector collector) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.zeroKeysGroupBy(collector, Group0Mapping1CollectorBiNode::new); return buildUniGroupBy(nodeConstructor); @@ -139,9 +143,9 @@ private UniConstraintStream buildUniGroupBy(GroupNodeConstructor BiConstraintStream groupBy( - BiConstraintCollector collectorA, - BiConstraintCollector collectorB) { + public @NonNull BiConstraintStream groupBy( + @NonNull BiConstraintCollector collectorA, + @NonNull BiConstraintCollector collectorB) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.zeroKeysGroupBy(collectorA, collectorB, Group0Mapping2CollectorBiNode::new); return buildBiGroupBy(nodeConstructor); @@ -155,10 +159,10 @@ public BiConstraintSt @Override public - TriConstraintStream - groupBy(BiConstraintCollector collectorA, - BiConstraintCollector collectorB, - BiConstraintCollector collectorC) { + @NonNull TriConstraintStream + groupBy(@NonNull BiConstraintCollector collectorA, + @NonNull BiConstraintCollector collectorB, + @NonNull BiConstraintCollector collectorC) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.zeroKeysGroupBy(collectorA, collectorB, collectorC, Group0Mapping3CollectorBiNode::new); return buildTriGroupBy(nodeConstructor); @@ -173,11 +177,11 @@ public BiConstraintSt @Override public - QuadConstraintStream - groupBy(BiConstraintCollector collectorA, - BiConstraintCollector collectorB, - BiConstraintCollector collectorC, - BiConstraintCollector collectorD) { + @NonNull QuadConstraintStream + groupBy(@NonNull BiConstraintCollector collectorA, + @NonNull BiConstraintCollector collectorB, + @NonNull BiConstraintCollector collectorC, + @NonNull BiConstraintCollector collectorD) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.zeroKeysGroupBy(collectorA, collectorB, collectorC, collectorD, Group0Mapping4CollectorBiNode::new); @@ -192,7 +196,7 @@ public BiConstraintSt } @Override - public UniConstraintStream groupBy(BiFunction groupKeyMapping) { + public @NonNull UniConstraintStream groupBy(@NonNull BiFunction groupKeyMapping) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.oneKeyGroupBy(groupKeyMapping, Group1Mapping0CollectorBiNode::new); return buildUniGroupBy(nodeConstructor); @@ -200,9 +204,10 @@ public UniConstraintStream groupBy(BiFunction - TriConstraintStream groupBy(BiFunction groupKeyMapping, - BiConstraintCollector collectorB, - BiConstraintCollector collectorC) { + @NonNull TriConstraintStream + groupBy(@NonNull BiFunction groupKeyMapping, + @NonNull BiConstraintCollector collectorB, + @NonNull BiConstraintCollector collectorC) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.oneKeyGroupBy(groupKeyMapping, collectorB, collectorC, Group1Mapping2CollectorBiNode::new); return buildTriGroupBy(nodeConstructor); @@ -210,11 +215,11 @@ TriConstraintStream groupBy(BiFunction - QuadConstraintStream - groupBy(BiFunction groupKeyMapping, - BiConstraintCollector collectorB, - BiConstraintCollector collectorC, - BiConstraintCollector collectorD) { + @NonNull QuadConstraintStream + groupBy(@NonNull BiFunction groupKeyMapping, + @NonNull BiConstraintCollector collectorB, + @NonNull BiConstraintCollector collectorC, + @NonNull BiConstraintCollector collectorD) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.oneKeyGroupBy(groupKeyMapping, collectorB, collectorC, collectorD, Group1Mapping3CollectorBiNode::new); @@ -222,26 +227,28 @@ TriConstraintStream groupBy(BiFunction BiConstraintStream groupBy( - BiFunction groupKeyMapping, - BiConstraintCollector collector) { + public @NonNull BiConstraintStream groupBy( + @NonNull BiFunction groupKeyMapping, + @NonNull BiConstraintCollector collector) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.oneKeyGroupBy(groupKeyMapping, collector, Group1Mapping1CollectorBiNode::new); return buildBiGroupBy(nodeConstructor); } @Override - public BiConstraintStream groupBy( - BiFunction groupKeyAMapping, BiFunction groupKeyBMapping) { + public @NonNull BiConstraintStream groupBy( + @NonNull BiFunction groupKeyAMapping, @NonNull BiFunction groupKeyBMapping) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.twoKeysGroupBy(groupKeyAMapping, groupKeyBMapping, Group2Mapping0CollectorBiNode::new); return buildBiGroupBy(nodeConstructor); } @Override - public TriConstraintStream groupBy( - BiFunction groupKeyAMapping, BiFunction groupKeyBMapping, - BiConstraintCollector collector) { + public @NonNull TriConstraintStream + groupBy( + @NonNull BiFunction groupKeyAMapping, + @NonNull BiFunction groupKeyBMapping, + @NonNull BiConstraintCollector collector) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.twoKeysGroupBy(groupKeyAMapping, groupKeyBMapping, collector, Group2Mapping1CollectorBiNode::new); @@ -250,10 +257,11 @@ public TriConstraintStream - QuadConstraintStream groupBy( - BiFunction groupKeyAMapping, BiFunction groupKeyBMapping, - BiConstraintCollector collectorC, - BiConstraintCollector collectorD) { + @NonNull QuadConstraintStream groupBy( + @NonNull BiFunction groupKeyAMapping, + @NonNull BiFunction groupKeyBMapping, + @NonNull BiConstraintCollector collectorC, + @NonNull BiConstraintCollector collectorD) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.twoKeysGroupBy(groupKeyAMapping, groupKeyBMapping, collectorC, collectorD, Group2Mapping2CollectorBiNode::new); @@ -261,9 +269,9 @@ QuadConstraintStream groupBy( } @Override - public TriConstraintStream groupBy( - BiFunction groupKeyAMapping, BiFunction groupKeyBMapping, - BiFunction groupKeyCMapping) { + public @NonNull TriConstraintStream groupBy( + @NonNull BiFunction groupKeyAMapping, @NonNull BiFunction groupKeyBMapping, + @NonNull BiFunction groupKeyCMapping) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.threeKeysGroupBy(groupKeyAMapping, groupKeyBMapping, groupKeyCMapping, Group3Mapping0CollectorBiNode::new); @@ -272,10 +280,11 @@ public TriConstraintStream - QuadConstraintStream - groupBy(BiFunction groupKeyAMapping, BiFunction groupKeyBMapping, - BiFunction groupKeyCMapping, - BiConstraintCollector collectorD) { + @NonNull QuadConstraintStream + groupBy(@NonNull BiFunction groupKeyAMapping, + @NonNull BiFunction groupKeyBMapping, + @NonNull BiFunction groupKeyCMapping, + @NonNull BiConstraintCollector collectorD) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.threeKeysGroupBy(groupKeyAMapping, groupKeyBMapping, groupKeyCMapping, collectorD, Group3Mapping1CollectorBiNode::new); @@ -283,9 +292,12 @@ public TriConstraintStream QuadConstraintStream - groupBy(BiFunction groupKeyAMapping, BiFunction groupKeyBMapping, - BiFunction groupKeyCMapping, BiFunction groupKeyDMapping) { + public + @NonNull QuadConstraintStream + groupBy(@NonNull BiFunction groupKeyAMapping, + @NonNull BiFunction groupKeyBMapping, + @NonNull BiFunction groupKeyCMapping, + @NonNull BiFunction groupKeyDMapping) { GroupNodeConstructor> nodeConstructor = GroupNodeConstructor.fourKeysGroupBy( groupKeyAMapping, groupKeyBMapping, groupKeyCMapping, groupKeyDMapping, @@ -298,7 +310,7 @@ public TriConstraintStream distinct() { + public @NonNull BiConstraintStream distinct() { if (guaranteesDistinct()) { return this; } else { @@ -308,7 +320,8 @@ public BiConstraintStream distinct() { } @Override - public BiConstraintStream concat(UniConstraintStream otherStream, Function paddingFunction) { + public @NonNull BiConstraintStream concat(@NonNull UniConstraintStream otherStream, + @NonNull Function paddingFunction) { var other = (BavetAbstractUniConstraintStream) otherStream; var leftBridge = new BavetForeBridgeBiConstraintStream<>(constraintFactory, this); var rightBridge = new BavetForeBridgeUniConstraintStream<>(constraintFactory, other); @@ -321,7 +334,7 @@ public BiConstraintStream concat(UniConstraintStream otherStream, Funct } @Override - public BiConstraintStream concat(BiConstraintStream otherStream) { + public @NonNull BiConstraintStream concat(@NonNull BiConstraintStream otherStream) { var other = (BavetAbstractBiConstraintStream) otherStream; var leftBridge = new BavetForeBridgeBiConstraintStream<>(constraintFactory, this); var rightBridge = new BavetForeBridgeBiConstraintStream<>(constraintFactory, other); @@ -334,8 +347,8 @@ public BiConstraintStream concat(BiConstraintStream otherStream) { } @Override - public TriConstraintStream concat(TriConstraintStream otherStream, - BiFunction paddingFunction) { + public @NonNull TriConstraintStream concat(@NonNull TriConstraintStream otherStream, + @NonNull BiFunction paddingFunction) { var other = (BavetAbstractTriConstraintStream) otherStream; var leftBridge = new BavetForeBridgeBiConstraintStream<>(constraintFactory, this); var rightBridge = new BavetForeBridgeTriConstraintStream<>(constraintFactory, other); @@ -348,8 +361,8 @@ public TriConstraintStream concat(TriConstraintStream othe } @Override - public QuadConstraintStream concat(QuadConstraintStream otherStream, - BiFunction paddingFunctionC, BiFunction paddingFunctionD) { + public @NonNull QuadConstraintStream concat(@NonNull QuadConstraintStream otherStream, + @NonNull BiFunction paddingFunctionC, @NonNull BiFunction paddingFunctionD) { var other = (BavetAbstractQuadConstraintStream) otherStream; var leftBridge = new BavetForeBridgeBiConstraintStream<>(constraintFactory, this); var rightBridge = new BavetForeBridgeQuadConstraintStream<>(constraintFactory, other); @@ -363,22 +376,24 @@ public QuadConstraintStream concat(QuadConstraintStream UniConstraintStream map(BiFunction mapping) { + public @NonNull UniConstraintStream map(@NonNull BiFunction mapping) { var stream = shareAndAddChild(new BavetUniMapBiConstraintStream<>(constraintFactory, this, mapping)); return constraintFactory.share(new BavetAftBridgeUniConstraintStream<>(constraintFactory, stream), stream::setAftBridge); } @Override - public BiConstraintStream map(BiFunction mappingA, - BiFunction mappingB) { + public @NonNull BiConstraintStream map( + @NonNull BiFunction mappingA, + @NonNull BiFunction mappingB) { var stream = shareAndAddChild(new BavetBiMapBiConstraintStream<>(constraintFactory, this, mappingA, mappingB)); return constraintFactory.share(new BavetAftBridgeBiConstraintStream<>(constraintFactory, stream), stream::setAftBridge); } @Override - public TriConstraintStream - map(BiFunction mappingA, BiFunction mappingB, BiFunction mappingC) { + public @NonNull TriConstraintStream + map(@NonNull BiFunction mappingA, @NonNull BiFunction mappingB, + @NonNull BiFunction mappingC) { var stream = shareAndAddChild( new BavetTriMapBiConstraintStream<>(constraintFactory, this, mappingA, mappingB, mappingC, false)); return constraintFactory.share(new BavetAftBridgeTriConstraintStream<>(constraintFactory, stream), @@ -386,9 +401,10 @@ public BiConstraintStream map(BiFunctio } @Override - public QuadConstraintStream map( - BiFunction mappingA, BiFunction mappingB, BiFunction mappingC, - BiFunction mappingD) { + public @NonNull QuadConstraintStream map( + @NonNull BiFunction mappingA, @NonNull BiFunction mappingB, + @NonNull BiFunction mappingC, + @NonNull BiFunction mappingD) { var stream = shareAndAddChild(new BavetQuadMapBiConstraintStream<>(constraintFactory, this, mappingA, mappingB, mappingC, mappingD, false)); return constraintFactory.share(new BavetAftBridgeQuadConstraintStream<>(constraintFactory, stream), @@ -396,7 +412,8 @@ public QuadConstraintStream BiConstraintStream flattenLast(Function> mapping) { + public @NonNull BiConstraintStream + flattenLast(@NonNull Function> mapping) { var stream = shareAndAddChild(new BavetFlattenLastBiConstraintStream<>(constraintFactory, this, mapping)); return constraintFactory.share(new BavetAftBridgeBiConstraintStream<>(constraintFactory, stream), stream::setAftBridge); } @@ -406,7 +423,7 @@ public BiConstraintStream flattenLast(Function TriConstraintStream expand(BiFunction mapping) { + public @NonNull TriConstraintStream expand(@NonNull BiFunction mapping) { var stream = shareAndAddChild( new BavetTriMapBiConstraintStream<>(constraintFactory, this, ConstantLambdaUtils.biPickFirst(), @@ -416,8 +433,9 @@ public TriConstraintStream expand(BiFunction QuadConstraintStream expand(BiFunction mappingC, - BiFunction mappingD) { + public @NonNull QuadConstraintStream expand( + @NonNull BiFunction mappingC, + @NonNull BiFunction mappingD) { var stream = shareAndAddChild(new BavetQuadMapBiConstraintStream<>(constraintFactory, this, ConstantLambdaUtils.biPickFirst(), ConstantLambdaUtils.biPickSecond(), mappingC, mappingD, true)); diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/common/BavetAbstractConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/common/BavetAbstractConstraintStream.java index eecdc9ab57..2aeec36ae1 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/common/BavetAbstractConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/common/BavetAbstractConstraintStream.java @@ -14,6 +14,8 @@ import ai.timefold.solver.core.impl.score.stream.common.RetrievalSemantics; import ai.timefold.solver.core.impl.score.stream.common.ScoreImpactType; +import org.jspecify.annotations.NonNull; + public abstract class BavetAbstractConstraintStream extends AbstractConstraintStream { protected final BavetConstraintFactory constraintFactory; @@ -125,7 +127,7 @@ protected void assertEmptyChildStreamList() { // ************************************************************************ @Override - public BavetConstraintFactory getConstraintFactory() { + public @NonNull BavetConstraintFactory getConstraintFactory() { return constraintFactory; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/tri/BavetAbstractTriConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/tri/BavetAbstractTriConstraintStream.java index afa40ec25f..b0de0d90a5 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/tri/BavetAbstractTriConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/tri/BavetAbstractTriConstraintStream.java @@ -55,6 +55,8 @@ import ai.timefold.solver.core.impl.score.stream.common.tri.TriConstraintBuilderImpl; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + public abstract class BavetAbstractTriConstraintStream extends BavetAbstractConstraintStream implements InnerTriConstraintStream { @@ -73,7 +75,7 @@ protected BavetAbstractTriConstraintStream(BavetConstraintFactory con // ************************************************************************ @Override - public BavetAbstractTriConstraintStream filter(TriPredicate predicate) { + public @NonNull TriConstraintStream filter(@NonNull TriPredicate predicate) { return shareAndAddChild(new BavetFilterTriConstraintStream<>(constraintFactory, this, predicate)); } @@ -83,8 +85,8 @@ public BavetAbstractTriConstraintStream filter(TriPredicate< @Override @SafeVarargs - public final QuadConstraintStream join(UniConstraintStream otherStream, - QuadJoiner... joiners) { + public final @NonNull QuadConstraintStream join(@NonNull UniConstraintStream otherStream, + QuadJoiner @NonNull... joiners) { var other = (BavetAbstractUniConstraintStream) otherStream; var joinerComber = QuadJoinerComber.comb(joiners); var leftBridge = new BavetForeBridgeTriConstraintStream<>(constraintFactory, this); @@ -104,15 +106,15 @@ public final QuadConstraintStream join(UniConstraintStream ot @SafeVarargs @Override - public final TriConstraintStream ifExists(UniConstraintStream otherStream, - QuadJoiner... joiners) { + public final @NonNull TriConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner @NonNull... joiners) { return ifExistsOrNot(true, otherStream, joiners); } @SafeVarargs @Override - public final TriConstraintStream ifNotExists(UniConstraintStream otherStream, - QuadJoiner... joiners) { + public final @NonNull TriConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull QuadJoiner @NonNull... joiners) { return ifExistsOrNot(false, otherStream, joiners); } @@ -132,8 +134,8 @@ private TriConstraintStream ifExistsOrNot(boolean shouldExist, UniC // ************************************************************************ @Override - public UniConstraintStream groupBy( - TriConstraintCollector collector) { + public @NonNull UniConstraintStream groupBy( + @NonNull TriConstraintCollector collector) { GroupNodeConstructor> nodeConstructor = zeroKeysGroupBy(collector, Group0Mapping1CollectorTriNode::new); return buildUniGroupBy(nodeConstructor); @@ -147,9 +149,9 @@ public UniConstraintStream groupBy( } @Override - public BiConstraintStream groupBy( - TriConstraintCollector collectorA, - TriConstraintCollector collectorB) { + public @NonNull BiConstraintStream groupBy( + @NonNull TriConstraintCollector collectorA, + @NonNull TriConstraintCollector collectorB) { GroupNodeConstructor> nodeConstructor = zeroKeysGroupBy(collectorA, collectorB, Group0Mapping2CollectorTriNode::new); return buildBiGroupBy(nodeConstructor); @@ -162,11 +164,11 @@ public BiConstraintSt } @Override - public + public @NonNull TriConstraintStream - groupBy(TriConstraintCollector collectorA, - TriConstraintCollector collectorB, - TriConstraintCollector collectorC) { + groupBy(@NonNull TriConstraintCollector collectorA, + @NonNull TriConstraintCollector collectorB, + @NonNull TriConstraintCollector collectorC) { GroupNodeConstructor> nodeConstructor = zeroKeysGroupBy(collectorA, collectorB, collectorC, Group0Mapping3CollectorTriNode::new); return buildTriGroupBy(nodeConstructor); @@ -180,12 +182,12 @@ public BiConstraintSt } @Override - public + public @NonNull QuadConstraintStream - groupBy(TriConstraintCollector collectorA, - TriConstraintCollector collectorB, - TriConstraintCollector collectorC, - TriConstraintCollector collectorD) { + groupBy(@NonNull TriConstraintCollector collectorA, + @NonNull TriConstraintCollector collectorB, + @NonNull TriConstraintCollector collectorC, + @NonNull TriConstraintCollector collectorD) { GroupNodeConstructor> nodeConstructor = zeroKeysGroupBy(collectorA, collectorB, collectorC, collectorD, Group0Mapping4CollectorTriNode::new); return buildQuadGroupBy(nodeConstructor); @@ -199,7 +201,8 @@ public BiConstraintSt } @Override - public UniConstraintStream groupBy(TriFunction groupKeyMapping) { + public @NonNull UniConstraintStream + groupBy(@NonNull TriFunction groupKeyMapping) { GroupNodeConstructor> nodeConstructor = oneKeyGroupBy(groupKeyMapping, Group1Mapping0CollectorTriNode::new); return buildUniGroupBy(nodeConstructor); @@ -207,82 +210,85 @@ public UniConstraintStream groupBy(TriFunction - TriConstraintStream groupBy(TriFunction groupKeyMapping, - TriConstraintCollector collectorB, - TriConstraintCollector collectorC) { + @NonNull TriConstraintStream + groupBy(@NonNull TriFunction groupKeyMapping, + @NonNull TriConstraintCollector collectorB, + @NonNull TriConstraintCollector collectorC) { GroupNodeConstructor> nodeConstructor = oneKeyGroupBy(groupKeyMapping, collectorB, collectorC, Group1Mapping2CollectorTriNode::new); return buildTriGroupBy(nodeConstructor); } @Override - public + public @NonNull QuadConstraintStream - groupBy(TriFunction groupKeyMapping, - TriConstraintCollector collectorB, - TriConstraintCollector collectorC, - TriConstraintCollector collectorD) { + groupBy(@NonNull TriFunction groupKeyMapping, + @NonNull TriConstraintCollector collectorB, + @NonNull TriConstraintCollector collectorC, + @NonNull TriConstraintCollector collectorD) { GroupNodeConstructor> nodeConstructor = oneKeyGroupBy(groupKeyMapping, collectorB, collectorC, collectorD, Group1Mapping3CollectorTriNode::new); return buildQuadGroupBy(nodeConstructor); } @Override - public BiConstraintStream groupBy( - TriFunction groupKeyMapping, - TriConstraintCollector collector) { + public @NonNull BiConstraintStream groupBy( + @NonNull TriFunction groupKeyMapping, + @NonNull TriConstraintCollector collector) { GroupNodeConstructor> nodeConstructor = oneKeyGroupBy(groupKeyMapping, collector, Group1Mapping1CollectorTriNode::new); return buildBiGroupBy(nodeConstructor); } @Override - public BiConstraintStream groupBy( - TriFunction groupKeyAMapping, - TriFunction groupKeyBMapping) { + public @NonNull BiConstraintStream groupBy( + @NonNull TriFunction groupKeyAMapping, + @NonNull TriFunction groupKeyBMapping) { GroupNodeConstructor> nodeConstructor = twoKeysGroupBy(groupKeyAMapping, groupKeyBMapping, Group2Mapping0CollectorTriNode::new); return buildBiGroupBy(nodeConstructor); } @Override - public TriConstraintStream groupBy( - TriFunction groupKeyAMapping, - TriFunction groupKeyBMapping, - TriConstraintCollector collector) { + public @NonNull TriConstraintStream + groupBy( + @NonNull TriFunction groupKeyAMapping, + @NonNull TriFunction groupKeyBMapping, + @NonNull TriConstraintCollector collector) { GroupNodeConstructor> nodeConstructor = twoKeysGroupBy(groupKeyAMapping, groupKeyBMapping, collector, Group2Mapping1CollectorTriNode::new); return buildTriGroupBy(nodeConstructor); } @Override - public + public @NonNull QuadConstraintStream groupBy( - TriFunction groupKeyAMapping, - TriFunction groupKeyBMapping, - TriConstraintCollector collectorC, - TriConstraintCollector collectorD) { + @NonNull TriFunction groupKeyAMapping, + @NonNull TriFunction groupKeyBMapping, + @NonNull TriConstraintCollector collectorC, + @NonNull TriConstraintCollector collectorD) { GroupNodeConstructor> nodeConstructor = twoKeysGroupBy(groupKeyAMapping, groupKeyBMapping, collectorC, collectorD, Group2Mapping2CollectorTriNode::new); return buildQuadGroupBy(nodeConstructor); } @Override - public TriConstraintStream groupBy( - TriFunction groupKeyAMapping, TriFunction groupKeyBMapping, - TriFunction groupKeyCMapping) { + public @NonNull TriConstraintStream groupBy( + @NonNull TriFunction groupKeyAMapping, + @NonNull TriFunction groupKeyBMapping, + @NonNull TriFunction groupKeyCMapping) { GroupNodeConstructor> nodeConstructor = threeKeysGroupBy(groupKeyAMapping, groupKeyBMapping, groupKeyCMapping, Group3Mapping0CollectorTriNode::new); return buildTriGroupBy(nodeConstructor); } @Override - public + public @NonNull QuadConstraintStream - groupBy(TriFunction groupKeyAMapping, - TriFunction groupKeyBMapping, - TriFunction groupKeyCMapping, - TriConstraintCollector collectorD) { + groupBy(@NonNull TriFunction groupKeyAMapping, + @NonNull TriFunction groupKeyBMapping, + @NonNull TriFunction groupKeyCMapping, + @NonNull TriConstraintCollector collectorD) { GroupNodeConstructor> nodeConstructor = threeKeysGroupBy(groupKeyAMapping, groupKeyBMapping, groupKeyCMapping, collectorD, Group3Mapping1CollectorTriNode::new); @@ -290,11 +296,12 @@ public TriConstraintStream QuadConstraintStream - groupBy(TriFunction groupKeyAMapping, - TriFunction groupKeyBMapping, - TriFunction groupKeyCMapping, - TriFunction groupKeyDMapping) { + public @NonNull + QuadConstraintStream + groupBy(@NonNull TriFunction groupKeyAMapping, + @NonNull TriFunction groupKeyBMapping, + @NonNull TriFunction groupKeyCMapping, + @NonNull TriFunction groupKeyDMapping) { GroupNodeConstructor> nodeConstructor = fourKeysGroupBy(groupKeyAMapping, groupKeyBMapping, groupKeyCMapping, groupKeyDMapping, Group4Mapping0CollectorTriNode::new); @@ -306,7 +313,7 @@ public TriConstraintStream distinct() { + public @NonNull TriConstraintStream distinct() { if (guaranteesDistinct()) { return this; } else { @@ -317,8 +324,9 @@ public TriConstraintStream distinct() { } @Override - public TriConstraintStream concat(UniConstraintStream otherStream, Function paddingFunctionB, - Function paddingFunctionC) { + public @NonNull TriConstraintStream concat(@NonNull UniConstraintStream otherStream, + @NonNull Function paddingFunctionB, + @NonNull Function paddingFunctionC) { var other = (BavetAbstractUniConstraintStream) otherStream; var leftBridge = new BavetForeBridgeTriConstraintStream<>(constraintFactory, this); var rightBridge = new BavetForeBridgeUniConstraintStream<>(constraintFactory, other); @@ -332,7 +340,8 @@ public TriConstraintStream concat(UniConstraintStream otherStream, F } @Override - public TriConstraintStream concat(BiConstraintStream otherStream, BiFunction paddingFunction) { + public @NonNull TriConstraintStream concat(@NonNull BiConstraintStream otherStream, + @NonNull BiFunction paddingFunction) { var other = (BavetAbstractBiConstraintStream) otherStream; var leftBridge = new BavetForeBridgeTriConstraintStream<>(constraintFactory, this); var rightBridge = new BavetForeBridgeBiConstraintStream<>(constraintFactory, other); @@ -345,7 +354,7 @@ public TriConstraintStream concat(BiConstraintStream otherStream, } @Override - public TriConstraintStream concat(TriConstraintStream otherStream) { + public @NonNull TriConstraintStream concat(@NonNull TriConstraintStream otherStream) { var other = (BavetAbstractTriConstraintStream) otherStream; var leftBridge = new BavetForeBridgeTriConstraintStream<>(constraintFactory, this); var rightBridge = new BavetForeBridgeTriConstraintStream<>(constraintFactory, other); @@ -358,8 +367,8 @@ public TriConstraintStream concat(TriConstraintStream otherStr } @Override - public QuadConstraintStream concat(QuadConstraintStream otherStream, - TriFunction paddingFunction) { + public @NonNull QuadConstraintStream concat(@NonNull QuadConstraintStream otherStream, + @NonNull TriFunction paddingFunction) { var other = (BavetAbstractQuadConstraintStream) otherStream; var leftBridge = new BavetForeBridgeTriConstraintStream<>(constraintFactory, this); var rightBridge = new BavetForeBridgeQuadConstraintStream<>(constraintFactory, other); @@ -373,23 +382,24 @@ public QuadConstraintStream concat(QuadConstraintStream UniConstraintStream map(TriFunction mapping) { + public @NonNull UniConstraintStream map(@NonNull TriFunction mapping) { var stream = shareAndAddChild(new BavetUniMapTriConstraintStream<>(constraintFactory, this, mapping)); return constraintFactory.share(new BavetAftBridgeUniConstraintStream<>(constraintFactory, stream), stream::setAftBridge); } @Override - public BiConstraintStream map(TriFunction mappingA, - TriFunction mappingB) { + public @NonNull BiConstraintStream map( + @NonNull TriFunction mappingA, + @NonNull TriFunction mappingB) { var stream = shareAndAddChild(new BavetBiMapTriConstraintStream<>(constraintFactory, this, mappingA, mappingB)); return constraintFactory.share(new BavetAftBridgeBiConstraintStream<>(constraintFactory, stream), stream::setAftBridge); } @Override - public TriConstraintStream map( - TriFunction mappingA, TriFunction mappingB, - TriFunction mappingC) { + public @NonNull TriConstraintStream map( + @NonNull TriFunction mappingA, @NonNull TriFunction mappingB, + @NonNull TriFunction mappingC) { var stream = shareAndAddChild( new BavetTriMapTriConstraintStream<>(constraintFactory, this, mappingA, mappingB, mappingC)); return constraintFactory.share(new BavetAftBridgeTriConstraintStream<>(constraintFactory, stream), @@ -397,9 +407,9 @@ public TriConstraintStream QuadConstraintStream map( - TriFunction mappingA, TriFunction mappingB, - TriFunction mappingC, TriFunction mappingD) { + public @NonNull QuadConstraintStream map( + @NonNull TriFunction mappingA, @NonNull TriFunction mappingB, + @NonNull TriFunction mappingC, @NonNull TriFunction mappingD) { var stream = shareAndAddChild(new BavetQuadMapTriConstraintStream<>(constraintFactory, this, mappingA, mappingB, mappingC, mappingD, false)); return constraintFactory.share(new BavetAftBridgeQuadConstraintStream<>(constraintFactory, stream), @@ -407,7 +417,8 @@ public QuadConstraintStream TriConstraintStream flattenLast(Function> mapping) { + public @NonNull TriConstraintStream + flattenLast(@NonNull Function> mapping) { var stream = shareAndAddChild(new BavetFlattenLastTriConstraintStream<>(constraintFactory, this, mapping)); return constraintFactory.share(new BavetAftBridgeTriConstraintStream<>(constraintFactory, stream), stream::setAftBridge); @@ -418,7 +429,7 @@ public TriConstraintStream flattenLast(Function QuadConstraintStream expand(TriFunction mapping) { + public @NonNull QuadConstraintStream expand(@NonNull TriFunction mapping) { var stream = shareAndAddChild(new BavetQuadMapTriConstraintStream<>(constraintFactory, this, ConstantLambdaUtils.triPickFirst(), ConstantLambdaUtils.triPickSecond(), diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/uni/BavetAbstractUniConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/uni/BavetAbstractUniConstraintStream.java index eb40682d9f..11049e205d 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/uni/BavetAbstractUniConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/uni/BavetAbstractUniConstraintStream.java @@ -55,6 +55,8 @@ import ai.timefold.solver.core.impl.score.stream.common.uni.UniConstraintBuilderImpl; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + public abstract class BavetAbstractUniConstraintStream extends BavetAbstractConstraintStream implements InnerUniConstraintStream { @@ -73,7 +75,7 @@ protected BavetAbstractUniConstraintStream(BavetConstraintFactory con // ************************************************************************ @Override - public BavetAbstractUniConstraintStream filter(Predicate predicate) { + public @NonNull UniConstraintStream filter(@NonNull Predicate predicate) { return shareAndAddChild(new BavetFilterUniConstraintStream<>(constraintFactory, this, predicate)); } @@ -83,8 +85,8 @@ public BavetAbstractUniConstraintStream filter(Predicate predic @Override @SafeVarargs - public final BiConstraintStream join(UniConstraintStream otherStream, - BiJoiner... joiners) { + public final @NonNull BiConstraintStream join(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner... joiners) { BiJoinerComber joinerComber = BiJoinerComber.comb(joiners); return join(otherStream, joinerComber); } @@ -109,13 +111,15 @@ public final BiConstraintStream join(UniConstraintStream otherStrea @SafeVarargs @Override - public final UniConstraintStream ifExists(UniConstraintStream otherStream, BiJoiner... joiners) { + public final @NonNull UniConstraintStream ifExists(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner... joiners) { return ifExistsOrNot(true, otherStream, joiners); } @SafeVarargs @Override - public final UniConstraintStream ifNotExists(UniConstraintStream otherStream, BiJoiner... joiners) { + public final @NonNull UniConstraintStream ifNotExists(@NonNull UniConstraintStream otherStream, + @NonNull BiJoiner... joiners) { return ifExistsOrNot(false, otherStream, joiners); } @@ -135,8 +139,8 @@ private UniConstraintStream ifExistsOrNot(boolean shouldExist, UniConstra // ************************************************************************ @Override - public UniConstraintStream groupBy( - UniConstraintCollector collector) { + public @NonNull UniConstraintStream groupBy( + @NonNull UniConstraintCollector collector) { GroupNodeConstructor> nodeConstructor = zeroKeysGroupBy(collector, Group0Mapping1CollectorUniNode::new); return buildUniGroupBy(nodeConstructor); @@ -149,9 +153,9 @@ private UniConstraintStream buildUniGroupBy(GroupNodeConstructor BiConstraintStream groupBy( - UniConstraintCollector collectorA, - UniConstraintCollector collectorB) { + public @NonNull BiConstraintStream groupBy( + @NonNull UniConstraintCollector collectorA, + @NonNull UniConstraintCollector collectorB) { GroupNodeConstructor> nodeConstructor = zeroKeysGroupBy(collectorA, collectorB, Group0Mapping2CollectorUniNode::new); return buildBiGroupBy(nodeConstructor); @@ -164,11 +168,11 @@ public BiConstraintSt } @Override - public + public @NonNull TriConstraintStream - groupBy(UniConstraintCollector collectorA, - UniConstraintCollector collectorB, - UniConstraintCollector collectorC) { + groupBy(@NonNull UniConstraintCollector collectorA, + @NonNull UniConstraintCollector collectorB, + @NonNull UniConstraintCollector collectorC) { GroupNodeConstructor> nodeConstructor = zeroKeysGroupBy(collectorA, collectorB, collectorC, Group0Mapping3CollectorUniNode::new); return buildTriGroupBy(nodeConstructor); @@ -182,12 +186,12 @@ public BiConstraintSt } @Override - public + public @NonNull QuadConstraintStream - groupBy(UniConstraintCollector collectorA, - UniConstraintCollector collectorB, - UniConstraintCollector collectorC, - UniConstraintCollector collectorD) { + groupBy(@NonNull UniConstraintCollector collectorA, + @NonNull UniConstraintCollector collectorB, + @NonNull UniConstraintCollector collectorC, + @NonNull UniConstraintCollector collectorD) { GroupNodeConstructor> nodeConstructor = zeroKeysGroupBy(collectorA, collectorB, collectorC, collectorD, Group0Mapping4CollectorUniNode::new); return buildQuadGroupBy(nodeConstructor); @@ -201,86 +205,87 @@ public BiConstraintSt } @Override - public UniConstraintStream groupBy(Function groupKeyMapping) { + public @NonNull UniConstraintStream groupBy(@NonNull Function groupKeyMapping) { GroupNodeConstructor> nodeConstructor = oneKeyGroupBy(groupKeyMapping, Group1Mapping0CollectorUniNode::new); return buildUniGroupBy(nodeConstructor); } @Override - public - TriConstraintStream groupBy(Function groupKeyMapping, - UniConstraintCollector collectorB, - UniConstraintCollector collectorC) { + public @NonNull + TriConstraintStream groupBy(@NonNull Function groupKeyMapping, + @NonNull UniConstraintCollector collectorB, + @NonNull UniConstraintCollector collectorC) { GroupNodeConstructor> nodeConstructor = oneKeyGroupBy(groupKeyMapping, collectorB, collectorC, Group1Mapping2CollectorUniNode::new); return buildTriGroupBy(nodeConstructor); } @Override - public + public @NonNull QuadConstraintStream - groupBy(Function groupKeyMapping, - UniConstraintCollector collectorB, - UniConstraintCollector collectorC, - UniConstraintCollector collectorD) { + groupBy(@NonNull Function groupKeyMapping, + @NonNull UniConstraintCollector collectorB, + @NonNull UniConstraintCollector collectorC, + @NonNull UniConstraintCollector collectorD) { GroupNodeConstructor> nodeConstructor = oneKeyGroupBy(groupKeyMapping, collectorB, collectorC, collectorD, Group1Mapping3CollectorUniNode::new); return buildQuadGroupBy(nodeConstructor); } @Override - public BiConstraintStream groupBy( - Function groupKeyMapping, - UniConstraintCollector collector) { + public @NonNull BiConstraintStream groupBy( + @NonNull Function groupKeyMapping, + @NonNull UniConstraintCollector collector) { GroupNodeConstructor> nodeConstructor = oneKeyGroupBy(groupKeyMapping, collector, Group1Mapping1CollectorUniNode::new); return buildBiGroupBy(nodeConstructor); } @Override - public BiConstraintStream groupBy( - Function groupKeyAMapping, Function groupKeyBMapping) { + public @NonNull BiConstraintStream groupBy( + @NonNull Function groupKeyAMapping, @NonNull Function groupKeyBMapping) { GroupNodeConstructor> nodeConstructor = twoKeysGroupBy(groupKeyAMapping, groupKeyBMapping, Group2Mapping0CollectorUniNode::new); return buildBiGroupBy(nodeConstructor); } @Override - public TriConstraintStream groupBy( - Function groupKeyAMapping, Function groupKeyBMapping, - UniConstraintCollector collector) { + public @NonNull TriConstraintStream + groupBy( + @NonNull Function groupKeyAMapping, @NonNull Function groupKeyBMapping, + @NonNull UniConstraintCollector collector) { GroupNodeConstructor> nodeConstructor = twoKeysGroupBy(groupKeyAMapping, groupKeyBMapping, collector, Group2Mapping1CollectorUniNode::new); return buildTriGroupBy(nodeConstructor); } @Override - public + public @NonNull QuadConstraintStream groupBy( - Function groupKeyAMapping, Function groupKeyBMapping, - UniConstraintCollector collectorC, - UniConstraintCollector collectorD) { + @NonNull Function groupKeyAMapping, @NonNull Function groupKeyBMapping, + @NonNull UniConstraintCollector collectorC, + @NonNull UniConstraintCollector collectorD) { GroupNodeConstructor> nodeConstructor = twoKeysGroupBy(groupKeyAMapping, groupKeyBMapping, collectorC, collectorD, Group2Mapping2CollectorUniNode::new); return buildQuadGroupBy(nodeConstructor); } @Override - public TriConstraintStream groupBy( - Function groupKeyAMapping, Function groupKeyBMapping, - Function groupKeyCMapping) { + public @NonNull TriConstraintStream groupBy( + @NonNull Function groupKeyAMapping, @NonNull Function groupKeyBMapping, + @NonNull Function groupKeyCMapping) { GroupNodeConstructor> nodeConstructor = threeKeysGroupBy(groupKeyAMapping, groupKeyBMapping, groupKeyCMapping, Group3Mapping0CollectorUniNode::new); return buildTriGroupBy(nodeConstructor); } @Override - public + public @NonNull QuadConstraintStream - groupBy(Function groupKeyAMapping, Function groupKeyBMapping, - Function groupKeyCMapping, - UniConstraintCollector collectorD) { + groupBy(@NonNull Function groupKeyAMapping, @NonNull Function groupKeyBMapping, + @NonNull Function groupKeyCMapping, + @NonNull UniConstraintCollector collectorD) { GroupNodeConstructor> nodeConstructor = threeKeysGroupBy(groupKeyAMapping, groupKeyBMapping, groupKeyCMapping, collectorD, Group3Mapping1CollectorUniNode::new); @@ -288,9 +293,10 @@ public TriConstraintStream QuadConstraintStream - groupBy(Function groupKeyAMapping, Function groupKeyBMapping, - Function groupKeyCMapping, Function groupKeyDMapping) { + public @NonNull + QuadConstraintStream + groupBy(@NonNull Function groupKeyAMapping, @NonNull Function groupKeyBMapping, + @NonNull Function groupKeyCMapping, @NonNull Function groupKeyDMapping) { GroupNodeConstructor> nodeConstructor = fourKeysGroupBy(groupKeyAMapping, groupKeyBMapping, groupKeyCMapping, groupKeyDMapping, Group4Mapping0CollectorUniNode::new); @@ -302,7 +308,7 @@ public TriConstraintStream distinct() { + public @NonNull UniConstraintStream distinct() { if (guaranteesDistinct()) { return this; } else { @@ -311,7 +317,7 @@ public UniConstraintStream distinct() { } @Override - public UniConstraintStream concat(UniConstraintStream otherStream) { + public @NonNull UniConstraintStream concat(@NonNull UniConstraintStream otherStream) { var other = (BavetAbstractUniConstraintStream) otherStream; var leftBridge = new BavetForeBridgeUniConstraintStream<>(constraintFactory, this); var rightBridge = new BavetForeBridgeUniConstraintStream<>(constraintFactory, other); @@ -324,7 +330,8 @@ public UniConstraintStream concat(UniConstraintStream otherStream) { } @Override - public BiConstraintStream concat(BiConstraintStream otherStream, Function paddingFunction) { + public @NonNull BiConstraintStream concat(@NonNull BiConstraintStream otherStream, + @NonNull Function paddingFunction) { var other = (BavetAbstractBiConstraintStream) otherStream; var leftBridge = new BavetForeBridgeUniConstraintStream<>(constraintFactory, this); var rightBridge = new BavetForeBridgeBiConstraintStream<>(constraintFactory, other); @@ -337,8 +344,9 @@ public BiConstraintStream concat(BiConstraintStream otherStream, } @Override - public TriConstraintStream concat(TriConstraintStream otherStream, Function paddingFunctionB, - Function paddingFunctionC) { + public @NonNull TriConstraintStream concat(@NonNull TriConstraintStream otherStream, + @NonNull Function paddingFunctionB, + @NonNull Function paddingFunctionC) { var other = (BavetAbstractTriConstraintStream) otherStream; var leftBridge = new BavetForeBridgeUniConstraintStream<>(constraintFactory, this); var rightBridge = new BavetForeBridgeTriConstraintStream<>(constraintFactory, other); @@ -352,8 +360,9 @@ public TriConstraintStream concat(TriConstraintStream o } @Override - public QuadConstraintStream concat(QuadConstraintStream otherStream, - Function paddingFunctionB, Function paddingFunctionC, Function paddingFunctionD) { + public @NonNull QuadConstraintStream concat(@NonNull QuadConstraintStream otherStream, + @NonNull Function paddingFunctionB, @NonNull Function paddingFunctionC, + @NonNull Function paddingFunctionD) { var other = (BavetAbstractQuadConstraintStream) otherStream; var leftBridge = new BavetForeBridgeUniConstraintStream<>(constraintFactory, this); var rightBridge = new BavetForeBridgeQuadConstraintStream<>(constraintFactory, other); @@ -368,23 +377,24 @@ public QuadConstraintStream concat(QuadConstraintStream UniConstraintStream map(Function mapping) { + public @NonNull UniConstraintStream map(@NonNull Function mapping) { var stream = shareAndAddChild(new BavetUniMapUniConstraintStream<>(constraintFactory, this, mapping)); return constraintFactory.share(new BavetAftBridgeUniConstraintStream<>(constraintFactory, stream), stream::setAftBridge); } @Override - public BiConstraintStream map(Function mappingA, - Function mappingB) { + public @NonNull BiConstraintStream map(@NonNull Function mappingA, + @NonNull Function mappingB) { var stream = shareAndAddChild(new BavetBiMapUniConstraintStream<>(constraintFactory, this, mappingA, mappingB, false)); return constraintFactory.share(new BavetAftBridgeBiConstraintStream<>(constraintFactory, stream), stream::setAftBridge); } @Override - public TriConstraintStream map(Function mappingA, - Function mappingB, Function mappingC) { + public @NonNull TriConstraintStream map( + @NonNull Function mappingA, + @NonNull Function mappingB, @NonNull Function mappingC) { var stream = shareAndAddChild( new BavetTriMapUniConstraintStream<>(constraintFactory, this, mappingA, mappingB, mappingC, false)); return constraintFactory.share(new BavetAftBridgeTriConstraintStream<>(constraintFactory, stream), @@ -392,9 +402,10 @@ public TriConstraintStream QuadConstraintStream map( - Function mappingA, Function mappingB, Function mappingC, - Function mappingD) { + public @NonNull QuadConstraintStream map( + @NonNull Function mappingA, @NonNull Function mappingB, + @NonNull Function mappingC, + @NonNull Function mappingD) { var stream = shareAndAddChild(new BavetQuadMapUniConstraintStream<>(constraintFactory, this, mappingA, mappingB, mappingC, mappingD, false)); return constraintFactory.share(new BavetAftBridgeQuadConstraintStream<>(constraintFactory, stream), @@ -402,7 +413,7 @@ public QuadConstraintStream UniConstraintStream flattenLast(Function> mapping) { + public @NonNull UniConstraintStream flattenLast(@NonNull Function> mapping) { var stream = shareAndAddChild(new BavetFlattenLastUniConstraintStream<>(constraintFactory, this, mapping)); return constraintFactory.share(new BavetAftBridgeUniConstraintStream<>(constraintFactory, stream), stream::setAftBridge); @@ -413,7 +424,7 @@ public UniConstraintStream flattenLast(Function BiConstraintStream expand(Function mapping) { + public @NonNull BiConstraintStream expand(@NonNull Function mapping) { var stream = shareAndAddChild( new BavetBiMapUniConstraintStream<>(constraintFactory, this, @@ -422,8 +433,9 @@ public BiConstraintStream expand(Function m } @Override - public TriConstraintStream expand(Function mappingB, - Function mappingC) { + public @NonNull TriConstraintStream expand( + @NonNull Function mappingB, + @NonNull Function mappingC) { var stream = shareAndAddChild( new BavetTriMapUniConstraintStream<>(constraintFactory, this, ConstantLambdaUtils.identity(), mappingB, mappingC, @@ -433,8 +445,9 @@ public TriConstraintStream expand(Fu } @Override - public QuadConstraintStream - expand(Function mappingB, Function mappingC, Function mappingD) { + public @NonNull QuadConstraintStream + expand(@NonNull Function mappingB, @NonNull Function mappingC, + @NonNull Function mappingD) { var stream = shareAndAddChild( new BavetQuadMapUniConstraintStream<>(constraintFactory, this, ConstantLambdaUtils.identity(), mappingB, diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/LoadBalanceImpl.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/LoadBalanceImpl.java index 1912b4fc20..16586b2365 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/LoadBalanceImpl.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/LoadBalanceImpl.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.api.score.stream.common.LoadBalance; +import org.jspecify.annotations.NonNull; + public final class LoadBalanceImpl implements LoadBalance { // If need be, precision can be made configurable on the constraint collector level. @@ -86,7 +88,7 @@ private void updateSquaredDeviation(long oldValue, long newValue) { } @Override - public Map loads() { + public @NonNull Map loads() { if (balancedItemCountMap.isEmpty()) { return Collections.emptyMap(); } @@ -94,7 +96,7 @@ public Map loads() { } @Override - public BigDecimal unfairness() { + public @NonNull BigDecimal unfairness() { var totalToBalanceCount = balancedItemCountMap.size(); return switch (totalToBalanceCount) { case 0 -> BigDecimal.ZERO; diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AndThenBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AndThenBiCollector.java index 5e90cdd9ff..a9d8434389 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AndThenBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AndThenBiCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector; +import org.jspecify.annotations.NonNull; + final class AndThenBiCollector implements BiConstraintCollector { @@ -20,17 +22,17 @@ final class AndThenBiCollector } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return delegate.supplier(); } @Override - public TriFunction accumulator() { + public @NonNull TriFunction accumulator() { return delegate.accumulator(); } @Override - public Function finisher() { + public @NonNull Function finisher() { var finisher = delegate.finisher(); return container -> mappingFunction.apply(finisher.apply(container)); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AverageIntBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AverageIntBiCollector.java index f34eaa3d12..823402bb1a 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AverageIntBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AverageIntBiCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.impl.score.stream.collector.IntAverageCalculator; +import org.jspecify.annotations.NonNull; + final class AverageIntBiCollector extends IntCalculatorBiCollector { AverageIntBiCollector(ToIntBiFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return IntAverageCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AverageLongBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AverageLongBiCollector.java index 0ca431cf98..884fb473b1 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AverageLongBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AverageLongBiCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.impl.score.stream.collector.LongAverageCalculator; +import org.jspecify.annotations.NonNull; + final class AverageLongBiCollector extends LongCalculatorBiCollector { AverageLongBiCollector(ToLongBiFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return LongAverageCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AverageReferenceBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AverageReferenceBiCollector.java index e11cb7a9ce..22b4d4b56f 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AverageReferenceBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/AverageReferenceBiCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.ReferenceAverageCalculator; +import org.jspecify.annotations.NonNull; + final class AverageReferenceBiCollector extends ObjectCalculatorBiCollector> { private final Supplier> calculatorSupplier; @@ -17,7 +19,7 @@ final class AverageReferenceBiCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return calculatorSupplier; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ComposeFourBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ComposeFourBiCollector.java index 93a69dd242..55e3f6ef67 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ComposeFourBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ComposeFourBiCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector; import ai.timefold.solver.core.impl.util.Quadruple; +import org.jspecify.annotations.NonNull; + final class ComposeFourBiCollector implements BiConstraintCollector, Result_> { @@ -61,7 +63,7 @@ final class ComposeFourBiCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> { ResultHolder1_ a = firstSupplier.get(); ResultHolder2_ b = secondSupplier.get(); @@ -71,7 +73,7 @@ public Supplier, A, B, Runnable> + public @NonNull TriFunction, A, B, Runnable> accumulator() { return (resultHolder, a, b) -> composeUndo(firstAccumulator.apply(resultHolder.a(), a, b), secondAccumulator.apply(resultHolder.b(), a, b), @@ -90,7 +92,7 @@ private static Runnable composeUndo(Runnable first, Runnable second, Runnable th } @Override - public Function, Result_> finisher() { + public @NonNull Function, Result_> finisher() { return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.a()), secondFinisher.apply(resultHolder.b()), thirdFinisher.apply(resultHolder.c()), diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ComposeThreeBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ComposeThreeBiCollector.java index a1a978508b..d954589392 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ComposeThreeBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ComposeThreeBiCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector; import ai.timefold.solver.core.impl.util.Triple; +import org.jspecify.annotations.NonNull; + final class ComposeThreeBiCollector implements BiConstraintCollector, Result_> { private final BiConstraintCollector first; @@ -50,7 +52,7 @@ final class ComposeThreeBiCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> { ResultHolder1_ a = firstSupplier.get(); ResultHolder2_ b = secondSupplier.get(); @@ -59,7 +61,7 @@ public Supplier> supplier } @Override - public TriFunction, A, B, Runnable> accumulator() { + public @NonNull TriFunction, A, B, Runnable> accumulator() { return (resultHolder, a, b) -> composeUndo(firstAccumulator.apply(resultHolder.a(), a, b), secondAccumulator.apply(resultHolder.b(), a, b), thirdAccumulator.apply(resultHolder.c(), a, b)); @@ -74,7 +76,7 @@ private static Runnable composeUndo(Runnable first, Runnable second, Runnable th } @Override - public Function, Result_> finisher() { + public @NonNull Function, Result_> finisher() { return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.a()), secondFinisher.apply(resultHolder.b()), thirdFinisher.apply(resultHolder.c())); diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ComposeTwoBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ComposeTwoBiCollector.java index 46875e0836..82c641e267 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ComposeTwoBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ComposeTwoBiCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector; import ai.timefold.solver.core.impl.util.Pair; +import org.jspecify.annotations.NonNull; + final class ComposeTwoBiCollector implements BiConstraintCollector, Result_> { private final BiConstraintCollector first; @@ -42,12 +44,12 @@ final class ComposeTwoBiCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> new Pair<>(firstSupplier.get(), secondSupplier.get()); } @Override - public TriFunction, A, B, Runnable> accumulator() { + public @NonNull TriFunction, A, B, Runnable> accumulator() { return (resultHolder, a, b) -> composeUndo(firstAccumulator.apply(resultHolder.key(), a, b), secondAccumulator.apply(resultHolder.value(), a, b)); } @@ -60,7 +62,7 @@ private static Runnable composeUndo(Runnable first, Runnable second) { } @Override - public Function, Result_> finisher() { + public @NonNull Function, Result_> finisher() { return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.key()), secondFinisher.apply(resultHolder.value())); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ConditionalBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ConditionalBiCollector.java index f9992214e5..caee5f1e7e 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ConditionalBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ConditionalBiCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + final class ConditionalBiCollector implements BiConstraintCollector { private final BiPredicate predicate; @@ -23,12 +25,12 @@ final class ConditionalBiCollector } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return delegate.supplier(); } @Override - public TriFunction accumulator() { + public @NonNull TriFunction accumulator() { return (resultContainer, a, b) -> { if (predicate.test(a, b)) { return innerAccumulator.apply(resultContainer, a, b); @@ -39,7 +41,7 @@ public TriFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return delegate.finisher(); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ConnectedRangesBiConstraintCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ConnectedRangesBiConstraintCollector.java index cd7efd836c..d7fad0d070 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ConnectedRangesBiConstraintCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ConnectedRangesBiConstraintCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.ConnectedRangesCalculator; import ai.timefold.solver.core.impl.score.stream.collector.connected_ranges.Range; +import org.jspecify.annotations.NonNull; + final class ConnectedRangesBiConstraintCollector, Difference_ extends Comparable> extends ObjectCalculatorBiCollector, Range, ConnectedRangesCalculator> { @@ -27,7 +29,7 @@ public ConnectedRangesBiConstraintCollector(BiFunction> supplier() { + public @NonNull Supplier> supplier() { return () -> new ConnectedRangesCalculator<>(startMap, endMap, differenceFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ConsecutiveSequencesBiConstraintCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ConsecutiveSequencesBiConstraintCollector.java index 4831d7bca4..f0f36609a0 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ConsecutiveSequencesBiConstraintCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ConsecutiveSequencesBiConstraintCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.common.SequenceChain; import ai.timefold.solver.core.impl.score.stream.collector.SequenceCalculator; +import org.jspecify.annotations.NonNull; + final class ConsecutiveSequencesBiConstraintCollector extends ObjectCalculatorBiCollector, Result_, SequenceCalculator> { @@ -20,7 +22,7 @@ public ConsecutiveSequencesBiConstraintCollector(BiFunction resul } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> new SequenceCalculator<>(indexMap); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountDistinctIntBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountDistinctIntBiCollector.java index 8775aa525a..e2e0fa7dfb 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountDistinctIntBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountDistinctIntBiCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.IntDistinctCountCalculator; +import org.jspecify.annotations.NonNull; + final class CountDistinctIntBiCollector extends ObjectCalculatorBiCollector> { CountDistinctIntBiCollector(BiFunction mapper) { @@ -12,7 +14,7 @@ final class CountDistinctIntBiCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return IntDistinctCountCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountDistinctLongBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountDistinctLongBiCollector.java index 4c83171952..a5623a2a24 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountDistinctLongBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountDistinctLongBiCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.LongDistinctCountCalculator; +import org.jspecify.annotations.NonNull; + final class CountDistinctLongBiCollector extends ObjectCalculatorBiCollector> { CountDistinctLongBiCollector(BiFunction mapper) { @@ -12,7 +14,7 @@ final class CountDistinctLongBiCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return LongDistinctCountCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountIntBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountIntBiCollector.java index e1e4ae2f94..305be62558 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountIntBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountIntBiCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.IntCounter; +import org.jspecify.annotations.NonNull; + final class CountIntBiCollector implements BiConstraintCollector { private final static CountIntBiCollector INSTANCE = new CountIntBiCollector<>(); @@ -19,12 +21,12 @@ static CountIntBiCollector getInstance() { } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return IntCounter::new; } @Override - public TriFunction accumulator() { + public @NonNull TriFunction accumulator() { return (counter, a, b) -> { counter.increment(); return counter::decrement; @@ -32,7 +34,7 @@ public TriFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return IntCounter::result; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountLongBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountLongBiCollector.java index 8343de1cc5..6113b2b826 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountLongBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/CountLongBiCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.LongCounter; +import org.jspecify.annotations.NonNull; + final class CountLongBiCollector implements BiConstraintCollector { private final static CountLongBiCollector INSTANCE = new CountLongBiCollector<>(); @@ -19,12 +21,12 @@ static CountLongBiCollector getInstance() { } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return LongCounter::new; } @Override - public TriFunction accumulator() { + public @NonNull TriFunction accumulator() { return (counter, a, b) -> { counter.increment(); return counter::decrement; @@ -32,7 +34,7 @@ public TriFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return LongCounter::result; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/IntCalculatorBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/IntCalculatorBiCollector.java index 14588984ef..414f96d3f6 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/IntCalculatorBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/IntCalculatorBiCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.IntCalculator; +import org.jspecify.annotations.NonNull; + abstract sealed class IntCalculatorBiCollector> implements BiConstraintCollector permits AverageIntBiCollector, SumIntBiCollector { private final ToIntBiFunction mapper; @@ -17,7 +19,7 @@ public IntCalculatorBiCollector(ToIntBiFunction mapper) { } @Override - public TriFunction accumulator() { + public @NonNull TriFunction accumulator() { return (calculator, a, b) -> { final int mapped = mapper.applyAsInt(a, b); calculator.insert(mapped); @@ -26,7 +28,7 @@ public TriFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return IntCalculator::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/LoadBalanceBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/LoadBalanceBiCollector.java index 974b964a67..37c106ad75 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/LoadBalanceBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/LoadBalanceBiCollector.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.api.score.stream.common.LoadBalance; import ai.timefold.solver.core.impl.score.stream.collector.LoadBalanceImpl; +import org.jspecify.annotations.NonNull; + final class LoadBalanceBiCollector implements BiConstraintCollector, LoadBalance> { @@ -26,12 +28,12 @@ public LoadBalanceBiCollector(BiFunction balancedItemFunction, } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return LoadBalanceImpl::new; } @Override - public TriFunction, A, B, Runnable> accumulator() { + public @NonNull TriFunction, A, B, Runnable> accumulator() { return (balanceStatistics, a, b) -> { var balanced = balancedItemFunction.apply(a, b); var initialLoad = initialLoadFunction.applyAsLong(a, b); @@ -41,7 +43,7 @@ public TriFunction, A, B, Runnable> accumulator() { } @Override - public Function, LoadBalance> finisher() { + public @NonNull Function, LoadBalance> finisher() { return balanceStatistics -> balanceStatistics; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/LongCalculatorBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/LongCalculatorBiCollector.java index 760464246d..c465541881 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/LongCalculatorBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/LongCalculatorBiCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.LongCalculator; +import org.jspecify.annotations.NonNull; + abstract sealed class LongCalculatorBiCollector> implements BiConstraintCollector permits AverageLongBiCollector, SumLongBiCollector { private final ToLongBiFunction mapper; @@ -17,7 +19,7 @@ public LongCalculatorBiCollector(ToLongBiFunction mapper) } @Override - public TriFunction accumulator() { + public @NonNull TriFunction accumulator() { return (calculator, a, b) -> { final long mapped = mapper.applyAsLong(a, b); calculator.insert(mapped); @@ -26,7 +28,7 @@ public TriFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return LongCalculator::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MaxComparableBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MaxComparableBiCollector.java index 1d8c38ef63..5021d8c5ed 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MaxComparableBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MaxComparableBiCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MaxComparableBiCollector> extends UndoableActionableBiCollector> { MaxComparableBiCollector(BiFunction mapper) { @@ -12,7 +14,7 @@ final class MaxComparableBiCollector> supplier() { + public @NonNull Supplier> supplier() { return MinMaxUndoableActionable::maxCalculator; } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MaxComparatorBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MaxComparatorBiCollector.java index 86ac71fe8f..b91df7085c 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MaxComparatorBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MaxComparatorBiCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MaxComparatorBiCollector extends UndoableActionableBiCollector> { private final Comparator comparator; @@ -18,7 +20,7 @@ final class MaxComparatorBiCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.maxCalculator(comparator); } @@ -38,4 +40,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), comparator); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MaxPropertyBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MaxPropertyBiCollector.java index df675c2ebc..820df03ab6 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MaxPropertyBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MaxPropertyBiCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MaxPropertyBiCollector> extends UndoableActionableBiCollector> { private final Function propertyMapper; @@ -18,7 +20,7 @@ final class MaxPropertyBiCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.maxCalculator(propertyMapper); } @@ -38,4 +40,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), propertyMapper); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MinComparableBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MinComparableBiCollector.java index af950f1262..8e60d8702f 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MinComparableBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MinComparableBiCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MinComparableBiCollector> extends UndoableActionableBiCollector> { MinComparableBiCollector(BiFunction mapper) { @@ -12,7 +14,7 @@ final class MinComparableBiCollector> supplier() { + public @NonNull Supplier> supplier() { return MinMaxUndoableActionable::minCalculator; } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MinComparatorBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MinComparatorBiCollector.java index 1253564eaf..4848ce7e23 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MinComparatorBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MinComparatorBiCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MinComparatorBiCollector extends UndoableActionableBiCollector> { private final Comparator comparator; @@ -18,7 +20,7 @@ final class MinComparatorBiCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.minCalculator(comparator); } @@ -38,4 +40,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), comparator); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MinPropertyBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MinPropertyBiCollector.java index 692c4c223d..0be6403f97 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MinPropertyBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/MinPropertyBiCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MinPropertyBiCollector> extends UndoableActionableBiCollector> { private final Function propertyMapper; @@ -18,7 +20,7 @@ final class MinPropertyBiCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.minCalculator(propertyMapper); } @@ -38,4 +40,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), propertyMapper); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ObjectCalculatorBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ObjectCalculatorBiCollector.java index 418ac70bea..a584e4e3df 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ObjectCalculatorBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ObjectCalculatorBiCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.ObjectCalculator; +import org.jspecify.annotations.NonNull; + abstract sealed class ObjectCalculatorBiCollector> implements BiConstraintCollector permits AverageReferenceBiCollector, ConnectedRangesBiConstraintCollector, ConsecutiveSequencesBiConstraintCollector, @@ -19,7 +21,7 @@ public ObjectCalculatorBiCollector(BiFunction accumulator() { + public @NonNull TriFunction accumulator() { return (calculator, a, b) -> { final var mapped = mapper.apply(a, b); final var saved = calculator.insert(mapped); @@ -28,7 +30,7 @@ public TriFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return ObjectCalculator::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/SumIntBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/SumIntBiCollector.java index c08747afd3..cd3691233d 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/SumIntBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/SumIntBiCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.impl.score.stream.collector.IntSumCalculator; +import org.jspecify.annotations.NonNull; + final class SumIntBiCollector extends IntCalculatorBiCollector { SumIntBiCollector(ToIntBiFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return IntSumCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/SumLongBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/SumLongBiCollector.java index f273564948..62bc7c01ef 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/SumLongBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/SumLongBiCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.impl.score.stream.collector.LongSumCalculator; +import org.jspecify.annotations.NonNull; + final class SumLongBiCollector extends LongCalculatorBiCollector { SumLongBiCollector(ToLongBiFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return LongSumCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/SumReferenceBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/SumReferenceBiCollector.java index 25e499ea66..3b4aaae998 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/SumReferenceBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/SumReferenceBiCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.ReferenceSumCalculator; +import org.jspecify.annotations.NonNull; + final class SumReferenceBiCollector extends ObjectCalculatorBiCollector> { private final Result_ zero; @@ -23,7 +25,7 @@ final class SumReferenceBiCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> new ReferenceSumCalculator<>(zero, adder, subtractor); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToCollectionBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToCollectionBiCollector.java index bfb35064f6..2ace0ba2c2 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToCollectionBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToCollectionBiCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.CustomCollectionUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToCollectionBiCollector> extends UndoableActionableBiCollector> { private final IntFunction collectionFunction; @@ -19,7 +21,7 @@ final class ToCollectionBiCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> new CustomCollectionUndoableActionable<>(collectionFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToListBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToListBiCollector.java index 5b2620817c..d0df6849ea 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToListBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToListBiCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.ListUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToListBiCollector extends UndoableActionableBiCollector, ListUndoableActionable> { ToListBiCollector(BiFunction mapper) { @@ -13,7 +15,7 @@ final class ToListBiCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return ListUndoableActionable::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToMultiMapBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToMultiMapBiCollector.java index ad0437cb0e..c02a117520 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToMultiMapBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToMultiMapBiCollector.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MapUndoableActionable; import ai.timefold.solver.core.impl.util.Pair; +import org.jspecify.annotations.NonNull; + final class ToMultiMapBiCollector, Result_ extends Map> extends UndoableActionableBiCollector, Result_, MapUndoableActionable> { @@ -30,7 +32,7 @@ final class ToMultiMapBiCollector, } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> MapUndoableActionable.multiMap(mapSupplier, setFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToSetBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToSetBiCollector.java index 3be9ada650..f9887a2cd1 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToSetBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToSetBiCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.SetUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToSetBiCollector extends UndoableActionableBiCollector, SetUndoableActionable> { ToSetBiCollector(BiFunction mapper) { @@ -13,7 +15,7 @@ final class ToSetBiCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return SetUndoableActionable::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToSimpleMapBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToSimpleMapBiCollector.java index 4f3bfe0026..07f5b2169e 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToSimpleMapBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToSimpleMapBiCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MapUndoableActionable; import ai.timefold.solver.core.impl.util.Pair; +import org.jspecify.annotations.NonNull; + final class ToSimpleMapBiCollector> extends UndoableActionableBiCollector, Result_, MapUndoableActionable> { @@ -29,7 +31,7 @@ final class ToSimpleMapBiCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MapUndoableActionable.mergeMap(mapSupplier, mergeFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToSortedSetComparatorBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToSortedSetComparatorBiCollector.java index c064c5b119..7e07297ce4 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToSortedSetComparatorBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/ToSortedSetComparatorBiCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.SortedSetUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToSortedSetComparatorBiCollector extends UndoableActionableBiCollector, SortedSetUndoableActionable> { private final Comparator comparator; @@ -19,7 +21,7 @@ final class ToSortedSetComparatorBiCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> SortedSetUndoableActionable.orderBy(comparator); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/UndoableActionableBiCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/UndoableActionableBiCollector.java index a7d3366d77..f6ebfedb95 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/UndoableActionableBiCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/bi/UndoableActionableBiCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.bi.BiConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.UndoableActionable; +import org.jspecify.annotations.NonNull; + abstract sealed class UndoableActionableBiCollector> implements BiConstraintCollector permits MaxComparableBiCollector, MaxComparatorBiCollector, MaxPropertyBiCollector, MinComparableBiCollector, @@ -20,7 +22,7 @@ public UndoableActionableBiCollector(BiFunction accumulator() { + public @NonNull TriFunction accumulator() { return (calculator, a, b) -> { final Input_ mapped = mapper.apply(a, b); return calculator.insert(mapped); @@ -28,7 +30,7 @@ public TriFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return UndoableActionable::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/connected_ranges/ConnectedRangeChainImpl.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/connected_ranges/ConnectedRangeChainImpl.java index bb55f8c7b3..fa494084c8 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/connected_ranges/ConnectedRangeChainImpl.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/connected_ranges/ConnectedRangeChainImpl.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.api.score.stream.common.ConnectedRangeChain; import ai.timefold.solver.core.api.score.stream.common.RangeGap; +import org.jspecify.annotations.NonNull; + public final class ConnectedRangeChainImpl, Difference_ extends Comparable> implements ConnectedRangeChain { @@ -240,12 +242,12 @@ void removeRange(Range range) { } @Override - public Iterable> getConnectedRanges() { + public @NonNull Iterable> getConnectedRanges() { return (Iterable) startSplitPointToConnectedRange.values(); } @Override - public Iterable> getGaps() { + public @NonNull Iterable> getGaps() { return (Iterable) startSplitPointToNextGap.values(); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/connected_ranges/ConnectedRangeImpl.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/connected_ranges/ConnectedRangeImpl.java index ac00933d07..57e316f502 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/connected_ranges/ConnectedRangeImpl.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/connected_ranges/ConnectedRangeImpl.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.score.stream.common.ConnectedRange; +import org.jspecify.annotations.NonNull; + final class ConnectedRangeImpl, Difference_ extends Comparable> implements ConnectedRange { @@ -133,17 +135,17 @@ public int getMaximumOverlap() { } @Override - public Point_ getStart() { + public @NonNull Point_ getStart() { return startSplitPoint.splitPoint; } @Override - public Point_ getEnd() { + public @NonNull Point_ getEnd() { return endSplitPoint.splitPoint; } @Override - public Difference_ getLength() { + public @NonNull Difference_ getLength() { return differenceFunction.apply(startSplitPoint.splitPoint, endSplitPoint.splitPoint); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/connected_ranges/RangeGapImpl.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/connected_ranges/RangeGapImpl.java index 8edd9d1d7e..c867419a41 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/connected_ranges/RangeGapImpl.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/connected_ranges/RangeGapImpl.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.score.stream.common.ConnectedRange; import ai.timefold.solver.core.api.score.stream.common.RangeGap; +import org.jspecify.annotations.NonNull; + final class RangeGapImpl, Difference_ extends Comparable> implements RangeGap { private ConnectedRange previousConnectedRange; @@ -27,17 +29,17 @@ ConnectedRange getNextConnectedRange() { } @Override - public Point_ getPreviousRangeEnd() { + public @NonNull Point_ getPreviousRangeEnd() { return previousConnectedRange.getEnd(); } @Override - public Point_ getNextRangeStart() { + public @NonNull Point_ getNextRangeStart() { return nextConnectedRange.getStart(); } @Override - public Difference_ getLength() { + public @NonNull Difference_ getLength() { return length; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/consecutive/BreakImpl.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/consecutive/BreakImpl.java index 84ea6de7c9..de204d51bc 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/consecutive/BreakImpl.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/consecutive/BreakImpl.java @@ -2,6 +2,8 @@ import ai.timefold.solver.core.api.score.stream.common.Break; +import org.jspecify.annotations.NonNull; + /** * When adding fields, remember to add them to the JSON serialization code as well, if you want them exposed. * @@ -33,17 +35,17 @@ public boolean isLast() { } @Override - public Value_ getPreviousSequenceEnd() { + public @NonNull Value_ getPreviousSequenceEnd() { return previousSequence.lastItem.value(); } @Override - public Value_ getNextSequenceStart() { + public @NonNull Value_ getNextSequenceStart() { return nextSequence.firstItem.value(); } @Override - public Difference_ getLength() { + public @NonNull Difference_ getLength() { return length; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/consecutive/ConsecutiveSetTree.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/consecutive/ConsecutiveSetTree.java index c171f500fb..5170f6e1e3 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/consecutive/ConsecutiveSetTree.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/consecutive/ConsecutiveSetTree.java @@ -14,6 +14,9 @@ import ai.timefold.solver.core.api.score.stream.common.Sequence; import ai.timefold.solver.core.api.score.stream.common.SequenceChain; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * A {@code ConsecutiveSetTree} determines what values are consecutive. * A sequence x1, x2, x3, ..., xn @@ -53,17 +56,17 @@ public ConsecutiveSetTree(BiFunction differenceFunc } @Override - public Collection> getConsecutiveSequences() { + public @NonNull Collection> getConsecutiveSequences() { return Collections.unmodifiableCollection(startItemToSequence.values()); } @Override - public Collection> getBreaks() { + public @NonNull Collection> getBreaks() { return Collections.unmodifiableCollection(startItemToPreviousBreak.values()); } @Override - public Sequence getFirstSequence() { + public @Nullable Sequence getFirstSequence() { if (startItemToSequence.isEmpty()) { return null; } @@ -71,7 +74,7 @@ public Sequence getFirstSequence() { } @Override - public Sequence getLastSequence() { + public @Nullable Sequence getLastSequence() { if (startItemToSequence.isEmpty()) { return null; } @@ -79,7 +82,7 @@ public Sequence getLastSequence() { } @Override - public Break getFirstBreak() { + public @Nullable Break getFirstBreak() { if (startItemToSequence.size() <= 1) { return null; } @@ -87,7 +90,7 @@ public Break getFirstBreak() { } @Override - public Break getLastBreak() { + public @Nullable Break getLastBreak() { if (startItemToSequence.size() <= 1) { return null; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/consecutive/SequenceImpl.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/consecutive/SequenceImpl.java index 57d5c2ae1c..45348b0f61 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/consecutive/SequenceImpl.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/consecutive/SequenceImpl.java @@ -8,6 +8,9 @@ import ai.timefold.solver.core.api.score.stream.common.Break; import ai.timefold.solver.core.api.score.stream.common.Sequence; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * When adding fields, remember to add them to the JSON serialization code as well, if you want them exposed. * @@ -42,22 +45,22 @@ final class SequenceImpl, Difference_ } @Override - public Value_ getFirstItem() { + public @NonNull Value_ getFirstItem() { return firstItem.value(); } @Override - public Value_ getLastItem() { + public @NonNull Value_ getLastItem() { return lastItem.value(); } @Override - public Break getPreviousBreak() { + public @Nullable Break getPreviousBreak() { return sourceTree.getBreakBefore(firstItem); } @Override - public Break getNextBreak() { + public @Nullable Break getNextBreak() { return sourceTree.getBreakAfter(lastItem); } @@ -72,7 +75,7 @@ public boolean isLast() { } @Override - public Collection getItems() { + public @NonNull Collection getItems() { if (items == null) { return items = getComparableItems().values(); } @@ -93,7 +96,7 @@ public int getCount() { } @Override - public Difference_ getLength() { + public @NonNull Difference_ getLength() { if (length == null) { // memoize length for later calls // (assignment returns the right hand side) diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AndThenQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AndThenQuadCollector.java index 6a74567b6f..0f2db57489 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AndThenQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AndThenQuadCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.PentaFunction; import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintCollector; +import org.jspecify.annotations.NonNull; + final class AndThenQuadCollector implements QuadConstraintCollector { @@ -20,17 +22,17 @@ final class AndThenQuadCollector supplier() { + public @NonNull Supplier supplier() { return delegate.supplier(); } @Override - public PentaFunction accumulator() { + public @NonNull PentaFunction accumulator() { return delegate.accumulator(); } @Override - public Function finisher() { + public @NonNull Function finisher() { var finisher = delegate.finisher(); return container -> mappingFunction.apply(finisher.apply(container)); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AverageIntQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AverageIntQuadCollector.java index 80009c7108..1631244b7d 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AverageIntQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AverageIntQuadCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.function.ToIntQuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.IntAverageCalculator; +import org.jspecify.annotations.NonNull; + final class AverageIntQuadCollector extends IntCalculatorQuadCollector { AverageIntQuadCollector(ToIntQuadFunction mapper) { @@ -12,7 +14,7 @@ final class AverageIntQuadCollector } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return IntAverageCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AverageLongQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AverageLongQuadCollector.java index eebd312177..cee19fb8f2 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AverageLongQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AverageLongQuadCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.function.ToLongQuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.LongAverageCalculator; +import org.jspecify.annotations.NonNull; + final class AverageLongQuadCollector extends LongCalculatorQuadCollector { AverageLongQuadCollector(ToLongQuadFunction mapper) { @@ -12,7 +14,7 @@ final class AverageLongQuadCollector } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return LongAverageCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AverageReferenceQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AverageReferenceQuadCollector.java index c1e8998dde..0c49331519 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AverageReferenceQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/AverageReferenceQuadCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.ReferenceAverageCalculator; +import org.jspecify.annotations.NonNull; + final class AverageReferenceQuadCollector extends ObjectCalculatorQuadCollector> { @@ -18,7 +20,7 @@ final class AverageReferenceQuadCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return calculatorSupplier; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ComposeFourQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ComposeFourQuadCollector.java index dab481973e..c016de0300 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ComposeFourQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ComposeFourQuadCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintCollector; import ai.timefold.solver.core.impl.util.Quadruple; +import org.jspecify.annotations.NonNull; + final class ComposeFourQuadCollector implements QuadConstraintCollector, Result_> { @@ -61,7 +63,7 @@ final class ComposeFourQuadCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> { ResultHolder1_ a = firstSupplier.get(); ResultHolder2_ b = secondSupplier.get(); @@ -71,7 +73,8 @@ public Supplier, A, B, C, D, Runnable> + public @NonNull + PentaFunction, A, B, C, D, Runnable> accumulator() { return (resultHolder, a, b, c, d) -> composeUndo(firstAccumulator.apply(resultHolder.a(), a, b, c, d), secondAccumulator.apply(resultHolder.b(), a, b, c, d), @@ -90,7 +93,7 @@ private static Runnable composeUndo(Runnable first, Runnable second, Runnable th } @Override - public Function, Result_> finisher() { + public @NonNull Function, Result_> finisher() { return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.a()), secondFinisher.apply(resultHolder.b()), thirdFinisher.apply(resultHolder.c()), diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ComposeThreeQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ComposeThreeQuadCollector.java index 72c42e40a1..437a267e80 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ComposeThreeQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ComposeThreeQuadCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintCollector; import ai.timefold.solver.core.impl.util.Triple; +import org.jspecify.annotations.NonNull; + final class ComposeThreeQuadCollector implements QuadConstraintCollector, Result_> { private final QuadConstraintCollector first; @@ -51,7 +53,7 @@ final class ComposeThreeQuadCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> { ResultHolder1_ a = firstSupplier.get(); ResultHolder2_ b = secondSupplier.get(); @@ -60,7 +62,7 @@ public Supplier> supplier } @Override - public PentaFunction, A, B, C, D, Runnable> accumulator() { + public @NonNull PentaFunction, A, B, C, D, Runnable> accumulator() { return (resultHolder, a, b, c, d) -> composeUndo(firstAccumulator.apply(resultHolder.a(), a, b, c, d), secondAccumulator.apply(resultHolder.b(), a, b, c, d), thirdAccumulator.apply(resultHolder.c(), a, b, c, d)); @@ -75,7 +77,7 @@ private static Runnable composeUndo(Runnable first, Runnable second, Runnable th } @Override - public Function, Result_> finisher() { + public @NonNull Function, Result_> finisher() { return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.a()), secondFinisher.apply(resultHolder.b()), thirdFinisher.apply(resultHolder.c())); diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ComposeTwoQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ComposeTwoQuadCollector.java index 0ba09679e6..db4e1ece60 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ComposeTwoQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ComposeTwoQuadCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintCollector; import ai.timefold.solver.core.impl.util.Pair; +import org.jspecify.annotations.NonNull; + final class ComposeTwoQuadCollector implements QuadConstraintCollector, Result_> { private final QuadConstraintCollector first; @@ -42,12 +44,12 @@ final class ComposeTwoQuadCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> new Pair<>(firstSupplier.get(), secondSupplier.get()); } @Override - public PentaFunction, A, B, C, D, Runnable> accumulator() { + public @NonNull PentaFunction, A, B, C, D, Runnable> accumulator() { return (resultHolder, a, b, c, d) -> composeUndo(firstAccumulator.apply(resultHolder.key(), a, b, c, d), secondAccumulator.apply(resultHolder.value(), a, b, c, d)); } @@ -60,7 +62,7 @@ private static Runnable composeUndo(Runnable first, Runnable second) { } @Override - public Function, Result_> finisher() { + public @NonNull Function, Result_> finisher() { return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.key()), secondFinisher.apply(resultHolder.value())); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ConditionalQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ConditionalQuadCollector.java index 348b80d627..6e4391b51f 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ConditionalQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ConditionalQuadCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintCollector; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + final class ConditionalQuadCollector implements QuadConstraintCollector { private final QuadPredicate predicate; @@ -23,12 +25,12 @@ final class ConditionalQuadCollector } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return delegate.supplier(); } @Override - public PentaFunction accumulator() { + public @NonNull PentaFunction accumulator() { return (resultContainer, a, b, c, d) -> { if (predicate.test(a, b, c, d)) { return innerAccumulator.apply(resultContainer, a, b, c, d); @@ -39,7 +41,7 @@ public PentaFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return delegate.finisher(); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ConnectedRangesQuadConstraintCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ConnectedRangesQuadConstraintCollector.java index cf241a37bf..d876648941 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ConnectedRangesQuadConstraintCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ConnectedRangesQuadConstraintCollector.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.ConnectedRangesCalculator; import ai.timefold.solver.core.impl.score.stream.collector.connected_ranges.Range; +import org.jspecify.annotations.NonNull; + final class ConnectedRangesQuadConstraintCollector, Difference_ extends Comparable> extends ObjectCalculatorQuadCollector, Range, ConnectedRangesCalculator> { @@ -29,7 +31,7 @@ public ConnectedRangesQuadConstraintCollector( } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> new ConnectedRangesCalculator<>(startMap, endMap, differenceFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ConsecutiveSequencesQuadConstraintCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ConsecutiveSequencesQuadConstraintCollector.java index 48378a9817..0df054befd 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ConsecutiveSequencesQuadConstraintCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ConsecutiveSequencesQuadConstraintCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.common.SequenceChain; import ai.timefold.solver.core.impl.score.stream.collector.SequenceCalculator; +import org.jspecify.annotations.NonNull; + final class ConsecutiveSequencesQuadConstraintCollector extends ObjectCalculatorQuadCollector, Result_, SequenceCalculator> { @@ -21,7 +23,7 @@ public ConsecutiveSequencesQuadConstraintCollector(QuadFunction> supplier() { + public @NonNull Supplier> supplier() { return () -> new SequenceCalculator<>(indexMap); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountDistinctIntQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountDistinctIntQuadCollector.java index cb16d5bb31..71bce9ae42 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountDistinctIntQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountDistinctIntQuadCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.IntDistinctCountCalculator; +import org.jspecify.annotations.NonNull; + final class CountDistinctIntQuadCollector extends ObjectCalculatorQuadCollector> { CountDistinctIntQuadCollector(QuadFunction mapper) { @@ -12,7 +14,7 @@ final class CountDistinctIntQuadCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return IntDistinctCountCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountDistinctLongQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountDistinctLongQuadCollector.java index f1dcc17573..c9748bfabd 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountDistinctLongQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountDistinctLongQuadCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.LongDistinctCountCalculator; +import org.jspecify.annotations.NonNull; + final class CountDistinctLongQuadCollector extends ObjectCalculatorQuadCollector> { CountDistinctLongQuadCollector(QuadFunction mapper) { @@ -12,7 +14,7 @@ final class CountDistinctLongQuadCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return LongDistinctCountCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountIntQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountIntQuadCollector.java index 7148bdf25e..34ed6ea67b 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountIntQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountIntQuadCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.IntCounter; +import org.jspecify.annotations.NonNull; + final class CountIntQuadCollector implements QuadConstraintCollector { private final static CountIntQuadCollector INSTANCE = new CountIntQuadCollector<>(); @@ -19,12 +21,12 @@ static CountIntQuadCollector getInstance() { } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return IntCounter::new; } @Override - public PentaFunction accumulator() { + public @NonNull PentaFunction accumulator() { return (counter, a, b, c, d) -> { counter.increment(); return counter::decrement; @@ -32,7 +34,7 @@ public PentaFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return IntCounter::result; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountLongQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountLongQuadCollector.java index 8e25e11156..7308edc0f5 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountLongQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/CountLongQuadCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.LongCounter; +import org.jspecify.annotations.NonNull; + final class CountLongQuadCollector implements QuadConstraintCollector { private final static CountLongQuadCollector INSTANCE = new CountLongQuadCollector<>(); @@ -19,12 +21,12 @@ static CountLongQuadCollector getInstance() { } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return LongCounter::new; } @Override - public PentaFunction accumulator() { + public @NonNull PentaFunction accumulator() { return (counter, a, b, c, d) -> { counter.increment(); return counter::decrement; @@ -32,7 +34,7 @@ public PentaFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return LongCounter::result; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/IntCalculatorQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/IntCalculatorQuadCollector.java index 835cffa347..9eafb2b1c0 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/IntCalculatorQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/IntCalculatorQuadCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.IntCalculator; +import org.jspecify.annotations.NonNull; + abstract sealed class IntCalculatorQuadCollector> implements QuadConstraintCollector permits AverageIntQuadCollector, SumIntQuadCollector { @@ -18,7 +20,7 @@ public IntCalculatorQuadCollector(ToIntQuadFunction accumulator() { + public @NonNull PentaFunction accumulator() { return (calculator, a, b, c, d) -> { final int mapped = mapper.applyAsInt(a, b, c, d); calculator.insert(mapped); @@ -27,7 +29,7 @@ public PentaFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return IntCalculator::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/LoadBalanceQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/LoadBalanceQuadCollector.java index 29fd28ed95..1eee9a0b4b 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/LoadBalanceQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/LoadBalanceQuadCollector.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.LoadBalanceImpl; +import org.jspecify.annotations.NonNull; + final class LoadBalanceQuadCollector implements QuadConstraintCollector, LoadBalance> { @@ -26,12 +28,12 @@ public LoadBalanceQuadCollector(QuadFunction balancedItem } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return LoadBalanceImpl::new; } @Override - public PentaFunction, A, B, C, D, Runnable> accumulator() { + public @NonNull PentaFunction, A, B, C, D, Runnable> accumulator() { return (balanceStatistics, a, b, c, d) -> { var balanced = balancedItemFunction.apply(a, b, c, d); var initialLoad = initialLoadFunction.applyAsLong(a, b, c, d); @@ -41,7 +43,7 @@ public PentaFunction, A, B, C, D, Runnable> accumulat } @Override - public Function, LoadBalance> finisher() { + public @NonNull Function, LoadBalance> finisher() { return balanceStatistics -> balanceStatistics; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/LongCalculatorQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/LongCalculatorQuadCollector.java index d2937d6073..d51e7088f1 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/LongCalculatorQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/LongCalculatorQuadCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.LongCalculator; +import org.jspecify.annotations.NonNull; + abstract sealed class LongCalculatorQuadCollector> implements QuadConstraintCollector permits AverageLongQuadCollector, SumLongQuadCollector { @@ -18,7 +20,7 @@ public LongCalculatorQuadCollector(ToLongQuadFunction accumulator() { + public @NonNull PentaFunction accumulator() { return (calculator, a, b, c, d) -> { final long mapped = mapper.applyAsLong(a, b, c, d); calculator.insert(mapped); @@ -27,7 +29,7 @@ public PentaFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return LongCalculator::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MaxComparableQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MaxComparableQuadCollector.java index 7b4ca0ae50..2ffb237cc6 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MaxComparableQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MaxComparableQuadCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MaxComparableQuadCollector> extends UndoableActionableQuadCollector> { MaxComparableQuadCollector(QuadFunction mapper) { @@ -12,7 +14,7 @@ final class MaxComparableQuadCollector> supplier() { + public @NonNull Supplier> supplier() { return MinMaxUndoableActionable::maxCalculator; } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MaxComparatorQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MaxComparatorQuadCollector.java index 399095306f..b5c67600aa 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MaxComparatorQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MaxComparatorQuadCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MaxComparatorQuadCollector extends UndoableActionableQuadCollector> { private final Comparator comparator; @@ -18,7 +20,7 @@ final class MaxComparatorQuadCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.maxCalculator(comparator); } @@ -38,4 +40,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), comparator); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MaxPropertyQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MaxPropertyQuadCollector.java index 79ef672e0c..ed72e890df 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MaxPropertyQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MaxPropertyQuadCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MaxPropertyQuadCollector> extends UndoableActionableQuadCollector> { private final Function propertyMapper; @@ -18,7 +20,7 @@ final class MaxPropertyQuadCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.maxCalculator(propertyMapper); } @@ -38,4 +40,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), propertyMapper); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MinComparableQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MinComparableQuadCollector.java index c4af37503d..e907f1b223 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MinComparableQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MinComparableQuadCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MinComparableQuadCollector> extends UndoableActionableQuadCollector> { MinComparableQuadCollector(QuadFunction mapper) { @@ -12,7 +14,7 @@ final class MinComparableQuadCollector> supplier() { + public @NonNull Supplier> supplier() { return MinMaxUndoableActionable::minCalculator; } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MinComparatorQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MinComparatorQuadCollector.java index 350bca994e..8eeea5e614 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MinComparatorQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MinComparatorQuadCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MinComparatorQuadCollector extends UndoableActionableQuadCollector> { private final Comparator comparator; @@ -18,7 +20,7 @@ final class MinComparatorQuadCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.minCalculator(comparator); } @@ -38,4 +40,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), comparator); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MinPropertyQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MinPropertyQuadCollector.java index 2ff973d00f..da1893ef28 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MinPropertyQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/MinPropertyQuadCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MinPropertyQuadCollector> extends UndoableActionableQuadCollector> { private final Function propertyMapper; @@ -18,7 +20,7 @@ final class MinPropertyQuadCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.minCalculator(propertyMapper); } @@ -38,4 +40,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), propertyMapper); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ObjectCalculatorQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ObjectCalculatorQuadCollector.java index 78c300be1a..f2655e2e23 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ObjectCalculatorQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ObjectCalculatorQuadCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.ObjectCalculator; +import org.jspecify.annotations.NonNull; + abstract sealed class ObjectCalculatorQuadCollector> implements QuadConstraintCollector permits AverageReferenceQuadCollector, ConnectedRangesQuadConstraintCollector, @@ -21,7 +23,7 @@ public ObjectCalculatorQuadCollector(QuadFunction accumulator() { + public @NonNull PentaFunction accumulator() { return (calculator, a, b, c, d) -> { final var mapped = mapper.apply(a, b, c, d); final var saved = calculator.insert(mapped); @@ -30,7 +32,7 @@ public PentaFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return ObjectCalculator::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/SumIntQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/SumIntQuadCollector.java index 37d9e8c353..0c2ac590a2 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/SumIntQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/SumIntQuadCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.api.function.ToIntQuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.IntSumCalculator; +import org.jspecify.annotations.NonNull; + final class SumIntQuadCollector extends IntCalculatorQuadCollector { SumIntQuadCollector(ToIntQuadFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return IntSumCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/SumLongQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/SumLongQuadCollector.java index 7ee21f8940..7d66343651 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/SumLongQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/SumLongQuadCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.api.function.ToLongQuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.LongSumCalculator; +import org.jspecify.annotations.NonNull; + final class SumLongQuadCollector extends LongCalculatorQuadCollector { SumLongQuadCollector(ToLongQuadFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return LongSumCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/SumReferenceQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/SumReferenceQuadCollector.java index da49633c8e..1e3f24f6c2 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/SumReferenceQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/SumReferenceQuadCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.ReferenceSumCalculator; +import org.jspecify.annotations.NonNull; + final class SumReferenceQuadCollector extends ObjectCalculatorQuadCollector> { private final Result_ zero; @@ -24,7 +26,7 @@ final class SumReferenceQuadCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> new ReferenceSumCalculator<>(zero, adder, subtractor); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToCollectionQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToCollectionQuadCollector.java index 2fee5b28fc..7ae554e6a0 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToCollectionQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToCollectionQuadCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.CustomCollectionUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToCollectionQuadCollector> extends UndoableActionableQuadCollector> { @@ -20,7 +22,7 @@ final class ToCollectionQuadCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> new CustomCollectionUndoableActionable<>(collectionFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToListQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToListQuadCollector.java index c1293dbe93..ea3fc75aae 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToListQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToListQuadCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.ListUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToListQuadCollector extends UndoableActionableQuadCollector, ListUndoableActionable> { ToListQuadCollector(QuadFunction mapper) { @@ -13,7 +15,7 @@ final class ToListQuadCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return ListUndoableActionable::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToMultiMapQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToMultiMapQuadCollector.java index dd9f1a6a8e..9cccd28f8c 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToMultiMapQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToMultiMapQuadCollector.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MapUndoableActionable; import ai.timefold.solver.core.impl.util.Pair; +import org.jspecify.annotations.NonNull; + final class ToMultiMapQuadCollector, Result_ extends Map> extends UndoableActionableQuadCollector, Result_, MapUndoableActionable> { @@ -30,7 +32,7 @@ final class ToMultiMapQuadCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MapUndoableActionable.multiMap(mapSupplier, setFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToSetQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToSetQuadCollector.java index cd4ef37d11..5683fac568 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToSetQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToSetQuadCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.SetUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToSetQuadCollector extends UndoableActionableQuadCollector, SetUndoableActionable> { ToSetQuadCollector(QuadFunction mapper) { @@ -13,7 +15,7 @@ final class ToSetQuadCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return SetUndoableActionable::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToSimpleMapQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToSimpleMapQuadCollector.java index 188deaf597..7ec5be37f7 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToSimpleMapQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToSimpleMapQuadCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MapUndoableActionable; import ai.timefold.solver.core.impl.util.Pair; +import org.jspecify.annotations.NonNull; + final class ToSimpleMapQuadCollector> extends UndoableActionableQuadCollector, Result_, MapUndoableActionable> { @@ -29,7 +31,7 @@ final class ToSimpleMapQuadCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MapUndoableActionable.mergeMap(mapSupplier, mergeFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToSortedSetComparatorQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToSortedSetComparatorQuadCollector.java index 7f883e03b8..ac300332fa 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToSortedSetComparatorQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/ToSortedSetComparatorQuadCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.impl.score.stream.collector.SortedSetUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToSortedSetComparatorQuadCollector extends UndoableActionableQuadCollector, SortedSetUndoableActionable> { private final Comparator comparator; @@ -19,7 +21,7 @@ final class ToSortedSetComparatorQuadCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> SortedSetUndoableActionable.orderBy(comparator); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/UndoableActionableQuadCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/UndoableActionableQuadCollector.java index 0fff906fa4..0e7831de4c 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/UndoableActionableQuadCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/quad/UndoableActionableQuadCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.quad.QuadConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.UndoableActionable; +import org.jspecify.annotations.NonNull; + abstract sealed class UndoableActionableQuadCollector> implements QuadConstraintCollector permits MaxComparableQuadCollector, MaxComparatorQuadCollector, MaxPropertyQuadCollector, MinComparableQuadCollector, @@ -20,7 +22,7 @@ public UndoableActionableQuadCollector(QuadFunction accumulator() { + public @NonNull PentaFunction accumulator() { return (calculator, a, b, c, d) -> { final Input_ mapped = mapper.apply(a, b, c, d); return calculator.insert(mapped); @@ -28,7 +30,7 @@ public PentaFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return UndoableActionable::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AndThenTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AndThenTriCollector.java index 10dfd58d78..55cf898d2d 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AndThenTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AndThenTriCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.QuadFunction; import ai.timefold.solver.core.api.score.stream.tri.TriConstraintCollector; +import org.jspecify.annotations.NonNull; + final class AndThenTriCollector implements TriConstraintCollector { @@ -20,17 +22,17 @@ final class AndThenTriCollector supplier() { + public @NonNull Supplier supplier() { return delegate.supplier(); } @Override - public QuadFunction accumulator() { + public @NonNull QuadFunction accumulator() { return delegate.accumulator(); } @Override - public Function finisher() { + public @NonNull Function finisher() { var finisher = delegate.finisher(); return container -> mappingFunction.apply(finisher.apply(container)); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AverageIntTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AverageIntTriCollector.java index b66c95f78d..f9c41e23a7 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AverageIntTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AverageIntTriCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.api.function.ToIntTriFunction; import ai.timefold.solver.core.impl.score.stream.collector.IntAverageCalculator; +import org.jspecify.annotations.NonNull; + final class AverageIntTriCollector extends IntCalculatorTriCollector { AverageIntTriCollector(ToIntTriFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return IntAverageCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AverageLongTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AverageLongTriCollector.java index c12e07325a..250f7e82c5 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AverageLongTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AverageLongTriCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.api.function.ToLongTriFunction; import ai.timefold.solver.core.impl.score.stream.collector.LongAverageCalculator; +import org.jspecify.annotations.NonNull; + final class AverageLongTriCollector extends LongCalculatorTriCollector { AverageLongTriCollector(ToLongTriFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return LongAverageCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AverageReferenceTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AverageReferenceTriCollector.java index 7c16f7cbf0..fd03cbc580 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AverageReferenceTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/AverageReferenceTriCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.ReferenceAverageCalculator; +import org.jspecify.annotations.NonNull; + final class AverageReferenceTriCollector extends ObjectCalculatorTriCollector> { @@ -18,7 +20,7 @@ final class AverageReferenceTriCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return calculatorSupplier; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ComposeFourTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ComposeFourTriCollector.java index 00e187e377..8fdcbee357 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ComposeFourTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ComposeFourTriCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.tri.TriConstraintCollector; import ai.timefold.solver.core.impl.util.Quadruple; +import org.jspecify.annotations.NonNull; + final class ComposeFourTriCollector implements TriConstraintCollector, Result_> { @@ -60,7 +62,7 @@ final class ComposeFourTriCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> { ResultHolder1_ a = firstSupplier.get(); ResultHolder2_ b = secondSupplier.get(); @@ -70,7 +72,7 @@ public Supplier, A, B, C, Runnable> + public @NonNull QuadFunction, A, B, C, Runnable> accumulator() { return (resultHolder, a, b, c) -> composeUndo(firstAccumulator.apply(resultHolder.a(), a, b, c), secondAccumulator.apply(resultHolder.b(), a, b, c), @@ -89,7 +91,7 @@ private static Runnable composeUndo(Runnable first, Runnable second, Runnable th } @Override - public Function, Result_> finisher() { + public @NonNull Function, Result_> finisher() { return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.a()), secondFinisher.apply(resultHolder.b()), thirdFinisher.apply(resultHolder.c()), diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ComposeThreeTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ComposeThreeTriCollector.java index 3ce1f2e9ba..328d051287 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ComposeThreeTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ComposeThreeTriCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.api.score.stream.tri.TriConstraintCollector; import ai.timefold.solver.core.impl.util.Triple; +import org.jspecify.annotations.NonNull; + final class ComposeThreeTriCollector implements TriConstraintCollector, Result_> { private final TriConstraintCollector first; @@ -51,7 +53,7 @@ final class ComposeThreeTriCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> { ResultHolder1_ a = firstSupplier.get(); ResultHolder2_ b = secondSupplier.get(); @@ -60,7 +62,7 @@ public Supplier> supplier } @Override - public QuadFunction, A, B, C, Runnable> accumulator() { + public @NonNull QuadFunction, A, B, C, Runnable> accumulator() { return (resultHolder, a, b, c) -> composeUndo(firstAccumulator.apply(resultHolder.a(), a, b, c), secondAccumulator.apply(resultHolder.b(), a, b, c), thirdAccumulator.apply(resultHolder.c(), a, b, c)); @@ -75,7 +77,7 @@ private static Runnable composeUndo(Runnable first, Runnable second, Runnable th } @Override - public Function, Result_> finisher() { + public @NonNull Function, Result_> finisher() { return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.a()), secondFinisher.apply(resultHolder.b()), thirdFinisher.apply(resultHolder.c())); diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ComposeTwoTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ComposeTwoTriCollector.java index 655f29e256..7449ff9a60 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ComposeTwoTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ComposeTwoTriCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.api.score.stream.tri.TriConstraintCollector; import ai.timefold.solver.core.impl.util.Pair; +import org.jspecify.annotations.NonNull; + final class ComposeTwoTriCollector implements TriConstraintCollector, Result_> { private final TriConstraintCollector first; @@ -42,12 +44,12 @@ final class ComposeTwoTriCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> new Pair<>(firstSupplier.get(), secondSupplier.get()); } @Override - public QuadFunction, A, B, C, Runnable> accumulator() { + public @NonNull QuadFunction, A, B, C, Runnable> accumulator() { return (resultHolder, a, b, c) -> composeUndo(firstAccumulator.apply(resultHolder.key(), a, b, c), secondAccumulator.apply(resultHolder.value(), a, b, c)); } @@ -60,7 +62,7 @@ private static Runnable composeUndo(Runnable first, Runnable second) { } @Override - public Function, Result_> finisher() { + public @NonNull Function, Result_> finisher() { return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.key()), secondFinisher.apply(resultHolder.value())); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ConditionalTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ConditionalTriCollector.java index a6aa5b7dd1..3079a09dd8 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ConditionalTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ConditionalTriCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.api.score.stream.tri.TriConstraintCollector; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + final class ConditionalTriCollector implements TriConstraintCollector { private final TriPredicate predicate; @@ -23,12 +25,12 @@ final class ConditionalTriCollector } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return delegate.supplier(); } @Override - public QuadFunction accumulator() { + public @NonNull QuadFunction accumulator() { return (resultContainer, a, b, c) -> { if (predicate.test(a, b, c)) { return innerAccumulator.apply(resultContainer, a, b, c); @@ -39,7 +41,7 @@ public QuadFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return delegate.finisher(); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ConnectedRangesTriConstraintCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ConnectedRangesTriConstraintCollector.java index 17a5299dda..c5a9f60103 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ConnectedRangesTriConstraintCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ConnectedRangesTriConstraintCollector.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.ConnectedRangesCalculator; import ai.timefold.solver.core.impl.score.stream.collector.connected_ranges.Range; +import org.jspecify.annotations.NonNull; + final class ConnectedRangesTriConstraintCollector, Difference_ extends Comparable> extends ObjectCalculatorTriCollector, Range, ConnectedRangesCalculator> { @@ -28,7 +30,7 @@ public ConnectedRangesTriConstraintCollector(TriFunction> supplier() { + public @NonNull Supplier> supplier() { return () -> new ConnectedRangesCalculator<>(startMap, endMap, differenceFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ConsecutiveSequencesTriConstraintCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ConsecutiveSequencesTriConstraintCollector.java index b1253b0f82..25ec307559 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ConsecutiveSequencesTriConstraintCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ConsecutiveSequencesTriConstraintCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.common.SequenceChain; import ai.timefold.solver.core.impl.score.stream.collector.SequenceCalculator; +import org.jspecify.annotations.NonNull; + final class ConsecutiveSequencesTriConstraintCollector extends ObjectCalculatorTriCollector, Result_, SequenceCalculator> { @@ -21,7 +23,7 @@ public ConsecutiveSequencesTriConstraintCollector(TriFunction } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> new SequenceCalculator<>(indexMap); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountDistinctIntTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountDistinctIntTriCollector.java index e798f38e4d..48088d96e2 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountDistinctIntTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountDistinctIntTriCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.IntDistinctCountCalculator; +import org.jspecify.annotations.NonNull; + final class CountDistinctIntTriCollector extends ObjectCalculatorTriCollector> { CountDistinctIntTriCollector(TriFunction mapper) { @@ -12,7 +14,7 @@ final class CountDistinctIntTriCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return IntDistinctCountCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountDistinctLongTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountDistinctLongTriCollector.java index 69e07017a7..bcdb227781 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountDistinctLongTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountDistinctLongTriCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.LongDistinctCountCalculator; +import org.jspecify.annotations.NonNull; + final class CountDistinctLongTriCollector extends ObjectCalculatorTriCollector> { CountDistinctLongTriCollector(TriFunction mapper) { @@ -12,7 +14,7 @@ final class CountDistinctLongTriCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return LongDistinctCountCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountIntTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountIntTriCollector.java index 375a963083..3fd07c208e 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountIntTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountIntTriCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.score.stream.tri.TriConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.IntCounter; +import org.jspecify.annotations.NonNull; + final class CountIntTriCollector implements TriConstraintCollector { private final static CountIntTriCollector INSTANCE = new CountIntTriCollector<>(); @@ -19,12 +21,12 @@ static CountIntTriCollector getInstance() { } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return IntCounter::new; } @Override - public QuadFunction accumulator() { + public @NonNull QuadFunction accumulator() { return (counter, a, b, c) -> { counter.increment(); return counter::decrement; @@ -32,7 +34,7 @@ public QuadFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return IntCounter::result; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountLongTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountLongTriCollector.java index ad62a96884..bcb1322ba3 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountLongTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/CountLongTriCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.score.stream.tri.TriConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.LongCounter; +import org.jspecify.annotations.NonNull; + final class CountLongTriCollector implements TriConstraintCollector { private final static CountLongTriCollector INSTANCE = new CountLongTriCollector<>(); @@ -19,12 +21,12 @@ static CountLongTriCollector getInstance() { } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return LongCounter::new; } @Override - public QuadFunction accumulator() { + public @NonNull QuadFunction accumulator() { return (counter, a, b, c) -> { counter.increment(); return counter::decrement; @@ -32,7 +34,7 @@ public QuadFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return LongCounter::result; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/IntCalculatorTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/IntCalculatorTriCollector.java index f962d42a64..d865e452f6 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/IntCalculatorTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/IntCalculatorTriCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.tri.TriConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.IntCalculator; +import org.jspecify.annotations.NonNull; + abstract sealed class IntCalculatorTriCollector> implements TriConstraintCollector permits AverageIntTriCollector, SumIntTriCollector { private final ToIntTriFunction mapper; @@ -17,7 +19,7 @@ public IntCalculatorTriCollector(ToIntTriFunction accumulator() { + public @NonNull QuadFunction accumulator() { return (calculator, a, b, c) -> { final int mapped = mapper.applyAsInt(a, b, c); calculator.insert(mapped); @@ -26,7 +28,7 @@ public QuadFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return IntCalculator::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/LoadBalanceTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/LoadBalanceTriCollector.java index 9072dfa870..b1695e1d92 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/LoadBalanceTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/LoadBalanceTriCollector.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.api.score.stream.tri.TriConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.LoadBalanceImpl; +import org.jspecify.annotations.NonNull; + final class LoadBalanceTriCollector implements TriConstraintCollector, LoadBalance> { @@ -27,12 +29,12 @@ public LoadBalanceTriCollector(TriFunction balancedItemFunct } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return LoadBalanceImpl::new; } @Override - public QuadFunction, A, B, C, Runnable> accumulator() { + public @NonNull QuadFunction, A, B, C, Runnable> accumulator() { return (balanceStatistics, a, b, c) -> { var balanced = balancedItemFunction.apply(a, b, c); var initialLoad = initialLoadFunction.applyAsLong(a, b, c); @@ -42,7 +44,7 @@ public QuadFunction, A, B, C, Runnable> accumulator() } @Override - public Function, LoadBalance> finisher() { + public @NonNull Function, LoadBalance> finisher() { return balanceStatistics -> balanceStatistics; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/LongCalculatorTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/LongCalculatorTriCollector.java index 7fbac3b4b2..462a0a05df 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/LongCalculatorTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/LongCalculatorTriCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.tri.TriConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.LongCalculator; +import org.jspecify.annotations.NonNull; + abstract sealed class LongCalculatorTriCollector> implements TriConstraintCollector permits AverageLongTriCollector, SumLongTriCollector { private final ToLongTriFunction mapper; @@ -17,7 +19,7 @@ public LongCalculatorTriCollector(ToLongTriFunction accumulator() { + public @NonNull QuadFunction accumulator() { return (calculator, a, b, c) -> { final long mapped = mapper.applyAsLong(a, b, c); calculator.insert(mapped); @@ -26,7 +28,7 @@ public QuadFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return LongCalculator::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MaxComparableTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MaxComparableTriCollector.java index 09eac33370..c394d1b210 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MaxComparableTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MaxComparableTriCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MaxComparableTriCollector> extends UndoableActionableTriCollector> { MaxComparableTriCollector(TriFunction mapper) { @@ -12,7 +14,7 @@ final class MaxComparableTriCollector> supplier() { + public @NonNull Supplier> supplier() { return MinMaxUndoableActionable::maxCalculator; } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MaxComparatorTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MaxComparatorTriCollector.java index b51869370d..c84b9ed55e 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MaxComparatorTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MaxComparatorTriCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MaxComparatorTriCollector extends UndoableActionableTriCollector> { private final Comparator comparator; @@ -18,7 +20,7 @@ final class MaxComparatorTriCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.maxCalculator(comparator); } @@ -38,4 +40,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), comparator); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MaxPropertyTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MaxPropertyTriCollector.java index 0699f720aa..dae34989ec 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MaxPropertyTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MaxPropertyTriCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MaxPropertyTriCollector> extends UndoableActionableTriCollector> { private final Function propertyMapper; @@ -18,7 +20,7 @@ final class MaxPropertyTriCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.maxCalculator(propertyMapper); } @@ -38,4 +40,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), propertyMapper); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MinComparableTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MinComparableTriCollector.java index 10c4fc22df..2f6b8f32cf 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MinComparableTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MinComparableTriCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MinComparableTriCollector> extends UndoableActionableTriCollector> { MinComparableTriCollector(TriFunction mapper) { @@ -12,7 +14,7 @@ final class MinComparableTriCollector> supplier() { + public @NonNull Supplier> supplier() { return MinMaxUndoableActionable::minCalculator; } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MinComparatorTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MinComparatorTriCollector.java index 35cf492d37..dfaf20c3a0 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MinComparatorTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MinComparatorTriCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MinComparatorTriCollector extends UndoableActionableTriCollector> { private final Comparator comparator; @@ -18,7 +20,7 @@ final class MinComparatorTriCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.minCalculator(comparator); } @@ -38,4 +40,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), comparator); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MinPropertyTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MinPropertyTriCollector.java index f47ad6a2a6..f2f8828c57 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MinPropertyTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/MinPropertyTriCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MinPropertyTriCollector> extends UndoableActionableTriCollector> { private final Function propertyMapper; @@ -18,7 +20,7 @@ final class MinPropertyTriCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.minCalculator(propertyMapper); } @@ -38,4 +40,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), propertyMapper); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ObjectCalculatorTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ObjectCalculatorTriCollector.java index 44484d0cb0..d6a542d334 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ObjectCalculatorTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ObjectCalculatorTriCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.tri.TriConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.ObjectCalculator; +import org.jspecify.annotations.NonNull; + abstract sealed class ObjectCalculatorTriCollector> implements TriConstraintCollector permits AverageReferenceTriCollector, ConnectedRangesTriConstraintCollector, ConsecutiveSequencesTriConstraintCollector, @@ -19,7 +21,7 @@ public ObjectCalculatorTriCollector(TriFunction accumulator() { + public @NonNull QuadFunction accumulator() { return (calculator, a, b, c) -> { final var mapped = mapper.apply(a, b, c); final var saved = calculator.insert(mapped); @@ -28,7 +30,7 @@ public QuadFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return ObjectCalculator::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/SumIntTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/SumIntTriCollector.java index 60282d089a..80dabd72c3 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/SumIntTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/SumIntTriCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.api.function.ToIntTriFunction; import ai.timefold.solver.core.impl.score.stream.collector.IntSumCalculator; +import org.jspecify.annotations.NonNull; + final class SumIntTriCollector extends IntCalculatorTriCollector { SumIntTriCollector(ToIntTriFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return IntSumCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/SumLongTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/SumLongTriCollector.java index b684b13621..a942de0d19 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/SumLongTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/SumLongTriCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.api.function.ToLongTriFunction; import ai.timefold.solver.core.impl.score.stream.collector.LongSumCalculator; +import org.jspecify.annotations.NonNull; + final class SumLongTriCollector extends LongCalculatorTriCollector { SumLongTriCollector(ToLongTriFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return LongSumCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/SumReferenceTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/SumReferenceTriCollector.java index 4aa7da1937..466c4c8657 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/SumReferenceTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/SumReferenceTriCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.ReferenceSumCalculator; +import org.jspecify.annotations.NonNull; + final class SumReferenceTriCollector extends ObjectCalculatorTriCollector> { private final Result_ zero; @@ -23,7 +25,7 @@ final class SumReferenceTriCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> new ReferenceSumCalculator<>(zero, adder, subtractor); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToCollectionTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToCollectionTriCollector.java index 63c1546e70..3cf264f034 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToCollectionTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToCollectionTriCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.CustomCollectionUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToCollectionTriCollector> extends UndoableActionableTriCollector> { @@ -20,7 +22,7 @@ final class ToCollectionTriCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> new CustomCollectionUndoableActionable<>(collectionFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToListTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToListTriCollector.java index 9723c7349e..3499eda659 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToListTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToListTriCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.ListUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToListTriCollector extends UndoableActionableTriCollector, ListUndoableActionable> { ToListTriCollector(TriFunction mapper) { @@ -13,7 +15,7 @@ final class ToListTriCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return ListUndoableActionable::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToMultiMapTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToMultiMapTriCollector.java index 5ce3e0e63c..318148f402 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToMultiMapTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToMultiMapTriCollector.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MapUndoableActionable; import ai.timefold.solver.core.impl.util.Pair; +import org.jspecify.annotations.NonNull; + final class ToMultiMapTriCollector, Result_ extends Map> extends UndoableActionableTriCollector, Result_, MapUndoableActionable> { @@ -30,7 +32,7 @@ final class ToMultiMapTriCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MapUndoableActionable.multiMap(mapSupplier, setFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToSetTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToSetTriCollector.java index 1ed507515f..8f8463cc51 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToSetTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToSetTriCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.SetUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToSetTriCollector extends UndoableActionableTriCollector, SetUndoableActionable> { ToSetTriCollector(TriFunction mapper) { @@ -13,7 +15,7 @@ final class ToSetTriCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return SetUndoableActionable::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToSimpleMapTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToSimpleMapTriCollector.java index 9e22f08fae..d5d7f3e497 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToSimpleMapTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToSimpleMapTriCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MapUndoableActionable; import ai.timefold.solver.core.impl.util.Pair; +import org.jspecify.annotations.NonNull; + final class ToSimpleMapTriCollector> extends UndoableActionableTriCollector, Result_, MapUndoableActionable> { @@ -29,7 +31,7 @@ final class ToSimpleMapTriCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MapUndoableActionable.mergeMap(mapSupplier, mergeFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToSortedSetComparatorTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToSortedSetComparatorTriCollector.java index e8ec332c3f..09cd457389 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToSortedSetComparatorTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/ToSortedSetComparatorTriCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.function.TriFunction; import ai.timefold.solver.core.impl.score.stream.collector.SortedSetUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToSortedSetComparatorTriCollector extends UndoableActionableTriCollector, SortedSetUndoableActionable> { private final Comparator comparator; @@ -19,7 +21,7 @@ final class ToSortedSetComparatorTriCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> SortedSetUndoableActionable.orderBy(comparator); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/UndoableActionableTriCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/UndoableActionableTriCollector.java index 8ca701437e..51464e0201 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/UndoableActionableTriCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/tri/UndoableActionableTriCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.api.score.stream.tri.TriConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.UndoableActionable; +import org.jspecify.annotations.NonNull; + abstract sealed class UndoableActionableTriCollector> implements TriConstraintCollector permits MaxComparableTriCollector, MaxComparatorTriCollector, MaxPropertyTriCollector, MinComparableTriCollector, @@ -20,7 +22,7 @@ public UndoableActionableTriCollector(TriFunction accumulator() { + public @NonNull QuadFunction accumulator() { return (calculator, a, b, c) -> { final Input_ mapped = mapper.apply(a, b, c); return calculator.insert(mapped); @@ -28,7 +30,7 @@ public QuadFunction accumulator() { } @Override - public Function finisher() { + public @NonNull Function finisher() { return UndoableActionable::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AndThenUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AndThenUniCollector.java index ff0d588758..004dc9f5bf 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AndThenUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AndThenUniCollector.java @@ -7,6 +7,9 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + final class AndThenUniCollector implements UniConstraintCollector { @@ -20,17 +23,17 @@ final class AndThenUniCollector } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return delegate.supplier(); } @Override - public BiFunction accumulator() { + public @NonNull BiFunction accumulator() { return delegate.accumulator(); } @Override - public Function finisher() { + public @Nullable Function finisher() { var finisher = delegate.finisher(); return container -> mappingFunction.apply(finisher.apply(container)); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AverageIntUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AverageIntUniCollector.java index 9043ba6af6..5ae518c8dc 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AverageIntUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AverageIntUniCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.impl.score.stream.collector.IntAverageCalculator; +import org.jspecify.annotations.NonNull; + final class AverageIntUniCollector extends IntCalculatorUniCollector { AverageIntUniCollector(ToIntFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return IntAverageCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AverageLongUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AverageLongUniCollector.java index a08b092539..c96570f78e 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AverageLongUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AverageLongUniCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.impl.score.stream.collector.LongAverageCalculator; +import org.jspecify.annotations.NonNull; + final class AverageLongUniCollector extends LongCalculatorUniCollector { AverageLongUniCollector(ToLongFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return LongAverageCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AverageReferenceUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AverageReferenceUniCollector.java index 329d727ba0..cff3c9e63a 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AverageReferenceUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/AverageReferenceUniCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.ReferenceAverageCalculator; +import org.jspecify.annotations.NonNull; + final class AverageReferenceUniCollector extends ObjectCalculatorUniCollector> { private final Supplier> calculatorSupplier; @@ -17,7 +19,7 @@ final class AverageReferenceUniCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return calculatorSupplier; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeFourUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeFourUniCollector.java index 5e1a947756..36be7ecebd 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeFourUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeFourUniCollector.java @@ -9,6 +9,9 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; import ai.timefold.solver.core.impl.util.Quadruple; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + final class ComposeFourUniCollector implements UniConstraintCollector, Result_> { @@ -61,7 +64,7 @@ final class ComposeFourUniCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> { ResultHolder1_ a = firstSupplier.get(); ResultHolder2_ b = secondSupplier.get(); @@ -71,7 +74,8 @@ public Supplier, A, Runnable> accumulator() { + public @NonNull BiFunction, A, Runnable> + accumulator() { return (resultHolder, a) -> composeUndo(firstAccumulator.apply(resultHolder.a(), a), secondAccumulator.apply(resultHolder.b(), a), thirdAccumulator.apply(resultHolder.c(), a), @@ -89,7 +93,7 @@ private static Runnable composeUndo(Runnable first, Runnable second, Runnable th } @Override - public Function, Result_> finisher() { + public @Nullable Function, Result_> finisher() { return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.a()), secondFinisher.apply(resultHolder.b()), thirdFinisher.apply(resultHolder.c()), diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeThreeUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeThreeUniCollector.java index ff44475deb..932f831846 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeThreeUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeThreeUniCollector.java @@ -9,6 +9,9 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; import ai.timefold.solver.core.impl.util.Triple; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + final class ComposeThreeUniCollector implements UniConstraintCollector, Result_> { private final UniConstraintCollector first; @@ -51,7 +54,7 @@ final class ComposeThreeUniCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> { ResultHolder1_ a = firstSupplier.get(); ResultHolder2_ b = secondSupplier.get(); @@ -60,7 +63,7 @@ public Supplier> supplier } @Override - public BiFunction, A, Runnable> accumulator() { + public @NonNull BiFunction, A, Runnable> accumulator() { return (resultHolder, a) -> composeUndo(firstAccumulator.apply(resultHolder.a(), a), secondAccumulator.apply(resultHolder.b(), a), thirdAccumulator.apply(resultHolder.c(), a)); @@ -75,7 +78,7 @@ private static Runnable composeUndo(Runnable first, Runnable second, Runnable th } @Override - public Function, Result_> finisher() { + public @Nullable Function, Result_> finisher() { return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.a()), secondFinisher.apply(resultHolder.b()), thirdFinisher.apply(resultHolder.c())); diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeTwoUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeTwoUniCollector.java index 4bf8df7b9e..8033fe0d52 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeTwoUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ComposeTwoUniCollector.java @@ -8,6 +8,9 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; import ai.timefold.solver.core.impl.util.Pair; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + final class ComposeTwoUniCollector implements UniConstraintCollector, Result_> { private final UniConstraintCollector first; @@ -41,12 +44,12 @@ final class ComposeTwoUniCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> new Pair<>(firstSupplier.get(), secondSupplier.get()); } @Override - public BiFunction, A, Runnable> accumulator() { + public @NonNull BiFunction, A, Runnable> accumulator() { return (resultHolder, a) -> composeUndo(firstAccumulator.apply(resultHolder.key(), a), secondAccumulator.apply(resultHolder.value(), a)); } @@ -59,7 +62,7 @@ private static Runnable composeUndo(Runnable first, Runnable second) { } @Override - public Function, Result_> finisher() { + public @Nullable Function, Result_> finisher() { return resultHolder -> composeFunction.apply(firstFinisher.apply(resultHolder.key()), secondFinisher.apply(resultHolder.value())); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ConditionalUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ConditionalUniCollector.java index af22431ee9..610ef1c732 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ConditionalUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ConditionalUniCollector.java @@ -9,6 +9,9 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + final class ConditionalUniCollector implements UniConstraintCollector { private final Predicate predicate; @@ -22,12 +25,12 @@ final class ConditionalUniCollector } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return delegate.supplier(); } @Override - public BiFunction accumulator() { + public @NonNull BiFunction accumulator() { return (resultContainer, a) -> { if (predicate.test(a)) { return innerAccumulator.apply(resultContainer, a); @@ -38,7 +41,7 @@ public BiFunction accumulator() { } @Override - public Function finisher() { + public @Nullable Function finisher() { return delegate.finisher(); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ConnectedRangesUniConstraintCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ConnectedRangesUniConstraintCollector.java index 0eb267265a..e56fbe02b7 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ConnectedRangesUniConstraintCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ConnectedRangesUniConstraintCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.ConnectedRangesCalculator; import ai.timefold.solver.core.impl.score.stream.collector.connected_ranges.Range; +import org.jspecify.annotations.NonNull; + final class ConnectedRangesUniConstraintCollector, Difference_ extends Comparable> extends ObjectCalculatorUniCollector, Range, ConnectedRangesCalculator> { @@ -27,7 +29,7 @@ public ConnectedRangesUniConstraintCollector(Function> supplier() { + public @NonNull Supplier> supplier() { return () -> new ConnectedRangesCalculator<>(startMap, endMap, differenceFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ConsecutiveSequencesUniConstraintCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ConsecutiveSequencesUniConstraintCollector.java index 7887740990..41b282952e 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ConsecutiveSequencesUniConstraintCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ConsecutiveSequencesUniConstraintCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.SequenceCalculator; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + final class ConsecutiveSequencesUniConstraintCollector extends ObjectCalculatorUniCollector, A, SequenceCalculator> { @@ -19,7 +21,7 @@ public ConsecutiveSequencesUniConstraintCollector(ToIntFunction indexMap) { } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> new SequenceCalculator<>(indexMap); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountDistinctIntUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountDistinctIntUniCollector.java index dff9559f03..fce857b461 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountDistinctIntUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountDistinctIntUniCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.IntDistinctCountCalculator; +import org.jspecify.annotations.NonNull; + final class CountDistinctIntUniCollector extends ObjectCalculatorUniCollector> { CountDistinctIntUniCollector(Function mapper) { @@ -12,7 +14,7 @@ final class CountDistinctIntUniCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return IntDistinctCountCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountDistinctLongUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountDistinctLongUniCollector.java index 5c9a2c0cac..bd3d316db7 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountDistinctLongUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountDistinctLongUniCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.LongDistinctCountCalculator; +import org.jspecify.annotations.NonNull; + final class CountDistinctLongUniCollector extends ObjectCalculatorUniCollector> { CountDistinctLongUniCollector(Function mapper) { @@ -12,7 +14,7 @@ final class CountDistinctLongUniCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return LongDistinctCountCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountIntUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountIntUniCollector.java index 4292eb048b..398bcd230c 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountIntUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountIntUniCollector.java @@ -7,6 +7,9 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.IntCounter; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + final class CountIntUniCollector implements UniConstraintCollector { private final static CountIntUniCollector INSTANCE = new CountIntUniCollector<>(); @@ -19,12 +22,12 @@ static CountIntUniCollector getInstance() { } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return IntCounter::new; } @Override - public BiFunction accumulator() { + public @NonNull BiFunction accumulator() { return (counter, a) -> { counter.increment(); return counter::decrement; @@ -32,7 +35,7 @@ public BiFunction accumulator() { } @Override - public Function finisher() { + public @Nullable Function finisher() { return IntCounter::result; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountLongUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountLongUniCollector.java index 55fb9c882b..2250383436 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountLongUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/CountLongUniCollector.java @@ -7,6 +7,9 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.LongCounter; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + final class CountLongUniCollector implements UniConstraintCollector { private final static CountLongUniCollector INSTANCE = new CountLongUniCollector<>(); @@ -19,12 +22,12 @@ static CountLongUniCollector getInstance() { } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return LongCounter::new; } @Override - public BiFunction accumulator() { + public @NonNull BiFunction accumulator() { return (counter, a) -> { counter.increment(); return counter::decrement; @@ -32,7 +35,7 @@ public BiFunction accumulator() { } @Override - public Function finisher() { + public @Nullable Function finisher() { return LongCounter::result; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/IntCalculatorUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/IntCalculatorUniCollector.java index 3eb3099ff3..e1213ea6d4 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/IntCalculatorUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/IntCalculatorUniCollector.java @@ -8,6 +8,9 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.IntCalculator; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + abstract sealed class IntCalculatorUniCollector> implements UniConstraintCollector permits AverageIntUniCollector, SumIntUniCollector { private final ToIntFunction mapper; @@ -17,7 +20,7 @@ public IntCalculatorUniCollector(ToIntFunction mapper) { } @Override - public BiFunction accumulator() { + public @NonNull BiFunction accumulator() { return (calculator, a) -> { final int mapped = mapper.applyAsInt(a); calculator.insert(mapped); @@ -26,7 +29,7 @@ public BiFunction accumulator() { } @Override - public Function finisher() { + public @Nullable Function finisher() { return IntCalculator::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/LoadBalanceUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/LoadBalanceUniCollector.java index d8b4b1229e..dc0511bcea 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/LoadBalanceUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/LoadBalanceUniCollector.java @@ -10,6 +10,9 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.LoadBalanceImpl; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + final class LoadBalanceUniCollector implements UniConstraintCollector, LoadBalance> { @@ -25,12 +28,12 @@ public LoadBalanceUniCollector(Function balancedItemFunction, ToLo } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return LoadBalanceImpl::new; } @Override - public BiFunction, A, Runnable> accumulator() { + public @NonNull BiFunction, A, Runnable> accumulator() { return (balanceStatistics, a) -> { var balanced = balancedItemFunction.apply(a); var initialLoad = initialLoadFunction.applyAsLong(a); @@ -40,7 +43,7 @@ public BiFunction, A, Runnable> accumulator() { } @Override - public Function, LoadBalance> finisher() { + public @Nullable Function, LoadBalance> finisher() { return balanceStatistics -> balanceStatistics; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/LongCalculatorUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/LongCalculatorUniCollector.java index bf30deab35..c2251fb976 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/LongCalculatorUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/LongCalculatorUniCollector.java @@ -8,6 +8,9 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.LongCalculator; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + abstract sealed class LongCalculatorUniCollector> implements UniConstraintCollector permits AverageLongUniCollector, SumLongUniCollector { private final ToLongFunction mapper; @@ -17,7 +20,7 @@ public LongCalculatorUniCollector(ToLongFunction mapper) { } @Override - public BiFunction accumulator() { + public @NonNull BiFunction accumulator() { return (calculator, a) -> { final long mapped = mapper.applyAsLong(a); calculator.insert(mapped); @@ -26,7 +29,7 @@ public BiFunction accumulator() { } @Override - public Function finisher() { + public @Nullable Function finisher() { return LongCalculator::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MaxComparableUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MaxComparableUniCollector.java index 2b0b0c396f..2659a1b83e 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MaxComparableUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MaxComparableUniCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MaxComparableUniCollector> extends UndoableActionableUniCollector> { MaxComparableUniCollector(Function mapper) { @@ -12,7 +14,7 @@ final class MaxComparableUniCollector> supplier() { + public @NonNull Supplier> supplier() { return MinMaxUndoableActionable::maxCalculator; } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MaxComparatorUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MaxComparatorUniCollector.java index 401b013233..a1575520f8 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MaxComparatorUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MaxComparatorUniCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MaxComparatorUniCollector extends UndoableActionableUniCollector> { private final Comparator comparator; @@ -17,7 +19,7 @@ final class MaxComparatorUniCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.maxCalculator(comparator); } @@ -37,4 +39,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), comparator); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MaxPropertyUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MaxPropertyUniCollector.java index 54b7343446..d78f39af0d 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MaxPropertyUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MaxPropertyUniCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MaxPropertyUniCollector> extends UndoableActionableUniCollector> { private final Function propertyMapper; @@ -17,7 +19,7 @@ final class MaxPropertyUniCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.maxCalculator(propertyMapper); } @@ -37,4 +39,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), propertyMapper); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MinComparableUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MinComparableUniCollector.java index 3f85240609..2c7c6b27be 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MinComparableUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MinComparableUniCollector.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MinComparableUniCollector> extends UndoableActionableUniCollector> { MinComparableUniCollector(Function mapper) { @@ -12,7 +14,7 @@ final class MinComparableUniCollector> supplier() { + public @NonNull Supplier> supplier() { return MinMaxUndoableActionable::minCalculator; } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MinComparatorUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MinComparatorUniCollector.java index c783773d38..80df53e451 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MinComparatorUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MinComparatorUniCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MinComparatorUniCollector extends UndoableActionableUniCollector> { private final Comparator comparator; @@ -17,7 +19,7 @@ final class MinComparatorUniCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.minCalculator(comparator); } @@ -37,4 +39,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), comparator); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MinPropertyUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MinPropertyUniCollector.java index 147b688e2c..3d461845b6 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MinPropertyUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/MinPropertyUniCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MinMaxUndoableActionable; +import org.jspecify.annotations.NonNull; + final class MinPropertyUniCollector> extends UndoableActionableUniCollector> { private final Function propertyMapper; @@ -17,7 +19,7 @@ final class MinPropertyUniCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MinMaxUndoableActionable.minCalculator(propertyMapper); } @@ -37,4 +39,4 @@ public boolean equals(Object object) { public int hashCode() { return Objects.hash(super.hashCode(), propertyMapper); } -} \ No newline at end of file +} diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ObjectCalculatorUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ObjectCalculatorUniCollector.java index 746a303da2..c6b0630d9c 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ObjectCalculatorUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ObjectCalculatorUniCollector.java @@ -7,6 +7,9 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.ObjectCalculator; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + abstract sealed class ObjectCalculatorUniCollector> implements UniConstraintCollector permits AverageReferenceUniCollector, ConnectedRangesUniConstraintCollector, ConsecutiveSequencesUniConstraintCollector, @@ -19,7 +22,7 @@ public ObjectCalculatorUniCollector(Function mapper } @Override - public BiFunction accumulator() { + public @NonNull BiFunction accumulator() { return (calculator, a) -> { final var mapped = mapper.apply(a); final var saved = calculator.insert(mapped); @@ -28,7 +31,7 @@ public BiFunction accumulator() { } @Override - public Function finisher() { + public @Nullable Function finisher() { return ObjectCalculator::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/SumIntUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/SumIntUniCollector.java index 6fa92cbc80..ddf20fc821 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/SumIntUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/SumIntUniCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.impl.score.stream.collector.IntSumCalculator; +import org.jspecify.annotations.NonNull; + final class SumIntUniCollector extends IntCalculatorUniCollector { SumIntUniCollector(ToIntFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return IntSumCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/SumLongUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/SumLongUniCollector.java index 61e90d1233..356b8c5d0d 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/SumLongUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/SumLongUniCollector.java @@ -5,13 +5,15 @@ import ai.timefold.solver.core.impl.score.stream.collector.LongSumCalculator; +import org.jspecify.annotations.NonNull; + final class SumLongUniCollector extends LongCalculatorUniCollector { SumLongUniCollector(ToLongFunction mapper) { super(mapper); } @Override - public Supplier supplier() { + public @NonNull Supplier supplier() { return LongSumCalculator::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/SumReferenceUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/SumReferenceUniCollector.java index b5fb706639..b0f7ec014a 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/SumReferenceUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/SumReferenceUniCollector.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.ReferenceSumCalculator; +import org.jspecify.annotations.NonNull; + final class SumReferenceUniCollector extends ObjectCalculatorUniCollector> { private final Result_ zero; @@ -22,7 +24,7 @@ final class SumReferenceUniCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> new ReferenceSumCalculator<>(zero, adder, subtractor); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToCollectionUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToCollectionUniCollector.java index 0d31d51b1e..2ce729b69e 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToCollectionUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToCollectionUniCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.CustomCollectionUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToCollectionUniCollector> extends UndoableActionableUniCollector> { private final IntFunction collectionFunction; @@ -19,7 +21,7 @@ final class ToCollectionUniCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> new CustomCollectionUndoableActionable<>(collectionFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToListUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToListUniCollector.java index 0502a5af16..97b31dd209 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToListUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToListUniCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.ListUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToListUniCollector extends UndoableActionableUniCollector, ListUndoableActionable> { ToListUniCollector(Function mapper) { @@ -13,7 +15,7 @@ final class ToListUniCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return ListUndoableActionable::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToMultiMapUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToMultiMapUniCollector.java index 46936f7be7..1d64100c3f 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToMultiMapUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToMultiMapUniCollector.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MapUndoableActionable; import ai.timefold.solver.core.impl.util.Pair; +import org.jspecify.annotations.NonNull; + final class ToMultiMapUniCollector, Result_ extends Map> extends UndoableActionableUniCollector, Result_, MapUndoableActionable> { @@ -30,7 +32,7 @@ final class ToMultiMapUniCollector, Re } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> MapUndoableActionable.multiMap(mapSupplier, setFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToSetUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToSetUniCollector.java index ff0ae51322..0463d42ae2 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToSetUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToSetUniCollector.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.SetUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToSetUniCollector extends UndoableActionableUniCollector, SetUndoableActionable> { ToSetUniCollector(Function mapper) { @@ -13,7 +15,7 @@ final class ToSetUniCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return SetUndoableActionable::new; } } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToSimpleMapUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToSimpleMapUniCollector.java index 6e52895d4c..d537d24910 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToSimpleMapUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToSimpleMapUniCollector.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.MapUndoableActionable; import ai.timefold.solver.core.impl.util.Pair; +import org.jspecify.annotations.NonNull; + final class ToSimpleMapUniCollector> extends UndoableActionableUniCollector, Result_, MapUndoableActionable> { @@ -29,7 +31,7 @@ final class ToSimpleMapUniCollector> supplier() { + public @NonNull Supplier> supplier() { return () -> MapUndoableActionable.mergeMap(mapSupplier, mergeFunction); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToSortedSetComparatorUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToSortedSetComparatorUniCollector.java index 794041e684..720a50fda5 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToSortedSetComparatorUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/ToSortedSetComparatorUniCollector.java @@ -8,6 +8,8 @@ import ai.timefold.solver.core.impl.score.stream.collector.SortedSetUndoableActionable; +import org.jspecify.annotations.NonNull; + final class ToSortedSetComparatorUniCollector extends UndoableActionableUniCollector, SortedSetUndoableActionable> { private final Comparator comparator; @@ -19,7 +21,7 @@ final class ToSortedSetComparatorUniCollector } @Override - public Supplier> supplier() { + public @NonNull Supplier> supplier() { return () -> SortedSetUndoableActionable.orderBy(comparator); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/UndoableActionableUniCollector.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/UndoableActionableUniCollector.java index 7d13c15bb9..947fc6f22d 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/UndoableActionableUniCollector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/collector/uni/UndoableActionableUniCollector.java @@ -7,6 +7,9 @@ import ai.timefold.solver.core.api.score.stream.uni.UniConstraintCollector; import ai.timefold.solver.core.impl.score.stream.collector.UndoableActionable; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + abstract sealed class UndoableActionableUniCollector> implements UniConstraintCollector permits MaxComparableUniCollector, MaxComparatorUniCollector, MaxPropertyUniCollector, MinComparableUniCollector, @@ -19,7 +22,7 @@ public UndoableActionableUniCollector(Function mapp } @Override - public BiFunction accumulator() { + public @NonNull BiFunction accumulator() { return (calculator, a) -> { final Input_ mapped = mapper.apply(a); return calculator.insert(mapped); @@ -27,7 +30,7 @@ public BiFunction accumulator() { } @Override - public Function finisher() { + public @Nullable Function finisher() { return UndoableActionable::result; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraint.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraint.java index 5e37b3eaeb..136f02b989 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraint.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraint.java @@ -12,6 +12,8 @@ import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; import ai.timefold.solver.core.impl.score.definition.AbstractBendableScoreDefinition; +import org.jspecify.annotations.NonNull; + public abstract class AbstractConstraint, ConstraintFactory_ extends InnerConstraintFactory> implements Constraint { @@ -154,12 +156,12 @@ public ConstraintRef getConstraintRef() { } @Override - public String getDescription() { + public @NonNull String getDescription() { return description; } @Override - public String getConstraintGroup() { + public @NonNull String getConstraintGroup() { return constraintGroup; } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraintBuilder.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraintBuilder.java index bcf047ddd1..c6ece13466 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraintBuilder.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraintBuilder.java @@ -6,6 +6,8 @@ import ai.timefold.solver.core.api.score.stream.Constraint; import ai.timefold.solver.core.api.score.stream.ConstraintBuilder; +import org.jspecify.annotations.NonNull; + @SuppressWarnings("rawtypes") public abstract class AbstractConstraintBuilder> implements ConstraintBuilder { private final ConstraintConstructor constraintConstructor; @@ -25,7 +27,8 @@ protected AbstractConstraintBuilder(ConstraintConstructor constraintConstructor, @SuppressWarnings("unchecked") @Override - public final Constraint asConstraintDescribed(String constraintName, String constraintDescription, String constraintGroup) { + public final @NonNull Constraint asConstraintDescribed(@NonNull String constraintName, + @NonNull String constraintDescription, @NonNull String constraintGroup) { return constraintConstructor.apply(null, constraintName, constraintDescription, constraintGroup, constraintWeight, impactType, getJustificationMapping(), getIndictedObjectsMapping()); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraintStream.java index 7f51983265..7a12e68af6 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraintStream.java @@ -4,6 +4,8 @@ import ai.timefold.solver.core.api.score.stream.ConstraintStream; +import org.jspecify.annotations.NonNull; + public abstract class AbstractConstraintStream implements ConstraintStream { private final RetrievalSemantics retrievalSemantics; @@ -21,7 +23,7 @@ public RetrievalSemantics getRetrievalSemantics() { // ************************************************************************ @Override - public abstract InnerConstraintFactory getConstraintFactory(); + public abstract @NonNull InnerConstraintFactory getConstraintFactory(); protected abstract JustificationMapping_ getDefaultJustificationMapping(); diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/InnerConstraintFactory.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/InnerConstraintFactory.java index 7bb7368988..4a5f6137f1 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/InnerConstraintFactory.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/InnerConstraintFactory.java @@ -25,10 +25,13 @@ import ai.timefold.solver.core.impl.score.stream.common.bi.DefaultBiJoiner; import ai.timefold.solver.core.impl.score.stream.common.uni.InnerUniConstraintStream; +import org.jspecify.annotations.NonNull; + public abstract class InnerConstraintFactory implements ConstraintFactory { @Override - public BiConstraintStream forEachUniquePair(Class sourceClass, BiJoiner... joiners) { + public @NonNull BiConstraintStream forEachUniquePair(@NonNull Class sourceClass, + BiJoiner @NonNull... joiners) { BiJoinerComber joinerComber = BiJoinerComber.comb(joiners); joinerComber.addJoiner(buildLessThanId(sourceClass)); return ((InnerUniConstraintStream) forEach(sourceClass)) @@ -48,7 +51,8 @@ private DefaultBiJoiner buildLessThanId(Class sourceClass) { } @Override - public BiConstraintStream fromUniquePair(Class fromClass, BiJoiner... joiners) { + public @NonNull BiConstraintStream fromUniquePair(@NonNull Class fromClass, + @NonNull BiJoiner... joiners) { BiJoinerComber joinerComber = BiJoinerComber.comb(joiners); joinerComber.addJoiner(buildLessThanId(fromClass)); return ((InnerUniConstraintStream) from(fromClass)) diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/BiConstraintBuilderImpl.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/BiConstraintBuilderImpl.java index 1717bd5549..56d3b302b3 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/BiConstraintBuilderImpl.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/BiConstraintBuilderImpl.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.impl.score.stream.common.AbstractConstraintBuilder; import ai.timefold.solver.core.impl.score.stream.common.ScoreImpactType; +import org.jspecify.annotations.NonNull; + public final class BiConstraintBuilderImpl> extends AbstractConstraintBuilder implements BiConstraintBuilder { @@ -29,8 +31,8 @@ protected TriFunction getJustificationMap } @Override - public BiConstraintBuilder justifyWith( - TriFunction justificationMapping) { + public @NonNull BiConstraintBuilder justifyWith( + @NonNull TriFunction justificationMapping) { if (this.justificationMapping != null) { throw new IllegalStateException(""" Justification mapping already set (%s). @@ -48,7 +50,8 @@ protected BiFunction> getIndictedObjectsMapping() { } @Override - public BiConstraintBuilder indictWith(BiFunction> indictedObjectsMapping) { + public @NonNull BiConstraintBuilder + indictWith(@NonNull BiFunction> indictedObjectsMapping) { if (this.indictedObjectsMapping != null) { throw new IllegalStateException(""" Indicted objects' mapping already set (%s). diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/DefaultBiJoiner.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/DefaultBiJoiner.java index 148cbde957..bbcb517f82 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/DefaultBiJoiner.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/DefaultBiJoiner.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.score.stream.JoinerType; import ai.timefold.solver.core.impl.score.stream.common.AbstractJoiner; +import org.jspecify.annotations.NonNull; + public final class DefaultBiJoiner extends AbstractJoiner implements BiJoiner { private static final DefaultBiJoiner NONE = new DefaultBiJoiner(new Function[0], new JoinerType[0], new Function[0]); @@ -35,7 +37,7 @@ public static DefaultBiJoiner merge(List> joi } @Override - public DefaultBiJoiner and(BiJoiner otherJoiner) { + public @NonNull DefaultBiJoiner and(@NonNull BiJoiner otherJoiner) { DefaultBiJoiner castJoiner = (DefaultBiJoiner) otherJoiner; int joinerCount = getJoinerCount(); int castJoinerCount = castJoiner.getJoinerCount(); diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/FilteringBiJoiner.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/FilteringBiJoiner.java index 836315e8a8..3b4b8cd3b5 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/FilteringBiJoiner.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/FilteringBiJoiner.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.score.stream.bi.BiJoiner; +import org.jspecify.annotations.NonNull; + public final class FilteringBiJoiner implements BiJoiner { private final BiPredicate filter; @@ -14,7 +16,7 @@ public FilteringBiJoiner(BiPredicate filter) { } @Override - public FilteringBiJoiner and(BiJoiner otherJoiner) { + public @NonNull FilteringBiJoiner and(@NonNull BiJoiner otherJoiner) { FilteringBiJoiner castJoiner = (FilteringBiJoiner) otherJoiner; return new FilteringBiJoiner<>(filter.and(castJoiner.getFilter())); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/InnerBiConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/InnerBiConstraintStream.java index 2fb59d9622..e3125ff6d3 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/InnerBiConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/bi/InnerBiConstraintStream.java @@ -21,6 +21,8 @@ import ai.timefold.solver.core.impl.score.stream.common.ScoreImpactType; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + public interface InnerBiConstraintStream extends BiConstraintStream { static TriFunction, DefaultConstraintJustification> createDefaultJustificationMapping() { @@ -42,7 +44,7 @@ static BiFunction> createDefaultIndictedObjectsMappin boolean guaranteesDistinct(); @Override - default TriConstraintStream join(Class otherClass, TriJoiner... joiners) { + default @NonNull TriConstraintStream join(@NonNull Class otherClass, TriJoiner... joiners) { if (getRetrievalSemantics() == STANDARD) { return join(getConstraintFactory().forEach(otherClass), joiners); } else { @@ -51,7 +53,8 @@ default TriConstraintStream join(Class otherClass, TriJoiner BiConstraintStream ifExists(Class otherClass, TriJoiner... joiners) { + default @NonNull BiConstraintStream ifExists(@NonNull Class otherClass, + TriJoiner @NonNull... joiners) { if (getRetrievalSemantics() == STANDARD) { return ifExists(getConstraintFactory().forEach(otherClass), joiners); } else { @@ -61,7 +64,8 @@ default BiConstraintStream ifExists(Class otherClass, TriJoiner BiConstraintStream ifExistsIncludingUnassigned(Class otherClass, TriJoiner... joiners) { + default @NonNull BiConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull TriJoiner @NonNull... joiners) { if (getRetrievalSemantics() == STANDARD) { return ifExists(getConstraintFactory().forEachIncludingUnassigned(otherClass), joiners); } else { @@ -70,7 +74,8 @@ default BiConstraintStream ifExistsIncludingUnassigned(Class otherC } @Override - default BiConstraintStream ifNotExists(Class otherClass, TriJoiner... joiners) { + default @NonNull BiConstraintStream ifNotExists(@NonNull Class otherClass, + @NonNull TriJoiner... joiners) { if (getRetrievalSemantics() == STANDARD) { return ifNotExists(getConstraintFactory().forEach(otherClass), joiners); } else { @@ -80,7 +85,8 @@ default BiConstraintStream ifNotExists(Class otherClass, TriJoiner< } @Override - default BiConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, TriJoiner... joiners) { + default @NonNull BiConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull TriJoiner... joiners) { if (getRetrievalSemantics() == STANDARD) { return ifNotExists(getConstraintFactory().forEachIncludingUnassigned(otherClass), joiners); } else { @@ -89,7 +95,7 @@ default BiConstraintStream ifNotExistsIncludingUnassigned(Class oth } @Override - default BiConstraintStream distinct() { + default @NonNull BiConstraintStream distinct() { if (guaranteesDistinct()) { return this; } else { @@ -99,20 +105,22 @@ default BiConstraintStream distinct() { } @Override - default > BiConstraintBuilder penalize(Score_ constraintWeight, - ToIntBiFunction matchWeigher) { + default > @NonNull BiConstraintBuilder penalize(@NonNull Score_ constraintWeight, + @NonNull ToIntBiFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.PENALTY); } @Override - default > BiConstraintBuilder penalizeLong(Score_ constraintWeight, - ToLongBiFunction matchWeigher) { + default @NonNull > BiConstraintBuilder penalizeLong( + @NonNull Score_ constraintWeight, + @NonNull ToLongBiFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.PENALTY); } @Override - default > BiConstraintBuilder penalizeBigDecimal(Score_ constraintWeight, - BiFunction matchWeigher) { + default @NonNull > BiConstraintBuilder penalizeBigDecimal( + @NonNull Score_ constraintWeight, + @NonNull BiFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.PENALTY); } @@ -132,20 +140,22 @@ default > BiConstraintBuilder penaliz } @Override - default > BiConstraintBuilder reward(Score_ constraintWeight, - ToIntBiFunction matchWeigher) { + default > @NonNull BiConstraintBuilder reward(@NonNull Score_ constraintWeight, + @NonNull ToIntBiFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.REWARD); } @Override - default > BiConstraintBuilder rewardLong(Score_ constraintWeight, - ToLongBiFunction matchWeigher) { + default > @NonNull BiConstraintBuilder rewardLong( + @NonNull Score_ constraintWeight, + @NonNull ToLongBiFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.REWARD); } @Override - default > BiConstraintBuilder rewardBigDecimal(Score_ constraintWeight, - BiFunction matchWeigher) { + default > @NonNull BiConstraintBuilder rewardBigDecimal( + @NonNull Score_ constraintWeight, + @NonNull BiFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.REWARD); } @@ -165,20 +175,22 @@ default > BiConstraintBuilder rewardB } @Override - default > BiConstraintBuilder impact(Score_ constraintWeight, - ToIntBiFunction matchWeigher) { + default > @NonNull BiConstraintBuilder impact(@NonNull Score_ constraintWeight, + @NonNull ToIntBiFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.MIXED); } @Override - default > BiConstraintBuilder impactLong(Score_ constraintWeight, - ToLongBiFunction matchWeigher) { + default > @NonNull BiConstraintBuilder impactLong( + @NonNull Score_ constraintWeight, + @NonNull ToLongBiFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.MIXED); } @Override - default > BiConstraintBuilder impactBigDecimal(Score_ constraintWeight, - BiFunction matchWeigher) { + default > @NonNull BiConstraintBuilder impactBigDecimal( + @NonNull Score_ constraintWeight, + @NonNull BiFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.MIXED); } @@ -210,61 +222,64 @@ > BiConstraintBuilder innerImpact(Sco ScoreImpactType scoreImpactType); @Override - default Constraint penalize(String constraintName, Score constraintWeight) { + default @NonNull Constraint penalize(@NonNull String constraintName, @NonNull Score constraintWeight) { return penalize((Score) constraintWeight) .asConstraint(constraintName); } @Override - default Constraint penalize(String constraintPackage, String constraintName, Score constraintWeight) { + default @NonNull Constraint penalize(@NonNull String constraintPackage, @NonNull String constraintName, + @NonNull Score constraintWeight) { return penalize((Score) constraintWeight) .asConstraint(constraintPackage, constraintName); } @Override - default Constraint penalizeConfigurable(String constraintName) { + default @NonNull Constraint penalizeConfigurable(@NonNull String constraintName) { return penalizeConfigurable() .asConstraint(constraintName); } @Override - default Constraint penalizeConfigurable(String constraintPackage, String constraintName) { + default @NonNull Constraint penalizeConfigurable(@NonNull String constraintPackage, @NonNull String constraintName) { return penalizeConfigurable() .asConstraint(constraintPackage, constraintName); } @Override - default Constraint reward(String constraintName, Score constraintWeight) { + default @NonNull Constraint reward(@NonNull String constraintName, @NonNull Score constraintWeight) { return reward((Score) constraintWeight) .asConstraint(constraintName); } @Override - default Constraint reward(String constraintPackage, String constraintName, Score constraintWeight) { + default @NonNull Constraint reward(@NonNull String constraintPackage, @NonNull String constraintName, + @NonNull Score constraintWeight) { return reward((Score) constraintWeight) .asConstraint(constraintPackage, constraintName); } @Override - default Constraint rewardConfigurable(String constraintName) { + default @NonNull Constraint rewardConfigurable(@NonNull String constraintName) { return rewardConfigurable() .asConstraint(constraintName); } @Override - default Constraint rewardConfigurable(String constraintPackage, String constraintName) { + default @NonNull Constraint rewardConfigurable(@NonNull String constraintPackage, @NonNull String constraintName) { return penalizeConfigurable() .asConstraint(constraintPackage, constraintName); } @Override - default Constraint impact(String constraintName, Score constraintWeight) { + default @NonNull Constraint impact(@NonNull String constraintName, @NonNull Score constraintWeight) { return impact((Score) constraintWeight) .asConstraint(constraintName); } @Override - default Constraint impact(String constraintPackage, String constraintName, Score constraintWeight) { + default @NonNull Constraint impact(@NonNull String constraintPackage, @NonNull String constraintName, + @NonNull Score constraintWeight) { return impact((Score) constraintWeight) .asConstraint(constraintPackage, constraintName); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/DefaultQuadJoiner.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/DefaultQuadJoiner.java index 19884669b5..3cf0048deb 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/DefaultQuadJoiner.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/DefaultQuadJoiner.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.score.stream.JoinerType; import ai.timefold.solver.core.impl.score.stream.common.AbstractJoiner; +import org.jspecify.annotations.NonNull; + public final class DefaultQuadJoiner extends AbstractJoiner implements QuadJoiner { private static final DefaultQuadJoiner NONE = @@ -37,7 +39,7 @@ public static DefaultQuadJoiner merge(List and(QuadJoiner otherJoiner) { + public @NonNull DefaultQuadJoiner and(@NonNull QuadJoiner otherJoiner) { DefaultQuadJoiner castJoiner = (DefaultQuadJoiner) otherJoiner; int joinerCount = getJoinerCount(); int castJoinerCount = castJoiner.getJoinerCount(); diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/FilteringQuadJoiner.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/FilteringQuadJoiner.java index ecc4d78494..73c3461858 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/FilteringQuadJoiner.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/FilteringQuadJoiner.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.function.QuadPredicate; import ai.timefold.solver.core.api.score.stream.quad.QuadJoiner; +import org.jspecify.annotations.NonNull; + public final class FilteringQuadJoiner implements QuadJoiner { private final QuadPredicate filter; @@ -14,7 +16,7 @@ public FilteringQuadJoiner(QuadPredicate filter) { } @Override - public FilteringQuadJoiner and(QuadJoiner otherJoiner) { + public @NonNull FilteringQuadJoiner and(@NonNull QuadJoiner otherJoiner) { FilteringQuadJoiner castJoiner = (FilteringQuadJoiner) otherJoiner; return new FilteringQuadJoiner<>(filter.and(castJoiner.getFilter())); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/InnerQuadConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/InnerQuadConstraintStream.java index 97df49f9a5..81e780b333 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/InnerQuadConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/InnerQuadConstraintStream.java @@ -18,6 +18,8 @@ import ai.timefold.solver.core.impl.score.stream.common.ScoreImpactType; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + public interface InnerQuadConstraintStream extends QuadConstraintStream { static PentaFunction, DefaultConstraintJustification> @@ -203,61 +205,64 @@ > QuadConstraintBuilder innerIm QuadFunction matchWeigher, ScoreImpactType scoreImpactType); @Override - default Constraint penalize(String constraintName, Score constraintWeight) { + default @NonNull Constraint penalize(@NonNull String constraintName, @NonNull Score constraintWeight) { return penalize((Score) constraintWeight) .asConstraint(constraintName); } @Override - default Constraint penalize(String constraintPackage, String constraintName, Score constraintWeight) { + default @NonNull Constraint penalize(@NonNull String constraintPackage, @NonNull String constraintName, + @NonNull Score constraintWeight) { return penalize((Score) constraintWeight) .asConstraint(constraintPackage, constraintName); } @Override - default Constraint penalizeConfigurable(String constraintName) { + default @NonNull Constraint penalizeConfigurable(@NonNull String constraintName) { return penalizeConfigurable() .asConstraint(constraintName); } @Override - default Constraint penalizeConfigurable(String constraintPackage, String constraintName) { + default @NonNull Constraint penalizeConfigurable(@NonNull String constraintPackage, @NonNull String constraintName) { return penalizeConfigurable() .asConstraint(constraintPackage, constraintName); } @Override - default Constraint reward(String constraintName, Score constraintWeight) { + default @NonNull Constraint reward(@NonNull String constraintName, @NonNull Score constraintWeight) { return reward((Score) constraintWeight) .asConstraint(constraintName); } @Override - default Constraint reward(String constraintPackage, String constraintName, Score constraintWeight) { + default @NonNull Constraint reward(@NonNull String constraintPackage, @NonNull String constraintName, + @NonNull Score constraintWeight) { return reward((Score) constraintWeight) .asConstraint(constraintPackage, constraintName); } @Override - default Constraint rewardConfigurable(String constraintName) { + default @NonNull Constraint rewardConfigurable(@NonNull String constraintName) { return rewardConfigurable() .asConstraint(constraintName); } @Override - default Constraint rewardConfigurable(String constraintPackage, String constraintName) { + default @NonNull Constraint rewardConfigurable(@NonNull String constraintPackage, @NonNull String constraintName) { return penalizeConfigurable() .asConstraint(constraintPackage, constraintName); } @Override - default Constraint impact(String constraintName, Score constraintWeight) { + default @NonNull Constraint impact(@NonNull String constraintName, @NonNull Score constraintWeight) { return impact((Score) constraintWeight) .asConstraint(constraintName); } @Override - default Constraint impact(String constraintPackage, String constraintName, Score constraintWeight) { + default @NonNull Constraint impact(@NonNull String constraintPackage, @NonNull String constraintName, + @NonNull Score constraintWeight) { return impact((Score) constraintWeight) .asConstraint(constraintPackage, constraintName); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/QuadConstraintBuilderImpl.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/QuadConstraintBuilderImpl.java index 2cb2d2ba53..a8877e1284 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/QuadConstraintBuilderImpl.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/quad/QuadConstraintBuilderImpl.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.impl.score.stream.common.AbstractConstraintBuilder; import ai.timefold.solver.core.impl.score.stream.common.ScoreImpactType; +import org.jspecify.annotations.NonNull; + public final class QuadConstraintBuilderImpl> extends AbstractConstraintBuilder implements QuadConstraintBuilder { @@ -29,8 +31,9 @@ protected PentaFunction getJustific } @Override - public QuadConstraintBuilder justifyWith( - PentaFunction justificationMapping) { + public @NonNull QuadConstraintBuilder + justifyWith( + @NonNull PentaFunction justificationMapping) { if (this.justificationMapping != null) { throw new IllegalStateException(""" Justification mapping already set (%s). @@ -48,8 +51,8 @@ protected QuadFunction> getIndictedObjectsMapping } @Override - public QuadConstraintBuilder - indictWith(QuadFunction> indictedObjectsMapping) { + public @NonNull QuadConstraintBuilder + indictWith(@NonNull QuadFunction> indictedObjectsMapping) { if (this.indictedObjectsMapping != null) { throw new IllegalStateException(""" Indicted objects' mapping already set (%s). diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/DefaultTriJoiner.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/DefaultTriJoiner.java index 723a4457cc..2f9d5acb0d 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/DefaultTriJoiner.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/DefaultTriJoiner.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.score.stream.JoinerType; import ai.timefold.solver.core.impl.score.stream.common.AbstractJoiner; +import org.jspecify.annotations.NonNull; + public final class DefaultTriJoiner extends AbstractJoiner implements TriJoiner { private static final DefaultTriJoiner NONE = @@ -37,7 +39,7 @@ public static DefaultTriJoiner merge(List and(TriJoiner otherJoiner) { + public @NonNull DefaultTriJoiner and(@NonNull TriJoiner otherJoiner) { DefaultTriJoiner castJoiner = (DefaultTriJoiner) otherJoiner; int joinerCount = getJoinerCount(); int castJoinerCount = castJoiner.getJoinerCount(); diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/FilteringTriJoiner.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/FilteringTriJoiner.java index ecc6f337ef..567fa4d937 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/FilteringTriJoiner.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/FilteringTriJoiner.java @@ -5,6 +5,8 @@ import ai.timefold.solver.core.api.function.TriPredicate; import ai.timefold.solver.core.api.score.stream.tri.TriJoiner; +import org.jspecify.annotations.NonNull; + public final class FilteringTriJoiner implements TriJoiner { private final TriPredicate filter; @@ -14,7 +16,7 @@ public FilteringTriJoiner(TriPredicate filter) { } @Override - public FilteringTriJoiner and(TriJoiner otherJoiner) { + public @NonNull FilteringTriJoiner and(@NonNull TriJoiner otherJoiner) { FilteringTriJoiner castJoiner = (FilteringTriJoiner) otherJoiner; return new FilteringTriJoiner<>(filter.and(castJoiner.getFilter())); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/InnerTriConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/InnerTriConstraintStream.java index 67932d9ca3..6d975c6cf5 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/InnerTriConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/InnerTriConstraintStream.java @@ -21,6 +21,8 @@ import ai.timefold.solver.core.impl.score.stream.common.ScoreImpactType; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + public interface InnerTriConstraintStream extends TriConstraintStream { static QuadFunction, DefaultConstraintJustification> createDefaultJustificationMapping() { @@ -42,7 +44,8 @@ static TriFunction> createDefaultIndictedObject boolean guaranteesDistinct(); @Override - default QuadConstraintStream join(Class otherClass, QuadJoiner... joiners) { + default @NonNull QuadConstraintStream join(@NonNull Class otherClass, + @NonNull QuadJoiner @NonNull... joiners) { if (getRetrievalSemantics() == STANDARD) { return join(getConstraintFactory().forEach(otherClass), joiners); } else { @@ -51,7 +54,8 @@ default QuadConstraintStream join(Class otherClass, QuadJoine } @Override - default TriConstraintStream ifExists(Class otherClass, QuadJoiner... joiners) { + default @NonNull TriConstraintStream ifExists(@NonNull Class otherClass, + @NonNull QuadJoiner @NonNull... joiners) { if (getRetrievalSemantics() == STANDARD) { return ifExists(getConstraintFactory().forEach(otherClass), joiners); } else { @@ -61,8 +65,8 @@ default TriConstraintStream ifExists(Class otherClass, QuadJoine } @Override - default TriConstraintStream ifExistsIncludingUnassigned(Class otherClass, - QuadJoiner... joiners) { + default @NonNull TriConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull QuadJoiner @NonNull... joiners) { if (getRetrievalSemantics() == STANDARD) { return ifExists(getConstraintFactory().forEachIncludingUnassigned(otherClass), joiners); } else { @@ -71,7 +75,8 @@ default TriConstraintStream ifExistsIncludingUnassigned(Class ot } @Override - default TriConstraintStream ifNotExists(Class otherClass, QuadJoiner... joiners) { + default @NonNull TriConstraintStream ifNotExists(@NonNull Class otherClass, + @NonNull QuadJoiner @NonNull... joiners) { if (getRetrievalSemantics() == STANDARD) { return ifNotExists(getConstraintFactory().forEach(otherClass), joiners); } else { @@ -81,8 +86,8 @@ default TriConstraintStream ifNotExists(Class otherClass, QuadJo } @Override - default TriConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, - QuadJoiner... joiners) { + default @NonNull TriConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull QuadJoiner @NonNull... joiners) { if (getRetrievalSemantics() == STANDARD) { return ifNotExists(getConstraintFactory().forEachIncludingUnassigned(otherClass), joiners); } else { @@ -91,7 +96,7 @@ default TriConstraintStream ifNotExistsIncludingUnassigned(Class } @Override - default TriConstraintStream distinct() { + default @NonNull TriConstraintStream distinct() { if (guaranteesDistinct()) { return this; } else { @@ -102,20 +107,23 @@ default TriConstraintStream distinct() { } @Override - default > TriConstraintBuilder penalize(Score_ constraintWeight, - ToIntTriFunction matchWeigher) { + default @NonNull > TriConstraintBuilder penalize( + @NonNull Score_ constraintWeight, + @NonNull ToIntTriFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.PENALTY); } @Override - default > TriConstraintBuilder penalizeLong(Score_ constraintWeight, - ToLongTriFunction matchWeigher) { + default @NonNull > TriConstraintBuilder penalizeLong( + @NonNull Score_ constraintWeight, + @NonNull ToLongTriFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.PENALTY); } @Override - default > TriConstraintBuilder penalizeBigDecimal(Score_ constraintWeight, - TriFunction matchWeigher) { + default @NonNull > TriConstraintBuilder penalizeBigDecimal( + @NonNull Score_ constraintWeight, + @NonNull TriFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.PENALTY); } @@ -135,20 +143,23 @@ default > TriConstraintBuilder pen } @Override - default > TriConstraintBuilder reward(Score_ constraintWeight, - ToIntTriFunction matchWeigher) { + default @NonNull > TriConstraintBuilder reward( + @NonNull Score_ constraintWeight, + @NonNull ToIntTriFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.REWARD); } @Override - default > TriConstraintBuilder rewardLong(Score_ constraintWeight, - ToLongTriFunction matchWeigher) { + default @NonNull > TriConstraintBuilder rewardLong( + @NonNull Score_ constraintWeight, + @NonNull ToLongTriFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.REWARD); } @Override - default > TriConstraintBuilder rewardBigDecimal(Score_ constraintWeight, - TriFunction matchWeigher) { + default @NonNull > TriConstraintBuilder rewardBigDecimal( + @NonNull Score_ constraintWeight, + @NonNull TriFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.REWARD); } @@ -168,20 +179,23 @@ default > TriConstraintBuilder rew } @Override - default > TriConstraintBuilder impact(Score_ constraintWeight, - ToIntTriFunction matchWeigher) { + default @NonNull > TriConstraintBuilder impact( + @NonNull Score_ constraintWeight, + @NonNull ToIntTriFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.MIXED); } @Override - default > TriConstraintBuilder impactLong(Score_ constraintWeight, - ToLongTriFunction matchWeigher) { + default @NonNull > TriConstraintBuilder impactLong( + @NonNull Score_ constraintWeight, + @NonNull ToLongTriFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.MIXED); } @Override - default > TriConstraintBuilder impactBigDecimal(Score_ constraintWeight, - TriFunction matchWeigher) { + default @NonNull > TriConstraintBuilder impactBigDecimal( + @NonNull Score_ constraintWeight, + @NonNull TriFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.MIXED); } @@ -213,61 +227,64 @@ > TriConstraintBuilder innerImpact ScoreImpactType scoreImpactType); @Override - default Constraint penalize(String constraintName, Score constraintWeight) { + default @NonNull Constraint penalize(@NonNull String constraintName, @NonNull Score constraintWeight) { return penalize((Score) constraintWeight) .asConstraint(constraintName); } @Override - default Constraint penalize(String constraintPackage, String constraintName, Score constraintWeight) { + default @NonNull Constraint penalize(@NonNull String constraintPackage, @NonNull String constraintName, + @NonNull Score constraintWeight) { return penalize((Score) constraintWeight) .asConstraint(constraintPackage, constraintName); } @Override - default Constraint penalizeConfigurable(String constraintName) { + default @NonNull Constraint penalizeConfigurable(@NonNull String constraintName) { return penalizeConfigurable() .asConstraint(constraintName); } @Override - default Constraint penalizeConfigurable(String constraintPackage, String constraintName) { + default @NonNull Constraint penalizeConfigurable(@NonNull String constraintPackage, @NonNull String constraintName) { return penalizeConfigurable() .asConstraint(constraintPackage, constraintName); } @Override - default Constraint reward(String constraintName, Score constraintWeight) { + default @NonNull Constraint reward(@NonNull String constraintName, @NonNull Score constraintWeight) { return reward((Score) constraintWeight) .asConstraint(constraintName); } @Override - default Constraint reward(String constraintPackage, String constraintName, Score constraintWeight) { + default @NonNull Constraint reward(@NonNull String constraintPackage, @NonNull String constraintName, + @NonNull Score constraintWeight) { return reward((Score) constraintWeight) .asConstraint(constraintPackage, constraintName); } @Override - default Constraint rewardConfigurable(String constraintName) { + default @NonNull Constraint rewardConfigurable(@NonNull String constraintName) { return rewardConfigurable() .asConstraint(constraintName); } @Override - default Constraint rewardConfigurable(String constraintPackage, String constraintName) { + default @NonNull Constraint rewardConfigurable(@NonNull String constraintPackage, @NonNull String constraintName) { return penalizeConfigurable() .asConstraint(constraintPackage, constraintName); } @Override - default Constraint impact(String constraintName, Score constraintWeight) { + default @NonNull Constraint impact(@NonNull String constraintName, @NonNull Score constraintWeight) { return impact((Score) constraintWeight) .asConstraint(constraintName); } @Override - default Constraint impact(String constraintPackage, String constraintName, Score constraintWeight) { + default @NonNull Constraint impact(@NonNull String constraintPackage, @NonNull String constraintName, + @NonNull Score constraintWeight) { return impact((Score) constraintWeight) .asConstraint(constraintPackage, constraintName); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/TriConstraintBuilderImpl.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/TriConstraintBuilderImpl.java index 2e41fd5fc5..d268c68302 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/TriConstraintBuilderImpl.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/tri/TriConstraintBuilderImpl.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.impl.score.stream.common.AbstractConstraintBuilder; import ai.timefold.solver.core.impl.score.stream.common.ScoreImpactType; +import org.jspecify.annotations.NonNull; + public final class TriConstraintBuilderImpl> extends AbstractConstraintBuilder implements TriConstraintBuilder { @@ -29,8 +31,9 @@ protected QuadFunction getJustificatio } @Override - public TriConstraintBuilder justifyWith( - QuadFunction justificationMapping) { + public @NonNull TriConstraintBuilder + justifyWith( + @NonNull QuadFunction justificationMapping) { if (this.justificationMapping != null) { throw new IllegalStateException(""" Justification mapping already set (%s). @@ -48,7 +51,8 @@ protected TriFunction> getIndictedObjectsMapping() { } @Override - public TriConstraintBuilder indictWith(TriFunction> indictedObjectsMapping) { + public @NonNull TriConstraintBuilder + indictWith(@NonNull TriFunction> indictedObjectsMapping) { if (this.indictedObjectsMapping != null) { throw new IllegalStateException(""" Indicted objects' mapping already set (%s). diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/uni/InnerUniConstraintStream.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/uni/InnerUniConstraintStream.java index 590ea2b7b4..786f718b2c 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/uni/InnerUniConstraintStream.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/uni/InnerUniConstraintStream.java @@ -23,6 +23,8 @@ import ai.timefold.solver.core.impl.score.stream.common.bi.BiJoinerComber; import ai.timefold.solver.core.impl.util.ConstantLambdaUtils; +import org.jspecify.annotations.NonNull; + public interface InnerUniConstraintStream extends UniConstraintStream { static BiFunction, DefaultConstraintJustification> createDefaultJustificationMapping() { @@ -44,7 +46,7 @@ static Function> createDefaultIndictedObjectsMapping() { boolean guaranteesDistinct(); @Override - default BiConstraintStream join(Class otherClass, BiJoiner... joiners) { + default @NonNull BiConstraintStream join(@NonNull Class otherClass, @NonNull BiJoiner... joiners) { if (getRetrievalSemantics() == STANDARD) { return join(getConstraintFactory().forEach(otherClass), joiners); } else { @@ -63,7 +65,7 @@ default BiConstraintStream join(Class otherClass, BiJoiner... BiConstraintStream join(UniConstraintStream otherStream, BiJoinerComber joinerComber); @Override - default UniConstraintStream ifExists(Class otherClass, BiJoiner... joiners) { + default @NonNull UniConstraintStream ifExists(@NonNull Class otherClass, @NonNull BiJoiner... joiners) { if (getRetrievalSemantics() == STANDARD) { return ifExists(getConstraintFactory().forEach(otherClass), joiners); } else { @@ -73,7 +75,8 @@ default UniConstraintStream ifExists(Class otherClass, BiJoiner. } @Override - default UniConstraintStream ifExistsIncludingUnassigned(Class otherClass, BiJoiner... joiners) { + default @NonNull UniConstraintStream ifExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner... joiners) { if (getRetrievalSemantics() == STANDARD) { return ifExists(getConstraintFactory().forEachIncludingUnassigned(otherClass), joiners); } else { @@ -82,7 +85,7 @@ default UniConstraintStream ifExistsIncludingUnassigned(Class otherCla } @Override - default UniConstraintStream ifNotExists(Class otherClass, BiJoiner... joiners) { + default @NonNull UniConstraintStream ifNotExists(@NonNull Class otherClass, @NonNull BiJoiner... joiners) { if (getRetrievalSemantics() == STANDARD) { return ifNotExists(getConstraintFactory().forEach(otherClass), joiners); } else { @@ -92,7 +95,8 @@ default UniConstraintStream ifNotExists(Class otherClass, BiJoiner UniConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, BiJoiner... joiners) { + default @NonNull UniConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull BiJoiner... joiners) { if (getRetrievalSemantics() == STANDARD) { return ifNotExists(getConstraintFactory().forEachIncludingUnassigned(otherClass), joiners); } else { @@ -101,7 +105,7 @@ default UniConstraintStream ifNotExistsIncludingUnassigned(Class other } @Override - default UniConstraintStream distinct() { + default @NonNull UniConstraintStream distinct() { if (guaranteesDistinct()) { return this; } else { @@ -110,20 +114,22 @@ default UniConstraintStream distinct() { } @Override - default > UniConstraintBuilder penalize(Score_ constraintWeight, - ToIntFunction matchWeigher) { + default @NonNull > UniConstraintBuilder penalize(@NonNull Score_ constraintWeight, + @NonNull ToIntFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.PENALTY); } @Override - default > UniConstraintBuilder penalizeLong(Score_ constraintWeight, - ToLongFunction matchWeigher) { + default @NonNull > UniConstraintBuilder penalizeLong( + @NonNull Score_ constraintWeight, + @NonNull ToLongFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.PENALTY); } @Override - default > UniConstraintBuilder penalizeBigDecimal(Score_ constraintWeight, - Function matchWeigher) { + default @NonNull > UniConstraintBuilder penalizeBigDecimal( + @NonNull Score_ constraintWeight, + @NonNull Function matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.PENALTY); } @@ -143,20 +149,21 @@ default > UniConstraintBuilder penalizeB } @Override - default > UniConstraintBuilder reward(Score_ constraintWeight, - ToIntFunction matchWeigher) { + default @NonNull > UniConstraintBuilder reward(@NonNull Score_ constraintWeight, + @NonNull ToIntFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.REWARD); } @Override - default > UniConstraintBuilder rewardLong(Score_ constraintWeight, - ToLongFunction matchWeigher) { + default @NonNull > UniConstraintBuilder rewardLong(@NonNull Score_ constraintWeight, + @NonNull ToLongFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.REWARD); } @Override - default > UniConstraintBuilder rewardBigDecimal(Score_ constraintWeight, - Function matchWeigher) { + default @NonNull > UniConstraintBuilder rewardBigDecimal( + @NonNull Score_ constraintWeight, + @NonNull Function matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.REWARD); } @@ -176,20 +183,21 @@ default > UniConstraintBuilder rewardBig } @Override - default > UniConstraintBuilder impact(Score_ constraintWeight, - ToIntFunction matchWeigher) { + default @NonNull > UniConstraintBuilder impact(@NonNull Score_ constraintWeight, + @NonNull ToIntFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.MIXED); } @Override - default > UniConstraintBuilder impactLong(Score_ constraintWeight, - ToLongFunction matchWeigher) { + default @NonNull > UniConstraintBuilder impactLong(@NonNull Score_ constraintWeight, + @NonNull ToLongFunction matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.MIXED); } @Override - default > UniConstraintBuilder impactBigDecimal(Score_ constraintWeight, - Function matchWeigher) { + default @NonNull > UniConstraintBuilder impactBigDecimal( + @NonNull Score_ constraintWeight, + @NonNull Function matchWeigher) { return innerImpact(constraintWeight, matchWeigher, ScoreImpactType.MIXED); } @@ -218,61 +226,64 @@ > UniConstraintBuilder innerImpact(Score Function matchWeigher, ScoreImpactType scoreImpactType); @Override - default Constraint penalize(String constraintName, Score constraintWeight) { + default @NonNull Constraint penalize(@NonNull String constraintName, @NonNull Score constraintWeight) { return penalize((Score) constraintWeight) .asConstraint(constraintName); } @Override - default Constraint penalize(String constraintPackage, String constraintName, Score constraintWeight) { + default @NonNull Constraint penalize(@NonNull String constraintPackage, @NonNull String constraintName, + @NonNull Score constraintWeight) { return penalize((Score) constraintWeight) .asConstraint(constraintPackage, constraintName); } @Override - default Constraint penalizeConfigurable(String constraintName) { + default @NonNull Constraint penalizeConfigurable(@NonNull String constraintName) { return penalizeConfigurable() .asConstraint(constraintName); } @Override - default Constraint penalizeConfigurable(String constraintPackage, String constraintName) { + default @NonNull Constraint penalizeConfigurable(@NonNull String constraintPackage, @NonNull String constraintName) { return penalizeConfigurable() .asConstraint(constraintPackage, constraintName); } @Override - default Constraint reward(String constraintName, Score constraintWeight) { + default @NonNull Constraint reward(@NonNull String constraintName, @NonNull Score constraintWeight) { return reward((Score) constraintWeight) .asConstraint(constraintName); } @Override - default Constraint reward(String constraintPackage, String constraintName, Score constraintWeight) { + default @NonNull Constraint reward(@NonNull String constraintPackage, @NonNull String constraintName, + @NonNull Score constraintWeight) { return reward((Score) constraintWeight) .asConstraint(constraintPackage, constraintName); } @Override - default Constraint rewardConfigurable(String constraintName) { + default @NonNull Constraint rewardConfigurable(@NonNull String constraintName) { return rewardConfigurable() .asConstraint(constraintName); } @Override - default Constraint rewardConfigurable(String constraintPackage, String constraintName) { + default @NonNull Constraint rewardConfigurable(@NonNull String constraintPackage, @NonNull String constraintName) { return penalizeConfigurable() .asConstraint(constraintPackage, constraintName); } @Override - default Constraint impact(String constraintName, Score constraintWeight) { + default @NonNull Constraint impact(@NonNull String constraintName, @NonNull Score constraintWeight) { return impact((Score) constraintWeight) .asConstraint(constraintName); } @Override - default Constraint impact(String constraintPackage, String constraintName, Score constraintWeight) { + default @NonNull Constraint impact(@NonNull String constraintPackage, @NonNull String constraintName, + @NonNull Score constraintWeight) { return impact((Score) constraintWeight) .asConstraint(constraintPackage, constraintName); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/uni/UniConstraintBuilderImpl.java b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/uni/UniConstraintBuilderImpl.java index 38fe2700c7..76f594e9b7 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/uni/UniConstraintBuilderImpl.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/uni/UniConstraintBuilderImpl.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.impl.score.stream.common.AbstractConstraintBuilder; import ai.timefold.solver.core.impl.score.stream.common.ScoreImpactType; +import org.jspecify.annotations.NonNull; + public final class UniConstraintBuilderImpl> extends AbstractConstraintBuilder implements UniConstraintBuilder { @@ -29,8 +31,8 @@ protected BiFunction getJustificationMapping } @Override - public UniConstraintBuilder justifyWith( - BiFunction justificationMapping) { + public @NonNull UniConstraintBuilder justifyWith( + @NonNull BiFunction justificationMapping) { if (this.justificationMapping != null) { throw new IllegalStateException(""" Justification mapping already set (%s). @@ -48,7 +50,8 @@ protected Function> getIndictedObjectsMapping() { } @Override - public UniConstraintBuilder indictWith(Function> indictedObjectsMapping) { + public @NonNull UniConstraintBuilder + indictWith(@NonNull Function> indictedObjectsMapping) { if (this.indictedObjectsMapping != null) { throw new IllegalStateException(""" Indicted objects' mapping already set (%s). diff --git a/core/src/main/java/ai/timefold/solver/core/impl/solver/AbstractSolver.java b/core/src/main/java/ai/timefold/solver/core/impl/solver/AbstractSolver.java index d487c7d33e..68bc5159f1 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/solver/AbstractSolver.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/solver/AbstractSolver.java @@ -17,6 +17,7 @@ import ai.timefold.solver.core.impl.solver.scope.SolverScope; import ai.timefold.solver.core.impl.solver.termination.Termination; +import org.jspecify.annotations.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -137,12 +138,12 @@ public void stepEnded(AbstractStepScope stepScope) { // ************************************************************************ @Override - public void addEventListener(SolverEventListener eventListener) { + public void addEventListener(@NonNull SolverEventListener eventListener) { solverEventSupport.addEventListener(eventListener); } @Override - public void removeEventListener(SolverEventListener eventListener) { + public void removeEventListener(@NonNull SolverEventListener eventListener) { solverEventSupport.removeEventListener(eventListener); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/solver/BestSolutionHolder.java b/core/src/main/java/ai/timefold/solver/core/impl/solver/BestSolutionHolder.java index 0cdf045b49..e5880ea7d1 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/solver/BestSolutionHolder.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/solver/BestSolutionHolder.java @@ -16,6 +16,8 @@ import ai.timefold.solver.core.api.solver.Solver; import ai.timefold.solver.core.api.solver.change.ProblemChange; +import org.jspecify.annotations.NonNull; + final class BestSolutionHolder { private final Lock problemChangesLock = new ReentrantLock(); @@ -83,6 +85,7 @@ void set(Solution_ bestSolution, BooleanSupplier isEveryProblemChangeProcessed) * @return CompletableFuture that will be completed after the best solution containing this change is passed to * a user-defined Consumer. */ + @NonNull CompletableFuture addProblemChange(Solver solver, ProblemChange problemChange) { problemChangesLock.lock(); try { diff --git a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultRecommendedAssignment.java b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultRecommendedAssignment.java index 8a0eb076d5..f8205d7fb4 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultRecommendedAssignment.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultRecommendedAssignment.java @@ -4,8 +4,11 @@ import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; import ai.timefold.solver.core.api.solver.RecommendedAssignment; -public record DefaultRecommendedAssignment>(long index, Proposition_ proposition, - ScoreAnalysis scoreAnalysisDiff) +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + +public record DefaultRecommendedAssignment>(long index, + @Nullable Proposition_ proposition, @NonNull ScoreAnalysis scoreAnalysisDiff) implements RecommendedAssignment, Comparable> { diff --git a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultRecommendedFit.java b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultRecommendedFit.java index d7724939d7..9cb9396417 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultRecommendedFit.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultRecommendedFit.java @@ -4,12 +4,15 @@ import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; import ai.timefold.solver.core.api.solver.RecommendedFit; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * @deprecated Prefer {@link DefaultRecommendedAssignment} instead. */ @Deprecated(forRemoval = true, since = "1.15.0") -public record DefaultRecommendedFit>(long index, Proposition_ proposition, - ScoreAnalysis scoreAnalysisDiff) +public record DefaultRecommendedFit>(long index, @Nullable Proposition_ proposition, + @NonNull ScoreAnalysis scoreAnalysisDiff) implements RecommendedFit, Comparable> { diff --git a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolutionManager.java b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolutionManager.java index 91d70992ec..1d07209042 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolutionManager.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolutionManager.java @@ -20,6 +20,9 @@ import ai.timefold.solver.core.impl.score.director.InnerScoreDirector; import ai.timefold.solver.core.impl.score.director.InnerScoreDirectorFactory; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * @param the solution type, the class with the {@link PlanningSolution} annotation */ @@ -43,7 +46,7 @@ public InnerScoreDirectorFactory getScoreDirectorFactory() { } @Override - public Score_ update(Solution_ solution, SolutionUpdatePolicy solutionUpdatePolicy) { + public @Nullable Score_ update(@NonNull Solution_ solution, @NonNull SolutionUpdatePolicy solutionUpdatePolicy) { if (solutionUpdatePolicy == SolutionUpdatePolicy.NO_UPDATE) { throw new IllegalArgumentException("Can not call " + this.getClass().getSimpleName() + ".update() with this solutionUpdatePolicy (" + solutionUpdatePolicy + ")."); @@ -78,7 +81,8 @@ private Result_ callScoreDirector(Solution_ solution, @SuppressWarnings("unchecked") @Override - public ScoreExplanation explain(Solution_ solution, SolutionUpdatePolicy solutionUpdatePolicy) { + public @NonNull ScoreExplanation explain(@NonNull Solution_ solution, + @NonNull SolutionUpdatePolicy solutionUpdatePolicy) { var currentScore = (Score_) scoreDirectorFactory.getSolutionDescriptor().getScore(solution); var explanation = callScoreDirector(solution, solutionUpdatePolicy, DefaultScoreExplanation::new, true, false); assertFreshScore(solution, currentScore, explanation.getScore(), solutionUpdatePolicy); @@ -105,8 +109,8 @@ Current score (%s) and freshly calculated score (%s) for solution (%s) do not ma @SuppressWarnings("unchecked") @Override - public ScoreAnalysis analyze(Solution_ solution, ScoreAnalysisFetchPolicy fetchPolicy, - SolutionUpdatePolicy solutionUpdatePolicy) { + public @NonNull ScoreAnalysis analyze(@NonNull Solution_ solution, @NonNull ScoreAnalysisFetchPolicy fetchPolicy, + @NonNull SolutionUpdatePolicy solutionUpdatePolicy) { Objects.requireNonNull(fetchPolicy, "fetchPolicy"); var currentScore = (Score_) scoreDirectorFactory.getSolutionDescriptor().getScore(solution); var analysis = callScoreDirector(solution, solutionUpdatePolicy, @@ -117,8 +121,9 @@ public ScoreAnalysis analyze(Solution_ solution, ScoreAnalysisFetchPolic } @Override - public List> recommendAssignment(Solution_ solution, - In_ evaluatedEntityOrElement, Function propositionFunction, ScoreAnalysisFetchPolicy fetchPolicy) { + public @NonNull List> recommendAssignment(@NonNull Solution_ solution, + @NonNull In_ evaluatedEntityOrElement, @NonNull Function propositionFunction, + @NonNull ScoreAnalysisFetchPolicy fetchPolicy) { var assigner = new Assigner, In_, Out_>(solverFactory, propositionFunction, DefaultRecommendedAssignment::new, fetchPolicy, solution, evaluatedEntityOrElement); return callScoreDirector(solution, SolutionUpdatePolicy.UPDATE_ALL, assigner, true, true); diff --git a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolver.java b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolver.java index bb82457e07..9960df305a 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolver.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolver.java @@ -27,6 +27,8 @@ import ai.timefold.solver.core.impl.solver.termination.BasicPlumbingTermination; import ai.timefold.solver.core.impl.solver.termination.Termination; +import org.jspecify.annotations.NonNull; + import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.LongTaskTimer; import io.micrometer.core.instrument.Metrics; @@ -128,12 +130,12 @@ public boolean isTerminateEarly() { } @Override - public boolean addProblemFactChange(ProblemFactChange problemFactChange) { + public boolean addProblemFactChange(@NonNull ProblemFactChange problemFactChange) { return basicPlumbingTermination.addProblemChange(ProblemChangeAdapter.create(problemFactChange)); } @Override - public boolean addProblemFactChanges(List> problemFactChangeList) { + public boolean addProblemFactChanges(@NonNull List> problemFactChangeList) { Objects.requireNonNull(problemFactChangeList, () -> "The list of problem fact changes (" + problemFactChangeList + ") cannot be null."); List> problemChangeAdapterList = problemFactChangeList.stream() @@ -143,12 +145,12 @@ public boolean addProblemFactChanges(List> problemF } @Override - public void addProblemChange(ProblemChange problemChange) { + public void addProblemChange(@NonNull ProblemChange problemChange) { basicPlumbingTermination.addProblemChange(ProblemChangeAdapter.create(problemChange)); } @Override - public void addProblemChanges(List> problemChangeList) { + public void addProblemChanges(@NonNull List> problemChangeList) { Objects.requireNonNull(problemChangeList, () -> "The list of problem changes (" + problemChangeList + ") cannot be null."); problemChangeList.forEach(this::addProblemChange); @@ -176,7 +178,9 @@ public void setMonitorTagMap(Map monitorTagMap) { // ************************************************************************ @Override - public final Solution_ solve(Solution_ problem) { + public final @NonNull Solution_ solve(@NonNull Solution_ problem) { + // TODO: I suppose @NonNull does not guarantee the solution really is not null + // does it make sense to keep this check + the exception? if (problem == null) { throw new IllegalArgumentException("The problem (" + problem + ") must not be null."); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverFactory.java b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverFactory.java index 98ef08bf2d..5a4b3cb43c 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverFactory.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverFactory.java @@ -42,6 +42,8 @@ import ai.timefold.solver.core.impl.solver.termination.Termination; import ai.timefold.solver.core.impl.solver.termination.TerminationFactory; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -76,7 +78,7 @@ public > InnerScoreDirectorFactory buildSolver(SolverConfigOverride configOverride) { + public @NonNull Solver buildSolver(@NonNull SolverConfigOverride configOverride) { Objects.requireNonNull(configOverride, "Invalid configOverride (null) given to SolverFactory."); var isDaemon = Objects.requireNonNullElse(solverConfig.getDaemon(), false); @@ -129,7 +131,7 @@ public Solver buildSolver(SolverConfigOverride configOverr moveThreadCount == null ? SolverConfig.MOVE_THREAD_COUNT_NONE : Integer.toString(moveThreadCount)); } - public Integer resolveMoveThreadCount(boolean enforceMaximum) { + public @Nullable Integer resolveMoveThreadCount(boolean enforceMaximum) { var maybeCount = new MoveThreadCountResolver().resolveMoveThreadCount(solverConfig.getMoveThreadCount(), enforceMaximum); if (maybeCount.isPresent()) { diff --git a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverJob.java b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverJob.java index 11a5cc04d0..908693c794 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverJob.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverJob.java @@ -28,6 +28,7 @@ import ai.timefold.solver.core.impl.solver.scope.SolverScope; import ai.timefold.solver.core.impl.solver.termination.Termination; +import org.jspecify.annotations.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -89,12 +90,12 @@ public void setFinalBestSolutionFuture(Future finalBestSolutionFuture } @Override - public ProblemId_ getProblemId() { + public @NonNull ProblemId_ getProblemId() { return problemId; } @Override - public SolverStatus getSolverStatus() { + public @NonNull SolverStatus getSolverStatus() { return solverStatus; } @@ -161,7 +162,7 @@ private void solvingTerminated() { // } @Override - public CompletableFuture addProblemChange(ProblemChange problemChange) { + public @NonNull CompletableFuture addProblemChange(@NonNull ProblemChange problemChange) { Objects.requireNonNull(problemChange, () -> "A problem change (%s) must not be null.".formatted(problemId)); if (solverStatus == SolverStatus.NOT_SOLVING) { throw new IllegalStateException("Cannot add the problem change (%s) because the solver job (%s) is not solving." @@ -210,7 +211,7 @@ public boolean isTerminatedEarly() { } @Override - public Solution_ getFinalBestSolution() throws InterruptedException, ExecutionException { + public @NonNull Solution_ getFinalBestSolution() throws InterruptedException, ExecutionException { try { return finalBestSolutionFuture.get(); } catch (CancellationException cancellationException) { @@ -221,7 +222,7 @@ public Solution_ getFinalBestSolution() throws InterruptedException, ExecutionEx } @Override - public Duration getSolvingDuration() { + public @NonNull Duration getSolvingDuration() { return Duration.ofMillis(solver.getTimeMillisSpent()); } @@ -246,7 +247,7 @@ public long getMoveEvaluationSpeed() { } @Override - public ProblemSizeStatistics getProblemSizeStatistics() { + public @NonNull ProblemSizeStatistics getProblemSizeStatistics() { var problemSizeStatistics = solver.getSolverScope().getProblemSizeStatistics(); if (problemSizeStatistics != null) { return problemSizeStatistics; diff --git a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverJobBuilder.java b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverJobBuilder.java index 1a86b31ba6..28220f341a 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverJobBuilder.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverJobBuilder.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.api.solver.SolverJob; import ai.timefold.solver.core.api.solver.SolverJobBuilder; +import org.jspecify.annotations.NonNull; + /** * @param the solution type, the class with the {@link PlanningSolution} annotation * @param the ID type of submitted problem, such as {@link Long} or {@link UUID}. @@ -32,36 +34,37 @@ public DefaultSolverJobBuilder(DefaultSolverManager solve } @Override - public SolverJobBuilder withProblemId(ProblemId_ problemId) { + public @NonNull SolverJobBuilder withProblemId(@NonNull ProblemId_ problemId) { this.problemId = Objects.requireNonNull(problemId, "Invalid problemId (null) given to SolverJobBuilder."); return this; } @Override - public SolverJobBuilder - withProblemFinder(Function problemFinder) { + public @NonNull SolverJobBuilder + withProblemFinder(@NonNull Function problemFinder) { this.problemFinder = Objects.requireNonNull(problemFinder, "Invalid problemFinder (null) given to SolverJobBuilder."); return this; } @Override - public SolverJobBuilder withBestSolutionConsumer(Consumer bestSolutionConsumer) { + public @NonNull SolverJobBuilder + withBestSolutionConsumer(@NonNull Consumer bestSolutionConsumer) { this.bestSolutionConsumer = Objects.requireNonNull(bestSolutionConsumer, "Invalid bestSolutionConsumer (null) given to SolverJobBuilder."); return this; } @Override - public SolverJobBuilder - withFinalBestSolutionConsumer(Consumer finalBestSolutionConsumer) { + public @NonNull SolverJobBuilder + withFinalBestSolutionConsumer(@NonNull Consumer finalBestSolutionConsumer) { this.finalBestSolutionConsumer = Objects.requireNonNull(finalBestSolutionConsumer, "Invalid finalBestSolutionConsumer (null) given to SolverJobBuilder."); return this; } @Override - public SolverJobBuilder - withFirstInitializedSolutionConsumer(Consumer firstInitializedSolutionConsumer) { + public @NonNull SolverJobBuilder + withFirstInitializedSolutionConsumer(@NonNull Consumer firstInitializedSolutionConsumer) { this.initializedSolutionConsumer = Objects.requireNonNull(firstInitializedSolutionConsumer, "Invalid initializedSolutionConsumer (null) given to SolverJobBuilder."); return this; @@ -76,22 +79,23 @@ public SolverJobBuilder withBestSolutionConsumer(Consumer } @Override - public SolverJobBuilder - withExceptionHandler(BiConsumer exceptionHandler) { + public @NonNull SolverJobBuilder + withExceptionHandler(@NonNull BiConsumer exceptionHandler) { this.exceptionHandler = Objects.requireNonNull(exceptionHandler, "Invalid exceptionHandler (null) given to SolverJobBuilder."); return this; } @Override - public SolverJobBuilder withConfigOverride(SolverConfigOverride solverConfigOverride) { + public @NonNull SolverJobBuilder + withConfigOverride(@NonNull SolverConfigOverride solverConfigOverride) { this.solverConfigOverride = Objects.requireNonNull(solverConfigOverride, "Invalid solverConfigOverride (null) given to SolverJobBuilder."); return this; } @Override - public SolverJob run() { + public @NonNull SolverJob run() { if (solverConfigOverride == null) { // The config is required by SolverFactory and it must be initialized this.solverConfigOverride = new SolverConfigOverride<>(); diff --git a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverManager.java b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverManager.java index 0e68c7efe9..d8f0567ba1 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverManager.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolverManager.java @@ -25,6 +25,7 @@ import ai.timefold.solver.core.config.solver.SolverManagerConfig; import ai.timefold.solver.core.config.util.ConfigUtils; +import org.jspecify.annotations.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -74,7 +75,7 @@ private DefaultSolverJob getSolverJob(ProblemId_ problemI } @Override - public SolverJobBuilder solveBuilder() { + public @NonNull SolverJobBuilder solveBuilder() { return new DefaultSolverJobBuilder<>(this); } @@ -123,7 +124,7 @@ protected SolverJob solve(ProblemId_ problemId, } @Override - public SolverStatus getSolverStatus(ProblemId_ problemId) { + public @NonNull SolverStatus getSolverStatus(@NonNull ProblemId_ problemId) { DefaultSolverJob solverJob = getSolverJob(problemId); if (solverJob == null) { return SolverStatus.NOT_SOLVING; @@ -144,7 +145,8 @@ public SolverStatus getSolverStatus(ProblemId_ problemId) { // } @Override - public CompletableFuture addProblemChange(ProblemId_ problemId, ProblemChange problemChange) { + public @NonNull CompletableFuture addProblemChange(@NonNull ProblemId_ problemId, + @NonNull ProblemChange problemChange) { DefaultSolverJob solverJob = getSolverJob(problemId); if (solverJob == null) { // We cannot distinguish between "already terminated" and "never solved" without causing a memory leak. @@ -156,7 +158,7 @@ public CompletableFuture addProblemChange(ProblemId_ problemId, ProblemCha } @Override - public void terminateEarly(ProblemId_ problemId) { + public void terminateEarly(@NonNull ProblemId_ problemId) { DefaultSolverJob solverJob = getSolverJob(problemId); if (solverJob == null) { // We cannot distinguish between "already terminated" and "never solved" without causing a memory leak. diff --git a/core/src/main/java/ai/timefold/solver/core/impl/solver/change/DefaultProblemChangeDirector.java b/core/src/main/java/ai/timefold/solver/core/impl/solver/change/DefaultProblemChangeDirector.java index 392d673754..0949e8e142 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/solver/change/DefaultProblemChangeDirector.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/solver/change/DefaultProblemChangeDirector.java @@ -9,6 +9,9 @@ import ai.timefold.solver.core.api.solver.change.ProblemChangeDirector; import ai.timefold.solver.core.impl.score.director.InnerScoreDirector; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + public final class DefaultProblemChangeDirector implements ProblemChangeDirector { private final InnerScoreDirector scoreDirector; @@ -18,7 +21,7 @@ public DefaultProblemChangeDirector(InnerScoreDirector scoreDirect } @Override - public void addEntity(Entity entity, Consumer entityConsumer) { + public void addEntity(@NonNull Entity entity, @NonNull Consumer entityConsumer) { Objects.requireNonNull(entity, () -> "Entity (" + entity + ") cannot be null."); Objects.requireNonNull(entityConsumer, () -> "Entity consumer (" + entityConsumer + ") cannot be null."); scoreDirector.beforeEntityAdded(entity); @@ -27,7 +30,7 @@ public void addEntity(Entity entity, Consumer entityConsumer) { } @Override - public void removeEntity(Entity entity, Consumer entityConsumer) { + public void removeEntity(@NonNull Entity entity, @NonNull Consumer entityConsumer) { Objects.requireNonNull(entity, () -> "Entity (" + entity + ") cannot be null."); Objects.requireNonNull(entityConsumer, () -> "Entity consumer (" + entityConsumer + ") cannot be null."); Entity workingEntity = lookUpWorkingObjectOrFail(entity); @@ -37,7 +40,8 @@ public void removeEntity(Entity entity, Consumer entityConsumer } @Override - public void changeVariable(Entity entity, String variableName, Consumer entityConsumer) { + public void changeVariable(@NonNull Entity entity, @NonNull String variableName, + @NonNull Consumer entityConsumer) { Objects.requireNonNull(entity, () -> "Entity (" + entity + ") cannot be null."); Objects.requireNonNull(variableName, () -> "Planning variable name (" + variableName + ") cannot be null."); Objects.requireNonNull(entityConsumer, () -> "Entity consumer (" + entityConsumer + ") cannot be null."); @@ -48,7 +52,8 @@ public void changeVariable(Entity entity, String variableName, Consumer } @Override - public void addProblemFact(ProblemFact problemFact, Consumer problemFactConsumer) { + public void addProblemFact(@NonNull ProblemFact problemFact, + @NonNull Consumer problemFactConsumer) { Objects.requireNonNull(problemFact, () -> "Problem fact (" + problemFact + ") cannot be null."); Objects.requireNonNull(problemFactConsumer, () -> "Problem fact consumer (" + problemFactConsumer + ") cannot be null."); @@ -58,7 +63,8 @@ public void addProblemFact(ProblemFact problemFact, Consumer void removeProblemFact(ProblemFact problemFact, Consumer problemFactConsumer) { + public void removeProblemFact(@NonNull ProblemFact problemFact, + @NonNull Consumer problemFactConsumer) { Objects.requireNonNull(problemFact, () -> "Problem fact (" + problemFact + ") cannot be null."); Objects.requireNonNull(problemFactConsumer, () -> "Problem fact consumer (" + problemFactConsumer + ") cannot be null."); @@ -69,8 +75,8 @@ public void removeProblemFact(ProblemFact problemFact, Consumer void changeProblemProperty(EntityOrProblemFact problemFactOrEntity, - Consumer problemFactOrEntityConsumer) { + public void changeProblemProperty(@NonNull EntityOrProblemFact problemFactOrEntity, + @NonNull Consumer problemFactOrEntityConsumer) { Objects.requireNonNull(problemFactOrEntity, () -> "Problem fact or entity (" + problemFactOrEntity + ") cannot be null."); Objects.requireNonNull(problemFactOrEntityConsumer, () -> "Problem fact or entity consumer (" @@ -82,7 +88,8 @@ public void changeProblemProperty(EntityOrProblemFact prob } @Override - public EntityOrProblemFact lookUpWorkingObjectOrFail(EntityOrProblemFact externalObject) { + public @Nullable EntityOrProblemFact + lookUpWorkingObjectOrFail(@Nullable EntityOrProblemFact externalObject) { return scoreDirector.lookUpWorkingObject(externalObject); } diff --git a/core/src/main/java/ai/timefold/solver/core/impl/statistic/BestSolutionMutationCountStatistic.java b/core/src/main/java/ai/timefold/solver/core/impl/statistic/BestSolutionMutationCountStatistic.java index 478c109761..57aa059b0d 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/statistic/BestSolutionMutationCountStatistic.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/statistic/BestSolutionMutationCountStatistic.java @@ -12,6 +12,8 @@ import ai.timefold.solver.core.impl.score.director.InnerScoreDirectorFactory; import ai.timefold.solver.core.impl.solver.DefaultSolver; +import org.jspecify.annotations.NonNull; + import io.micrometer.core.instrument.Metrics; public class BestSolutionMutationCountStatistic implements SolverStatistic { @@ -55,7 +57,7 @@ public int getMutationCount() { } @Override - public void bestSolutionChanged(BestSolutionChangedEvent event) { + public void bestSolutionChanged(@NonNull BestSolutionChangedEvent event) { Solution_ newBestSolution = event.getNewBestSolution(); if (oldBestSolution == null) { mutationCount = 0; diff --git a/core/src/test/java/ai/timefold/solver/core/config/solver/SolverConfigTest.java b/core/src/test/java/ai/timefold/solver/core/config/solver/SolverConfigTest.java index dbad8c99c9..0a0851db69 100644 --- a/core/src/test/java/ai/timefold/solver/core/config/solver/SolverConfigTest.java +++ b/core/src/test/java/ai/timefold/solver/core/config/solver/SolverConfigTest.java @@ -56,6 +56,7 @@ import org.apache.commons.io.IOUtils; import org.assertj.core.api.Assertions; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -356,7 +357,7 @@ private class DummyEntityForListVariable { public static class DummyRecordEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataRecordSolution solution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataRecordSolution solution) { return SimpleScore.of(solution.getEntityList().size()); } } diff --git a/core/src/test/java/ai/timefold/solver/core/config/solver/testutil/calculator/AbstractTestdataDifferentValuesCalculator.java b/core/src/test/java/ai/timefold/solver/core/config/solver/testutil/calculator/AbstractTestdataDifferentValuesCalculator.java index d50575e594..06762bfea9 100644 --- a/core/src/test/java/ai/timefold/solver/core/config/solver/testutil/calculator/AbstractTestdataDifferentValuesCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/config/solver/testutil/calculator/AbstractTestdataDifferentValuesCalculator.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataSolution; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + public class AbstractTestdataDifferentValuesCalculator implements EasyScoreCalculator { private boolean isCorrupted; @@ -19,7 +21,7 @@ public class AbstractTestdataDifferentValuesCalculator implements EasyScoreCalcu } @Override - public SimpleScore calculateScore(TestdataSolution solution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataSolution solution) { int score = 0; Set alreadyUsedValues = new HashSet<>(); diff --git a/core/src/test/java/ai/timefold/solver/core/config/solver/testutil/corruptedundoshadow/CorruptedUndoShadowEasyScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/config/solver/testutil/corruptedundoshadow/CorruptedUndoShadowEasyScoreCalculator.java index 294e678fb3..8b79e9fcbf 100644 --- a/core/src/test/java/ai/timefold/solver/core/config/solver/testutil/corruptedundoshadow/CorruptedUndoShadowEasyScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/config/solver/testutil/corruptedundoshadow/CorruptedUndoShadowEasyScoreCalculator.java @@ -5,9 +5,11 @@ import ai.timefold.solver.core.api.score.buildin.simple.SimpleScore; import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; +import org.jspecify.annotations.NonNull; + public class CorruptedUndoShadowEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(CorruptedUndoShadowSolution corruptedUndoShadowSolution) { + public @NonNull SimpleScore calculateScore(@NonNull CorruptedUndoShadowSolution corruptedUndoShadowSolution) { int score = 0; for (CorruptedUndoShadowEntity entity : corruptedUndoShadowSolution.entityList) { if (Objects.equals(entity.value, entity.valueClone)) { diff --git a/core/src/test/java/ai/timefold/solver/core/config/solver/testutil/corruptedundoshadow/CorruptedUndoShadowVariableListener.java b/core/src/test/java/ai/timefold/solver/core/config/solver/testutil/corruptedundoshadow/CorruptedUndoShadowVariableListener.java index 7a9925322a..e93e952c94 100644 --- a/core/src/test/java/ai/timefold/solver/core/config/solver/testutil/corruptedundoshadow/CorruptedUndoShadowVariableListener.java +++ b/core/src/test/java/ai/timefold/solver/core/config/solver/testutil/corruptedundoshadow/CorruptedUndoShadowVariableListener.java @@ -5,41 +5,43 @@ import ai.timefold.solver.core.api.domain.variable.VariableListener; import ai.timefold.solver.core.api.score.director.ScoreDirector; +import org.jspecify.annotations.NonNull; + public class CorruptedUndoShadowVariableListener implements VariableListener { @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, - CorruptedUndoShadowEntity corruptedUndoShadowEntity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull CorruptedUndoShadowEntity corruptedUndoShadowEntity) { } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - CorruptedUndoShadowEntity corruptedUndoShadowEntity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull CorruptedUndoShadowEntity corruptedUndoShadowEntity) { update(scoreDirector, corruptedUndoShadowEntity); } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, - CorruptedUndoShadowEntity corruptedUndoShadowEntity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull CorruptedUndoShadowEntity corruptedUndoShadowEntity) { } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, - CorruptedUndoShadowEntity corruptedUndoShadowEntity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull CorruptedUndoShadowEntity corruptedUndoShadowEntity) { } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, - CorruptedUndoShadowEntity corruptedUndoShadowEntity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull CorruptedUndoShadowEntity corruptedUndoShadowEntity) { } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - CorruptedUndoShadowEntity corruptedUndoShadowEntity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull CorruptedUndoShadowEntity corruptedUndoShadowEntity) { update(scoreDirector, corruptedUndoShadowEntity); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/exhaustivesearch/BlackBoxExhaustiveSearchPhaseTest.java b/core/src/test/java/ai/timefold/solver/core/impl/exhaustivesearch/BlackBoxExhaustiveSearchPhaseTest.java index 6274fa8f65..f3fb6524bd 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/exhaustivesearch/BlackBoxExhaustiveSearchPhaseTest.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/exhaustivesearch/BlackBoxExhaustiveSearchPhaseTest.java @@ -39,6 +39,7 @@ import ai.timefold.solver.core.impl.testdata.domain.comparable.TestdataDifficultyComparingSolution; import ai.timefold.solver.core.impl.testdata.util.PlannerTestUtils; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -436,7 +437,7 @@ public static class TestdataComparableDifferentValuesCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataDifficultyComparingSolution solution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataDifficultyComparingSolution solution) { int score = 0; Set alreadyUsedValues = new HashSet<>(); diff --git a/core/src/test/java/ai/timefold/solver/core/impl/heuristic/selector/move/generic/list/ListRuinRecreateMoveSelectorTest.java b/core/src/test/java/ai/timefold/solver/core/impl/heuristic/selector/move/generic/list/ListRuinRecreateMoveSelectorTest.java index 1d27203cf0..1b0e646d45 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/heuristic/selector/move/generic/list/ListRuinRecreateMoveSelectorTest.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/heuristic/selector/move/generic/list/ListRuinRecreateMoveSelectorTest.java @@ -31,6 +31,7 @@ import ai.timefold.solver.core.impl.testdata.domain.list.allows_unassigned.TestdataAllowsUnassignedValuesListValue; import ai.timefold.solver.core.impl.testutil.TestMeterRegistry; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ExecutionMode; @@ -43,7 +44,7 @@ class ListRuinRecreateMoveSelectorTest { public static final class TestdataListConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { constraintFactory.forEach(TestdataListValue.class) .penalize(SimpleScore.ONE, value -> Math.abs( @@ -108,7 +109,7 @@ public static final class TestdataAllowsUnassignedValuesListMixedConstraintProvi implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { constraintFactory.forEach(TestdataAllowsUnassignedValuesListEntity.class) .penalize(SimpleScore.ONE, entity -> entity.getValueList().size() * entity.getValueList().size()) @@ -156,4 +157,4 @@ void testRuiningAllowsUnassignedValues() { assertDoesNotThrow(() -> solver.solve(problem)); } -} \ No newline at end of file +} diff --git a/core/src/test/java/ai/timefold/solver/core/impl/score/DummySimpleScoreEasyScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/score/DummySimpleScoreEasyScoreCalculator.java index 108fbf22ca..73af843f44 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/score/DummySimpleScoreEasyScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/score/DummySimpleScoreEasyScoreCalculator.java @@ -3,10 +3,12 @@ import ai.timefold.solver.core.api.score.buildin.simple.SimpleScore; import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; +import org.jspecify.annotations.NonNull; + public class DummySimpleScoreEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(Solution_ solution_) { + public @NonNull SimpleScore calculateScore(@NonNull Solution_ solution_) { return SimpleScore.of(0); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/score/director/ScoreDirectorFactoryFactoryTest.java b/core/src/test/java/ai/timefold/solver/core/impl/score/director/ScoreDirectorFactoryFactoryTest.java index 9b266f8d11..761a060cc5 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/score/director/ScoreDirectorFactoryFactoryTest.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/score/director/ScoreDirectorFactoryFactoryTest.java @@ -19,6 +19,7 @@ import ai.timefold.solver.core.impl.score.director.stream.BavetConstraintStreamScoreDirectorFactory; import ai.timefold.solver.core.impl.testdata.domain.TestdataSolution; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Test; class ScoreDirectorFactoryFactoryTest { @@ -122,7 +123,7 @@ public void setIntProperty(int intProperty) { } @Override - public SimpleScore calculateScore(TestdataSolution testdataSolution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataSolution testdataSolution) { return SimpleScore.ZERO; } } @@ -150,42 +151,42 @@ public void setIntProperty(int intProperty) { } @Override - public void resetWorkingSolution(TestdataSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataSolution workingSolution) { } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { return SimpleScore.ZERO; } } public static class TestdataConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[0]; } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/score/director/easy/EasyScoreDirectorSemanticsTest.java b/core/src/test/java/ai/timefold/solver/core/impl/score/director/easy/EasyScoreDirectorSemanticsTest.java index c7157b2acb..658e42c85a 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/score/director/easy/EasyScoreDirectorSemanticsTest.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/score/director/easy/EasyScoreDirectorSemanticsTest.java @@ -22,6 +22,7 @@ import ai.timefold.solver.core.impl.testdata.domain.list.pinned.index.TestdataPinnedWithIndexListEasyScoreCalculator; import ai.timefold.solver.core.impl.testdata.domain.list.pinned.index.TestdataPinnedWithIndexListSolution; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Test; final class EasyScoreDirectorSemanticsTest extends AbstractScoreDirectorSemanticsTest { @@ -112,7 +113,7 @@ public void setIntProperty(int intProperty) { } @Override - public SimpleScore calculateScore(TestdataSolution testdataSolution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataSolution testdataSolution) { return SimpleScore.ZERO; } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/AbstractFactChangePropagationTest.java b/core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/AbstractFactChangePropagationTest.java index d2f072e57d..0ef9a1c7e1 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/AbstractFactChangePropagationTest.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/AbstractFactChangePropagationTest.java @@ -18,6 +18,7 @@ import ai.timefold.solver.core.impl.testdata.domain.chained.shadow.TestdataShadowingChainedEntity; import ai.timefold.solver.core.impl.testdata.domain.chained.shadow.TestdataShadowingChainedSolution; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Test; public abstract class AbstractFactChangePropagationTest { @@ -63,7 +64,7 @@ private Solver buildSolver(ConstraintStreamImp public static class ChainedEntityConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { anchorCannotBeNull(constraintFactory) }; diff --git a/core/src/test/java/ai/timefold/solver/core/impl/solver/DefaultSolverTest.java b/core/src/test/java/ai/timefold/solver/core/impl/solver/DefaultSolverTest.java index 49bdc535a6..8f83a4fdcc 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/solver/DefaultSolverTest.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/solver/DefaultSolverTest.java @@ -91,6 +91,8 @@ import org.assertj.core.api.Assertions; import org.assertj.core.api.SoftAssertions; import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; @@ -487,7 +489,7 @@ public static class BestScoreMetricEasyScoreCalculator implements EasyScoreCalculator { @Override - public HardSoftScore calculateScore(TestdataHardSoftScoreSolution testdataSolution) { + public @NonNull HardSoftScore calculateScore(@NonNull TestdataHardSoftScoreSolution testdataSolution) { var count = testdataSolution.getEntityList() .stream() .filter(e -> e.getValue() != null) @@ -700,7 +702,7 @@ public void stepEnded(AbstractStepScope stepScope public static class ErrorThrowingEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataSolution testdataSolution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataSolution testdataSolution) { throw new IllegalStateException("Thrown exception in constraint provider"); } } @@ -1249,7 +1251,7 @@ public static final class MinimizeUnusedEntitiesEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(Object solution) { + public @NonNull SimpleScore calculateScore(@NonNull Object solution) { return new MaximizeUnusedEntitiesEasyScoreCalculator().calculateScore(solution).negate(); } } @@ -1258,7 +1260,7 @@ public static final class MinimizeUnassignedEntitiesEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataAllowsUnassignedValuesListSolution solution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataAllowsUnassignedValuesListSolution solution) { var i = 0; for (var entity : solution.getEntityList()) { i += entity.getValueList().size(); @@ -1271,7 +1273,7 @@ public static final class MaximizeUnusedEntitiesEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(Object solution) { + public @NonNull SimpleScore calculateScore(@NonNull Object solution) { if (solution instanceof TestdataPinnedListSolution testdataPinnedListSolution) { var unusedEntities = 0; for (var entity : testdataPinnedListSolution.getEntityList()) { @@ -1305,7 +1307,7 @@ public SimpleScore calculateScore(Object solution) { public static class CorruptedEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataSolution testdataSolution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataSolution testdataSolution) { var random = (int) (Math.random() * 1000); return SimpleScore.of(random); } @@ -1315,58 +1317,58 @@ public static class CorruptedIncrementalScoreCalculator implements ConstraintMatchAwareIncrementalScoreCalculator { @Override - public void resetWorkingSolution(TestdataSolution workingSolution, boolean constraintMatchEnabled) { + public void resetWorkingSolution(@NonNull TestdataSolution workingSolution, boolean constraintMatchEnabled) { } @Override - public Collection> getConstraintMatchTotals() { + public @NonNull Collection> getConstraintMatchTotals() { return Collections.singletonList(new DefaultConstraintMatchTotal<>(ConstraintRef.of("a", "b"), SimpleScore.of(1))); } @Override - public Map> getIndictmentMap() { + public @Nullable Map> getIndictmentMap() { return Collections.singletonMap(new TestdataEntity("e1"), new DefaultIndictment<>(new TestdataEntity("e1"), SimpleScore.ONE)); } @Override - public void resetWorkingSolution(TestdataSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataSolution workingSolution) { } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { var random = (int) (Math.random() * 1000); return SimpleScore.of(random); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/TestConstraintFactory.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/TestConstraintFactory.java index c3c053a69d..6cc8302225 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/TestConstraintFactory.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/TestConstraintFactory.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; import ai.timefold.solver.core.impl.score.stream.common.InnerConstraintFactory; +import org.jspecify.annotations.NonNull; + public final class TestConstraintFactory> extends InnerConstraintFactory> { @@ -22,27 +24,27 @@ public SolutionDescriptor getSolutionDescriptor() { } @Override - public String getDefaultConstraintPackage() { + public @NonNull String getDefaultConstraintPackage() { return "constraintPackage"; } @Override - public UniConstraintStream forEach(Class sourceClass) { + public @NonNull UniConstraintStream forEach(@NonNull Class sourceClass) { throw new UnsupportedOperationException(); } @Override - public UniConstraintStream forEachIncludingUnassigned(Class sourceClass) { + public @NonNull UniConstraintStream forEachIncludingUnassigned(@NonNull Class sourceClass) { throw new UnsupportedOperationException(); } @Override - public UniConstraintStream from(Class fromClass) { + public @NonNull UniConstraintStream from(@NonNull Class fromClass) { throw new UnsupportedOperationException(); } @Override - public UniConstraintStream fromUnfiltered(Class fromClass) { + public @NonNull UniConstraintStream fromUnfiltered(@NonNull Class fromClass) { throw new UnsupportedOperationException(); } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/DummyVariableListener.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/DummyVariableListener.java index b8f6acace9..0be777a1bf 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/DummyVariableListener.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/DummyVariableListener.java @@ -3,35 +3,37 @@ import ai.timefold.solver.core.api.domain.variable.VariableListener; import ai.timefold.solver.core.api.score.director.ScoreDirector; +import org.jspecify.annotations.NonNull; + public abstract class DummyVariableListener implements VariableListener { @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Entity_ entity_) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity_) { // Nothing to do. } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Entity_ entity_) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity_) { // Nothing to do. } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, Entity_ entity_) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity_) { // Nothing to do. } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, Entity_ entity_) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity_) { // Nothing to do. } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Entity_ entity_) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity_) { // Nothing to do. } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Entity_ entity_) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Entity_ entity_) { // Nothing to do. } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/TestdataConstraintProvider.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/TestdataConstraintProvider.java index 134cd78275..21b9829181 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/TestdataConstraintProvider.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/TestdataConstraintProvider.java @@ -5,10 +5,12 @@ import ai.timefold.solver.core.api.score.stream.ConstraintFactory; import ai.timefold.solver.core.api.score.stream.ConstraintProvider; +import org.jspecify.annotations.NonNull; + public final class TestdataConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { alwaysPenalizingConstraint(constraintFactory) }; } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/TestdataEasyScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/TestdataEasyScoreCalculator.java index 399c6c4dbd..1ba5baf8f4 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/TestdataEasyScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/TestdataEasyScoreCalculator.java @@ -5,9 +5,11 @@ import ai.timefold.solver.core.api.score.buildin.simple.SimpleScore; import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; +import org.jspecify.annotations.NonNull; + public class TestdataEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataSolution solution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataSolution solution) { int score = 0; for (TestdataEntity left : solution.getEntityList()) { TestdataValue value = left.getValue(); diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/TestdataIncrementalScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/TestdataIncrementalScoreCalculator.java index 6781d685d3..38cd9390cb 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/TestdataIncrementalScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/TestdataIncrementalScoreCalculator.java @@ -17,6 +17,9 @@ import ai.timefold.solver.core.impl.score.constraint.DefaultConstraintMatchTotal; import ai.timefold.solver.core.impl.score.constraint.DefaultIndictment; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + public class TestdataIncrementalScoreCalculator implements ConstraintMatchAwareIncrementalScoreCalculator { @@ -25,7 +28,7 @@ public class TestdataIncrementalScoreCalculator private Map> indictmentMap; @Override - public void resetWorkingSolution(TestdataSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataSolution workingSolution) { score = 0; constraintMatchTotal = new DefaultConstraintMatchTotal<>( ConstraintRef.of("ai.timefold.solver.core.impl.testdata.domain", "testConstraint"), SimpleScore.ONE); @@ -51,52 +54,52 @@ public void resetWorkingSolution(TestdataSolution workingSolution) { } @Override - public void resetWorkingSolution(TestdataSolution workingSolution, boolean constraintMatchEnabled) { + public void resetWorkingSolution(@NonNull TestdataSolution workingSolution, boolean constraintMatchEnabled) { resetWorkingSolution(workingSolution); } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { return SimpleScore.of(score); } @Override - public Collection> getConstraintMatchTotals() { + public @NonNull Collection> getConstraintMatchTotals() { return Collections.singleton(constraintMatchTotal); } @Override - public Map> getIndictmentMap() { + public @Nullable Map> getIndictmentMap() { return indictmentMap; } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/allows_unassigned/TestdataAllowsUnassignedEasyScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/allows_unassigned/TestdataAllowsUnassignedEasyScoreCalculator.java index 5382598345..5d1a5277a9 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/allows_unassigned/TestdataAllowsUnassignedEasyScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/allows_unassigned/TestdataAllowsUnassignedEasyScoreCalculator.java @@ -6,10 +6,12 @@ import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + public class TestdataAllowsUnassignedEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataAllowsUnassignedSolution solution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataAllowsUnassignedSolution solution) { int score = 0; for (TestdataAllowsUnassignedEntity left : solution.getEntityList()) { TestdataValue value = left.getValue(); diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/allows_unassigned/TestdataAllowsUnassignedIncrementalScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/allows_unassigned/TestdataAllowsUnassignedIncrementalScoreCalculator.java index f13d6cf883..9f41b108b3 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/allows_unassigned/TestdataAllowsUnassignedIncrementalScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/allows_unassigned/TestdataAllowsUnassignedIncrementalScoreCalculator.java @@ -17,6 +17,9 @@ import ai.timefold.solver.core.impl.score.constraint.DefaultIndictment; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + public class TestdataAllowsUnassignedIncrementalScoreCalculator implements ConstraintMatchAwareIncrementalScoreCalculator { @@ -24,48 +27,49 @@ public class TestdataAllowsUnassignedIncrementalScoreCalculator private Map> indictmentMap; @Override - public void resetWorkingSolution(TestdataAllowsUnassignedSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataAllowsUnassignedSolution workingSolution) { resetWorkingSolution(workingSolution, true); } @Override - public void resetWorkingSolution(TestdataAllowsUnassignedSolution workingSolution, boolean constraintMatchEnabled) { + public void resetWorkingSolution(@NonNull TestdataAllowsUnassignedSolution workingSolution, + boolean constraintMatchEnabled) { this.workingSolution = workingSolution; this.indictmentMap = null; } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { return update().getScore(); } @@ -92,12 +96,12 @@ private DefaultConstraintMatchTotal update() { } @Override - public Collection> getConstraintMatchTotals() { + public @NonNull Collection> getConstraintMatchTotals() { return Collections.singleton(update()); } @Override - public Map> getIndictmentMap() { + public @Nullable Map> getIndictmentMap() { update(); return indictmentMap; } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/chained/shadow/TestdataShadowingChainedIncrementalScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/chained/shadow/TestdataShadowingChainedIncrementalScoreCalculator.java index 224a3a161f..ab12694458 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/chained/shadow/TestdataShadowingChainedIncrementalScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/chained/shadow/TestdataShadowingChainedIncrementalScoreCalculator.java @@ -11,54 +11,58 @@ import ai.timefold.solver.core.api.score.constraint.Indictment; import ai.timefold.solver.core.impl.score.constraint.DefaultConstraintMatchTotal; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + public class TestdataShadowingChainedIncrementalScoreCalculator implements ConstraintMatchAwareIncrementalScoreCalculator { private TestdataShadowingChainedSolution workingSolution; @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { var constraintMatchTotal = update(workingSolution); return constraintMatchTotal.getScore(); } @Override - public void resetWorkingSolution(TestdataShadowingChainedSolution workingSolution, boolean constraintMatchEnabled) { + public void resetWorkingSolution(@NonNull TestdataShadowingChainedSolution workingSolution, + boolean constraintMatchEnabled) { this.workingSolution = workingSolution; } @Override - public void resetWorkingSolution(TestdataShadowingChainedSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataShadowingChainedSolution workingSolution) { resetWorkingSolution(workingSolution, true); } @@ -81,13 +85,13 @@ private int countChainLength(TestdataShadowingChainedObject object) { } @Override - public Collection> getConstraintMatchTotals() { + public @NonNull Collection> getConstraintMatchTotals() { var constraintMatchTotal = update(workingSolution); return Collections.singleton(constraintMatchTotal); } @Override - public Map> getIndictmentMap() { + public @Nullable Map> getIndictmentMap() { throw new UnsupportedOperationException(); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataCorrectlyClonedSolution.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataCorrectlyClonedSolution.java index 8da94eaa08..898a2b6a78 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataCorrectlyClonedSolution.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataCorrectlyClonedSolution.java @@ -13,6 +13,8 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataEntity; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + @PlanningSolution(solutionCloner = TestdataCorrectlyClonedSolution.class) public class TestdataCorrectlyClonedSolution implements SolutionCloner { @@ -30,7 +32,7 @@ public List valueRange() { } @Override - public TestdataCorrectlyClonedSolution cloneSolution(TestdataCorrectlyClonedSolution original) { + public @NonNull TestdataCorrectlyClonedSolution cloneSolution(@NonNull TestdataCorrectlyClonedSolution original) { TestdataCorrectlyClonedSolution clone = new TestdataCorrectlyClonedSolution(); clone.clonedByCustomCloner = true; // score is immutable so no need to create a new instance diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataEntitiesNotClonedSolution.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataEntitiesNotClonedSolution.java index 3ef288f32e..eb99ec1266 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataEntitiesNotClonedSolution.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataEntitiesNotClonedSolution.java @@ -13,6 +13,8 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataEntity; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + @PlanningSolution(solutionCloner = TestdataEntitiesNotClonedSolution.class) public class TestdataEntitiesNotClonedSolution implements SolutionCloner { @@ -28,7 +30,7 @@ public List valueRange() { } @Override - public TestdataEntitiesNotClonedSolution cloneSolution(TestdataEntitiesNotClonedSolution original) { + public @NonNull TestdataEntitiesNotClonedSolution cloneSolution(@NonNull TestdataEntitiesNotClonedSolution original) { TestdataEntitiesNotClonedSolution clone = new TestdataEntitiesNotClonedSolution(); clone.entity = original.entity; clone.score = original.score; diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataScoreNotClonedSolution.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataScoreNotClonedSolution.java index a12210d119..1e7a93e127 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataScoreNotClonedSolution.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataScoreNotClonedSolution.java @@ -13,6 +13,8 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataEntity; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + @PlanningSolution(solutionCloner = TestdataScoreNotClonedSolution.class) public class TestdataScoreNotClonedSolution implements SolutionCloner { @@ -28,7 +30,7 @@ public List valueRange() { } @Override - public TestdataScoreNotClonedSolution cloneSolution(TestdataScoreNotClonedSolution original) { + public @NonNull TestdataScoreNotClonedSolution cloneSolution(@NonNull TestdataScoreNotClonedSolution original) { TestdataScoreNotClonedSolution clone = new TestdataScoreNotClonedSolution(); clone.entity.setValue(original.entity.getValue()); return clone; diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataScoreNotEqualSolution.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataScoreNotEqualSolution.java index f8030f60b4..fbf97a30a2 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataScoreNotEqualSolution.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/clone/customcloner/TestdataScoreNotEqualSolution.java @@ -13,6 +13,8 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataEntity; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + @PlanningSolution(solutionCloner = TestdataScoreNotEqualSolution.class) public class TestdataScoreNotEqualSolution implements SolutionCloner { @@ -28,7 +30,7 @@ public List valueRange() { } @Override - public TestdataScoreNotEqualSolution cloneSolution(TestdataScoreNotEqualSolution original) { + public @NonNull TestdataScoreNotEqualSolution cloneSolution(@NonNull TestdataScoreNotEqualSolution original) { TestdataScoreNotEqualSolution clone = new TestdataScoreNotEqualSolution(); clone.entity.setValue(original.entity.getValue()); if (original.score != null) { diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintconfiguration/TestdataConstraintWeighIncrementalScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintconfiguration/TestdataConstraintWeighIncrementalScoreCalculator.java index 1f3347e0b7..f160a8a7d0 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintconfiguration/TestdataConstraintWeighIncrementalScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintconfiguration/TestdataConstraintWeighIncrementalScoreCalculator.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.api.score.calculator.IncrementalScoreCalculator; import ai.timefold.solver.core.impl.testdata.domain.TestdataEntity; +import org.jspecify.annotations.NonNull; + @Deprecated(forRemoval = true, since = "1.13.0") public final class TestdataConstraintWeighIncrementalScoreCalculator implements IncrementalScoreCalculator { @@ -15,43 +17,43 @@ public final class TestdataConstraintWeighIncrementalScoreCalculator private List entityList; @Override - public void resetWorkingSolution(TestdataConstraintConfigurationSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataConstraintConfigurationSolution workingSolution) { this.workingSolution = workingSolution; this.entityList = new ArrayList<>(workingSolution.getEntityList()); } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { // No need to do anything. } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { entityList.add((TestdataEntity) entity); } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { throw new UnsupportedOperationException(); // Will not be called. } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { throw new UnsupportedOperationException(); // Will not be called. } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { // No need to do anything. } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { entityList.remove((TestdataEntity) entity); } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { SimpleScore constraintWeight = workingSolution.getConstraintConfiguration().getFirstWeight(); return constraintWeight.multiply(entityList.size()); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintconfiguration/TestdataConstraintWeightConstraintProvider.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintconfiguration/TestdataConstraintWeightConstraintProvider.java index 6ce2b7f680..666855e254 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintconfiguration/TestdataConstraintWeightConstraintProvider.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintconfiguration/TestdataConstraintWeightConstraintProvider.java @@ -5,10 +5,12 @@ import ai.timefold.solver.core.api.score.stream.ConstraintProvider; import ai.timefold.solver.core.impl.testdata.domain.TestdataEntity; +import org.jspecify.annotations.NonNull; + @Deprecated(forRemoval = true, since = "1.13.0") public final class TestdataConstraintWeightConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { onlyConstraint(constraintFactory) }; diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintconfiguration/TestdataConstraintWeightEasyScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintconfiguration/TestdataConstraintWeightEasyScoreCalculator.java index dc32a2cb32..96bc6ae629 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintconfiguration/TestdataConstraintWeightEasyScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintconfiguration/TestdataConstraintWeightEasyScoreCalculator.java @@ -3,12 +3,14 @@ import ai.timefold.solver.core.api.score.buildin.simple.SimpleScore; import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; +import org.jspecify.annotations.NonNull; + @Deprecated(forRemoval = true, since = "1.13.0") public final class TestdataConstraintWeightEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataConstraintConfigurationSolution solution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataConstraintConfigurationSolution solution) { SimpleScore constraintWeight = solution.getConstraintConfiguration().getFirstWeight(); return constraintWeight.multiply(solution.getEntityList().size()); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintweightoverrides/TestdataConstraintWeightOverridesConstraintProvider.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintweightoverrides/TestdataConstraintWeightOverridesConstraintProvider.java index 9e82bdb8c0..bffe985841 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintweightoverrides/TestdataConstraintWeightOverridesConstraintProvider.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/constraintweightoverrides/TestdataConstraintWeightOverridesConstraintProvider.java @@ -6,9 +6,11 @@ import ai.timefold.solver.core.api.score.stream.ConstraintProvider; import ai.timefold.solver.core.impl.testdata.domain.TestdataEntity; +import org.jspecify.annotations.NonNull; + public final class TestdataConstraintWeightOverridesConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { firstConstraint(constraintFactory), secondConstraint(constraintFactory) diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/extendedshadow/TestdataExtendedShadowVariableListener.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/extendedshadow/TestdataExtendedShadowVariableListener.java index 8fc0b26c1a..1d6d8573ed 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/extendedshadow/TestdataExtendedShadowVariableListener.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/extendedshadow/TestdataExtendedShadowVariableListener.java @@ -3,36 +3,38 @@ import ai.timefold.solver.core.api.domain.variable.VariableListener; import ai.timefold.solver.core.api.score.director.ScoreDirector; +import org.jspecify.annotations.NonNull; + public class TestdataExtendedShadowVariableListener implements VariableListener { @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, - TestdataExtendedShadowEntity entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowEntity entity) { } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataExtendedShadowEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowEntity entity) { } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, - TestdataExtendedShadowEntity entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowEntity entity) { } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, - TestdataExtendedShadowEntity entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowEntity entity) { } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, - TestdataExtendedShadowEntity entity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowEntity entity) { } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataExtendedShadowEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowEntity entity) { } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/interface_domain/TestdataInterfaceConstraintProvider.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/interface_domain/TestdataInterfaceConstraintProvider.java index b086ed167b..d33c35ec05 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/interface_domain/TestdataInterfaceConstraintProvider.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/interface_domain/TestdataInterfaceConstraintProvider.java @@ -5,10 +5,12 @@ import ai.timefold.solver.core.api.score.stream.ConstraintFactory; import ai.timefold.solver.core.api.score.stream.ConstraintProvider; +import org.jspecify.annotations.NonNull; + public class TestdataInterfaceConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { alwaysPenalizingConstraint(constraintFactory) }; } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/TestdataAllowsUnassignedValuesListConstraintProvider.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/TestdataAllowsUnassignedValuesListConstraintProvider.java index 513efb2c6e..7b1f0aaf77 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/TestdataAllowsUnassignedValuesListConstraintProvider.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/TestdataAllowsUnassignedValuesListConstraintProvider.java @@ -5,9 +5,11 @@ import ai.timefold.solver.core.api.score.stream.ConstraintFactory; import ai.timefold.solver.core.api.score.stream.ConstraintProvider; +import org.jspecify.annotations.NonNull; + public final class TestdataAllowsUnassignedValuesListConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { entityConstraint(constraintFactory), valueConstraint(constraintFactory) diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/TestdataAllowsUnassignedValuesListEasyScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/TestdataAllowsUnassignedValuesListEasyScoreCalculator.java index 51413f0e28..cfe48df570 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/TestdataAllowsUnassignedValuesListEasyScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/TestdataAllowsUnassignedValuesListEasyScoreCalculator.java @@ -3,11 +3,13 @@ import ai.timefold.solver.core.api.score.buildin.simple.SimpleScore; import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; +import org.jspecify.annotations.NonNull; + public final class TestdataAllowsUnassignedValuesListEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataAllowsUnassignedValuesListSolution solution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataAllowsUnassignedValuesListSolution solution) { int i = 0; for (TestdataAllowsUnassignedValuesListEntity entity : solution.getEntityList()) { i += entity.getValueList().size(); diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/TestdataAllowsUnassignedValuesListIncrementalScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/TestdataAllowsUnassignedValuesListIncrementalScoreCalculator.java index 823b3fe43a..a80ead1512 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/TestdataAllowsUnassignedValuesListIncrementalScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/TestdataAllowsUnassignedValuesListIncrementalScoreCalculator.java @@ -6,48 +6,50 @@ import ai.timefold.solver.core.api.score.buildin.simple.SimpleScore; import ai.timefold.solver.core.api.score.calculator.IncrementalScoreCalculator; +import org.jspecify.annotations.NonNull; + public final class TestdataAllowsUnassignedValuesListIncrementalScoreCalculator implements IncrementalScoreCalculator { private List entityList; @Override - public void resetWorkingSolution(TestdataAllowsUnassignedValuesListSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataAllowsUnassignedValuesListSolution workingSolution) { this.entityList = new ArrayList<>(workingSolution.getEntityList()); } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { // No need to do anything. } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { entityList.add((TestdataAllowsUnassignedValuesListEntity) entity); } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { throw new UnsupportedOperationException(); // Will not be called. } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { throw new UnsupportedOperationException(); // Will not be called. } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { // No need to do anything. } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { entityList.remove((TestdataAllowsUnassignedValuesListEntity) entity); } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { int i = 0; for (TestdataAllowsUnassignedValuesListEntity entity : entityList) { i += entity.getValueList().size(); diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/pinned/TestdataPinnedUnassignedValuesListConstraintProvider.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/pinned/TestdataPinnedUnassignedValuesListConstraintProvider.java index bf4d3386fe..ed5464eb1c 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/pinned/TestdataPinnedUnassignedValuesListConstraintProvider.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/allows_unassigned/pinned/TestdataPinnedUnassignedValuesListConstraintProvider.java @@ -5,9 +5,11 @@ import ai.timefold.solver.core.api.score.stream.ConstraintFactory; import ai.timefold.solver.core.api.score.stream.ConstraintProvider; +import org.jspecify.annotations.NonNull; + public final class TestdataPinnedUnassignedValuesListConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { entityConstraint(constraintFactory), valueConstraint(constraintFactory) diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/TestdataPinnedListConstraintProvider.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/TestdataPinnedListConstraintProvider.java index f787325dce..fa7cb96afb 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/TestdataPinnedListConstraintProvider.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/TestdataPinnedListConstraintProvider.java @@ -5,9 +5,11 @@ import ai.timefold.solver.core.api.score.stream.ConstraintFactory; import ai.timefold.solver.core.api.score.stream.ConstraintProvider; +import org.jspecify.annotations.NonNull; + public final class TestdataPinnedListConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { onlyConstraint(constraintFactory) }; diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/TestdataPinnedListEasyScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/TestdataPinnedListEasyScoreCalculator.java index ca495e212d..44e18b16c5 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/TestdataPinnedListEasyScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/TestdataPinnedListEasyScoreCalculator.java @@ -3,11 +3,13 @@ import ai.timefold.solver.core.api.score.buildin.simple.SimpleScore; import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; +import org.jspecify.annotations.NonNull; + public final class TestdataPinnedListEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataPinnedListSolution solution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataPinnedListSolution solution) { return SimpleScore.of(-solution.getEntityList().size()); } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/TestdataPinnedListIncrementalScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/TestdataPinnedListIncrementalScoreCalculator.java index 8ac09be103..6d582479f2 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/TestdataPinnedListIncrementalScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/TestdataPinnedListIncrementalScoreCalculator.java @@ -6,48 +6,50 @@ import ai.timefold.solver.core.api.score.buildin.simple.SimpleScore; import ai.timefold.solver.core.api.score.calculator.IncrementalScoreCalculator; +import org.jspecify.annotations.NonNull; + public final class TestdataPinnedListIncrementalScoreCalculator implements IncrementalScoreCalculator { private List entityList; @Override - public void resetWorkingSolution(TestdataPinnedListSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataPinnedListSolution workingSolution) { this.entityList = new ArrayList<>(workingSolution.getEntityList()); } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { // No need to do anything. } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { entityList.add((TestdataPinnedListEntity) entity); } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { // No need to do anything. } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { // No need to do anything. } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { // No need to do anything. } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { entityList.remove((TestdataPinnedListEntity) entity); } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { return SimpleScore.of(-entityList.size()); } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListCMAIncrementalScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListCMAIncrementalScoreCalculator.java index e98914de25..d8922f0f69 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListCMAIncrementalScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListCMAIncrementalScoreCalculator.java @@ -16,6 +16,9 @@ import ai.timefold.solver.core.impl.score.constraint.DefaultConstraintMatchTotal; import ai.timefold.solver.core.impl.score.constraint.DefaultIndictment; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + public class TestdataPinnedWithIndexListCMAIncrementalScoreCalculator implements ConstraintMatchAwareIncrementalScoreCalculator { @@ -23,48 +26,49 @@ public class TestdataPinnedWithIndexListCMAIncrementalScoreCalculator private Map> indictmentMap; @Override - public void resetWorkingSolution(TestdataPinnedWithIndexListSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataPinnedWithIndexListSolution workingSolution) { resetWorkingSolution(workingSolution, true); } @Override - public void resetWorkingSolution(TestdataPinnedWithIndexListSolution workingSolution, boolean constraintMatchEnabled) { + public void resetWorkingSolution(@NonNull TestdataPinnedWithIndexListSolution workingSolution, + boolean constraintMatchEnabled) { this.workingSolution = workingSolution; this.indictmentMap = null; } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { return update().getScore(); } @@ -94,12 +98,12 @@ private DefaultConstraintMatchTotal update() { } @Override - public Collection> getConstraintMatchTotals() { + public @NonNull Collection> getConstraintMatchTotals() { return Collections.singleton(update()); } @Override - public Map> getIndictmentMap() { + public @Nullable Map> getIndictmentMap() { update(); return indictmentMap; } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListConstraintProvider.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListConstraintProvider.java index 1ce48f20e7..9134e3e5ee 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListConstraintProvider.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListConstraintProvider.java @@ -5,9 +5,11 @@ import ai.timefold.solver.core.api.score.stream.ConstraintFactory; import ai.timefold.solver.core.api.score.stream.ConstraintProvider; +import org.jspecify.annotations.NonNull; + public final class TestdataPinnedWithIndexListConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { onlyConstraint(constraintFactory) }; diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListEasyScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListEasyScoreCalculator.java index bfcce10e18..bcbfafb00d 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListEasyScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListEasyScoreCalculator.java @@ -3,11 +3,13 @@ import ai.timefold.solver.core.api.score.buildin.simple.SimpleScore; import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; +import org.jspecify.annotations.NonNull; + public final class TestdataPinnedWithIndexListEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataPinnedWithIndexListSolution solution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataPinnedWithIndexListSolution solution) { return SimpleScore.of(-solution.getEntityList().size()); } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListIncrementalScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListIncrementalScoreCalculator.java index 1a4bfca018..15cbae653d 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListIncrementalScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/pinned/index/TestdataPinnedWithIndexListIncrementalScoreCalculator.java @@ -6,48 +6,50 @@ import ai.timefold.solver.core.api.score.buildin.simple.SimpleScore; import ai.timefold.solver.core.api.score.calculator.IncrementalScoreCalculator; +import org.jspecify.annotations.NonNull; + public final class TestdataPinnedWithIndexListIncrementalScoreCalculator implements IncrementalScoreCalculator { private List entityList; @Override - public void resetWorkingSolution(TestdataPinnedWithIndexListSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataPinnedWithIndexListSolution workingSolution) { this.entityList = new ArrayList<>(workingSolution.getEntityList()); } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { // No need to do anything. } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { entityList.add((TestdataPinnedWithIndexListEntity) entity); } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { // No need to do anything. } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { // No need to do anything. } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { // No need to do anything. } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { entityList.remove((TestdataPinnedWithIndexListEntity) entity); } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { return SimpleScore.of(-entityList.size()); } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/shadow_history/TestdataListWithShadowHistoryIncrementalScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/shadow_history/TestdataListWithShadowHistoryIncrementalScoreCalculator.java index 8c577bdbab..1702b22979 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/shadow_history/TestdataListWithShadowHistoryIncrementalScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/list/shadow_history/TestdataListWithShadowHistoryIncrementalScoreCalculator.java @@ -11,54 +11,58 @@ import ai.timefold.solver.core.api.score.constraint.Indictment; import ai.timefold.solver.core.impl.score.constraint.DefaultConstraintMatchTotal; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + public class TestdataListWithShadowHistoryIncrementalScoreCalculator implements ConstraintMatchAwareIncrementalScoreCalculator { private TestdataListSolutionWithShadowHistory workingSolution; @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { var constraintMatchTotal = update(workingSolution); return constraintMatchTotal.getScore(); } @Override - public void resetWorkingSolution(TestdataListSolutionWithShadowHistory workingSolution) { + public void resetWorkingSolution(@NonNull TestdataListSolutionWithShadowHistory workingSolution) { resetWorkingSolution(workingSolution, true); } @Override - public void resetWorkingSolution(TestdataListSolutionWithShadowHistory workingSolution, boolean constraintMatchEnabled) { + public void resetWorkingSolution(@NonNull TestdataListSolutionWithShadowHistory workingSolution, + boolean constraintMatchEnabled) { this.workingSolution = workingSolution; } @@ -75,13 +79,13 @@ private DefaultConstraintMatchTotal update(TestdataListSolutionWith } @Override - public Collection> getConstraintMatchTotals() { + public @NonNull Collection> getConstraintMatchTotals() { var constraintMatchTotal = update(workingSolution); return Collections.singleton(constraintMatchTotal); } @Override - public Map> getIndictmentMap() { + public @Nullable Map> getIndictmentMap() { throw new UnsupportedOperationException(); } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/multivar/TestdataMultivarIncrementalScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/multivar/TestdataMultivarIncrementalScoreCalculator.java index 5ae3e97e6e..80b5abe55f 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/multivar/TestdataMultivarIncrementalScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/multivar/TestdataMultivarIncrementalScoreCalculator.java @@ -14,6 +14,9 @@ import ai.timefold.solver.core.impl.score.constraint.DefaultConstraintMatchTotal; import ai.timefold.solver.core.impl.score.constraint.DefaultIndictment; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + public class TestdataMultivarIncrementalScoreCalculator implements ConstraintMatchAwareIncrementalScoreCalculator { @@ -21,48 +24,48 @@ public class TestdataMultivarIncrementalScoreCalculator private Map> indictmentMap; @Override - public void resetWorkingSolution(TestdataMultiVarSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataMultiVarSolution workingSolution) { resetWorkingSolution(workingSolution, true); } @Override - public void resetWorkingSolution(TestdataMultiVarSolution workingSolution, boolean constraintMatchEnabled) { + public void resetWorkingSolution(@NonNull TestdataMultiVarSolution workingSolution, boolean constraintMatchEnabled) { this.workingSolution = workingSolution; this.indictmentMap = null; } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { return update().getScore(); } @@ -83,12 +86,12 @@ private DefaultConstraintMatchTotal update() { } @Override - public Collection> getConstraintMatchTotals() { + public @NonNull Collection> getConstraintMatchTotals() { return Collections.singleton(update()); } @Override - public Map> getIndictmentMap() { + public @Nullable Map> getIndictmentMap() { update(); return indictmentMap; } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/TestdataPinningFilter.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/TestdataPinningFilter.java index 623bb6a29f..a0974229e0 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/TestdataPinningFilter.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/TestdataPinningFilter.java @@ -2,10 +2,12 @@ import ai.timefold.solver.core.api.domain.entity.PinningFilter; +import org.jspecify.annotations.NonNull; + public class TestdataPinningFilter implements PinningFilter { @Override - public boolean accept(TestdataPinnedSolution solution, TestdataPinnedEntity entity) { + public boolean accept(@NonNull TestdataPinnedSolution solution, @NonNull TestdataPinnedEntity entity) { return entity.isLocked(); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/allows_unassigned/TestdataAllowsUnassignedPinningFilter.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/allows_unassigned/TestdataAllowsUnassignedPinningFilter.java index e57ac3fec1..70577c6054 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/allows_unassigned/TestdataAllowsUnassignedPinningFilter.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/allows_unassigned/TestdataAllowsUnassignedPinningFilter.java @@ -2,11 +2,14 @@ import ai.timefold.solver.core.api.domain.entity.PinningFilter; +import org.jspecify.annotations.NonNull; + public class TestdataAllowsUnassignedPinningFilter implements PinningFilter { @Override - public boolean accept(TestdataPinnedAllowsUnassignedSolution solution, TestdataPinnedAllowsUnassignedEntity entity) { + public boolean accept(@NonNull TestdataPinnedAllowsUnassignedSolution solution, + @NonNull TestdataPinnedAllowsUnassignedEntity entity) { return entity.isLocked(); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/chained/TestdataChainedEntityPinningFilter.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/chained/TestdataChainedEntityPinningFilter.java index 61a8d21178..266cfe59ab 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/chained/TestdataChainedEntityPinningFilter.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/chained/TestdataChainedEntityPinningFilter.java @@ -2,11 +2,13 @@ import ai.timefold.solver.core.api.domain.entity.PinningFilter; +import org.jspecify.annotations.NonNull; + public class TestdataChainedEntityPinningFilter implements PinningFilter { @Override - public boolean accept(TestdataPinnedChainedSolution scoreDirector, TestdataPinnedChainedEntity entity) { + public boolean accept(@NonNull TestdataPinnedChainedSolution scoreDirector, @NonNull TestdataPinnedChainedEntity entity) { return entity.isPinned(); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/extended/TestdataExtendedPinningFilter.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/extended/TestdataExtendedPinningFilter.java index dac13e98ef..6b62969c73 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/extended/TestdataExtendedPinningFilter.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/pinned/extended/TestdataExtendedPinningFilter.java @@ -2,11 +2,13 @@ import ai.timefold.solver.core.api.domain.entity.PinningFilter; +import org.jspecify.annotations.NonNull; + public class TestdataExtendedPinningFilter implements PinningFilter { @Override - public boolean accept(TestdataExtendedPinnedSolution solution, TestdataExtendedPinnedEntity entity) { + public boolean accept(@NonNull TestdataExtendedPinnedSolution solution, @NonNull TestdataExtendedPinnedEntity entity) { return entity.isClosed(); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/TestdataShadowedEntity.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/TestdataShadowedEntity.java index bba27f1560..d16f9fb5c9 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/TestdataShadowedEntity.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/TestdataShadowedEntity.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataObject; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + @PlanningEntity public class TestdataShadowedEntity extends TestdataObject { @@ -67,14 +69,14 @@ public static class FirstShadowUpdatingVariableListener extends DummyVariableListener { @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataShadowedEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataShadowedEntity entity) { updateShadow(scoreDirector, entity); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataShadowedEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataShadowedEntity entity) { updateShadow(scoreDirector, entity); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/TestdataShadowedIncrementalScoreCalculator.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/TestdataShadowedIncrementalScoreCalculator.java index 822a9712c5..ba1c98d36e 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/TestdataShadowedIncrementalScoreCalculator.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/TestdataShadowedIncrementalScoreCalculator.java @@ -17,6 +17,9 @@ import ai.timefold.solver.core.impl.score.constraint.DefaultIndictment; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + public class TestdataShadowedIncrementalScoreCalculator implements ConstraintMatchAwareIncrementalScoreCalculator { @@ -24,48 +27,48 @@ public class TestdataShadowedIncrementalScoreCalculator private Map> indictmentMap; @Override - public void resetWorkingSolution(TestdataShadowedSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataShadowedSolution workingSolution) { resetWorkingSolution(workingSolution, true); } @Override - public void resetWorkingSolution(TestdataShadowedSolution workingSolution, boolean constraintMatchEnabled) { + public void resetWorkingSolution(@NonNull TestdataShadowedSolution workingSolution, boolean constraintMatchEnabled) { this.workingSolution = workingSolution; this.indictmentMap = null; } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { return update().getScore(); } @@ -95,12 +98,12 @@ private DefaultConstraintMatchTotal update() { } @Override - public Collection> getConstraintMatchTotals() { + public @NonNull Collection> getConstraintMatchTotals() { return Collections.singleton(update()); } @Override - public Map> getIndictmentMap() { + public @Nullable Map> getIndictmentMap() { update(); return indictmentMap; } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/corrupted/TestdataCorruptedShadowedEntity.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/corrupted/TestdataCorruptedShadowedEntity.java index 2eb590ec1e..5a522d96f1 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/corrupted/TestdataCorruptedShadowedEntity.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/corrupted/TestdataCorruptedShadowedEntity.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataObject; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + @PlanningEntity public class TestdataCorruptedShadowedEntity extends TestdataObject { @@ -62,14 +64,14 @@ public static class CountUpdatingVariableListener extends DummyVariableListener { @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataCorruptedShadowedEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataCorruptedShadowedEntity entity) { updateShadow(entity, scoreDirector); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataCorruptedShadowedEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataCorruptedShadowedEntity entity) { updateShadow(entity, scoreDirector); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/cyclic/invalid/TestdataCyclicReferencedShadowedEntity.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/cyclic/invalid/TestdataCyclicReferencedShadowedEntity.java index 392d7c9608..33e416c120 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/cyclic/invalid/TestdataCyclicReferencedShadowedEntity.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/cyclic/invalid/TestdataCyclicReferencedShadowedEntity.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataObject; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + @PlanningEntity public class TestdataCyclicReferencedShadowedEntity extends TestdataObject { @@ -80,14 +82,14 @@ public static class BarberAndCutsOwnHairUpdatingVariableListener extends DummyVariableListener { @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataCyclicReferencedShadowedEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataCyclicReferencedShadowedEntity entity) { updateShadow(entity, scoreDirector); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataCyclicReferencedShadowedEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataCyclicReferencedShadowedEntity entity) { updateShadow(entity, scoreDirector); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/cyclic/invalid/TestdataCyclicShadowedEntity.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/cyclic/invalid/TestdataCyclicShadowedEntity.java index 7f9b9d34a1..8c59275be0 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/cyclic/invalid/TestdataCyclicShadowedEntity.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/cyclic/invalid/TestdataCyclicShadowedEntity.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataObject; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + @PlanningEntity public class TestdataCyclicShadowedEntity extends TestdataObject { @@ -87,14 +89,14 @@ public static class RockShadowUpdatingVariableListener extends DummyVariableListener { @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataCyclicShadowedEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataCyclicShadowedEntity entity) { updateShadow(entity, scoreDirector); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataCyclicShadowedEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataCyclicShadowedEntity entity) { updateShadow(entity, scoreDirector); } @@ -112,14 +114,14 @@ public static class PaperShadowUpdatingVariableListener extends DummyVariableListener { @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataCyclicShadowedEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataCyclicShadowedEntity entity) { updateShadow(entity, scoreDirector); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataCyclicShadowedEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataCyclicShadowedEntity entity) { updateShadow(entity, scoreDirector); } @@ -137,14 +139,14 @@ public static class ScissorsShadowUpdatingVariableListener extends DummyVariableListener { @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataCyclicShadowedEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataCyclicShadowedEntity entity) { updateShadow(entity, scoreDirector); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataCyclicShadowedEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataCyclicShadowedEntity entity) { updateShadow(entity, scoreDirector); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/extended/TestdataExtendedShadowedChildEntity.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/extended/TestdataExtendedShadowedChildEntity.java index 84a09303e6..322812e9fc 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/extended/TestdataExtendedShadowedChildEntity.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/extended/TestdataExtendedShadowedChildEntity.java @@ -7,6 +7,8 @@ import ai.timefold.solver.core.impl.testdata.domain.DummyVariableListener; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + @PlanningEntity public class TestdataExtendedShadowedChildEntity extends TestdataExtendedShadowedParentEntity { @@ -49,14 +51,14 @@ public static class SecondShadowUpdatingVariableListener extends DummyVariableListener { @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataExtendedShadowedParentEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowedParentEntity entity) { updateShadow(scoreDirector, entity); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataExtendedShadowedParentEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowedParentEntity entity) { updateShadow(scoreDirector, entity); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/extended/TestdataExtendedShadowedParentEntity.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/extended/TestdataExtendedShadowedParentEntity.java index fe33267226..9ba93d9db6 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/extended/TestdataExtendedShadowedParentEntity.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/extended/TestdataExtendedShadowedParentEntity.java @@ -11,6 +11,8 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataObject; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + @PlanningEntity public class TestdataExtendedShadowedParentEntity extends TestdataObject { @@ -79,14 +81,14 @@ public static class FirstShadowUpdatingVariableListener extends DummyVariableListener { @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataExtendedShadowedParentEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowedParentEntity entity) { updateShadow(scoreDirector, entity); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataExtendedShadowedParentEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowedParentEntity entity) { updateShadow(scoreDirector, entity); } @@ -104,38 +106,38 @@ public static class ThirdShadowUpdatingVariableListener implements VariableListener { @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, - TestdataExtendedShadowedChildEntity testdataExtendedShadowedChildEntity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowedChildEntity testdataExtendedShadowedChildEntity) { // Do nothing. } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataExtendedShadowedChildEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowedChildEntity entity) { updateShadow(scoreDirector, entity); } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, - TestdataExtendedShadowedChildEntity testdataExtendedShadowedChildEntity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowedChildEntity testdataExtendedShadowedChildEntity) { // Do nothing. } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataExtendedShadowedChildEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowedChildEntity entity) { updateShadow(scoreDirector, entity); } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, - TestdataExtendedShadowedChildEntity testdataExtendedShadowedChildEntity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowedChildEntity testdataExtendedShadowedChildEntity) { // Do nothing. } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, - TestdataExtendedShadowedChildEntity testdataExtendedShadowedChildEntity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataExtendedShadowedChildEntity testdataExtendedShadowedChildEntity) { // Do nothing. } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/manytomany/TestdataManyToManyShadowedEntity.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/manytomany/TestdataManyToManyShadowedEntity.java index 6dc763e480..bd11bd7b67 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/manytomany/TestdataManyToManyShadowedEntity.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/manytomany/TestdataManyToManyShadowedEntity.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataObject; import ai.timefold.solver.core.impl.testdata.domain.TestdataValue; +import org.jspecify.annotations.NonNull; + @PlanningEntity public class TestdataManyToManyShadowedEntity extends TestdataObject { @@ -85,14 +87,14 @@ public static class ComposedValuesUpdatingVariableListener extends DummyVariableListener { @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataManyToManyShadowedEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataManyToManyShadowedEntity entity) { updateShadow(entity, scoreDirector); } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataManyToManyShadowedEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataManyToManyShadowedEntity entity) { updateShadow(entity, scoreDirector); } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/wrong_listener/TestdataWrongBasicShadowEntity.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/wrong_listener/TestdataWrongBasicShadowEntity.java index 3257ec1d7a..4abc27f1dd 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/wrong_listener/TestdataWrongBasicShadowEntity.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/wrong_listener/TestdataWrongBasicShadowEntity.java @@ -9,6 +9,8 @@ import ai.timefold.solver.core.impl.testdata.domain.TestdataEntity; import ai.timefold.solver.core.impl.testdata.domain.TestdataSolution; +import org.jspecify.annotations.NonNull; + @PlanningEntity public class TestdataWrongBasicShadowEntity { @@ -34,32 +36,36 @@ public void setShadow(String shadow) { public static class MyListVariableListener implements ListVariableListener { @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, TestdataEntity entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull TestdataEntity entity) { } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, TestdataEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull TestdataEntity entity) { } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, TestdataEntity entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataEntity entity) { } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, TestdataEntity entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull TestdataEntity entity) { } @Override - public void afterListVariableElementUnassigned(ScoreDirector scoreDirector, Object o) { + public void afterListVariableElementUnassigned(@NonNull ScoreDirector scoreDirector, + @NonNull Object o) { } @Override - public void beforeListVariableChanged(ScoreDirector scoreDirector, TestdataEntity entity, + public void beforeListVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataEntity entity, int fromIndex, int toIndex) { } @Override - public void afterListVariableChanged(ScoreDirector scoreDirector, TestdataEntity entity, + public void afterListVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataEntity entity, int fromIndex, int toIndex) { } } diff --git a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/wrong_listener/TestdataWrongListShadowEntity.java b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/wrong_listener/TestdataWrongListShadowEntity.java index 6574875d91..4ff3e02134 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/wrong_listener/TestdataWrongListShadowEntity.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/testdata/domain/shadow/wrong_listener/TestdataWrongListShadowEntity.java @@ -10,6 +10,8 @@ import ai.timefold.solver.core.impl.testdata.domain.list.TestdataListSolution; import ai.timefold.solver.core.impl.testdata.domain.list.TestdataListValue; +import org.jspecify.annotations.NonNull; + @PlanningEntity public class TestdataWrongListShadowEntity { @@ -36,27 +38,33 @@ public void setShadow(String shadow) { public static class MyBasicVariableListener implements VariableListener { @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, TestdataListEntity entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataListEntity entity) { } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, TestdataListEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataListEntity entity) { } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, TestdataListEntity entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataListEntity entity) { } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, TestdataListEntity entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataListEntity entity) { } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, TestdataListEntity entity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataListEntity entity) { } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, TestdataListEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataListEntity entity) { } } } diff --git a/persistence/jackson/pom.xml b/persistence/jackson/pom.xml index 66de9fd0dd..6caa8cea86 100644 --- a/persistence/jackson/pom.xml +++ b/persistence/jackson/pom.xml @@ -77,6 +77,12 @@ assertj-core test + + + + org.jspecify + jspecify + diff --git a/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableBreak.java b/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableBreak.java index 2311690de4..32de6418d5 100644 --- a/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableBreak.java +++ b/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableBreak.java @@ -2,6 +2,8 @@ import ai.timefold.solver.core.api.score.stream.common.Break; +import org.jspecify.annotations.NonNull; + import com.fasterxml.jackson.annotation.JsonProperty; record DeserializableBreak>( @@ -22,17 +24,17 @@ public boolean isLast() { } @Override - public Value_ getPreviousSequenceEnd() { + public @NonNull Value_ getPreviousSequenceEnd() { return previousSequenceEnd(); } @Override - public Value_ getNextSequenceStart() { + public @NonNull Value_ getNextSequenceStart() { return nextSequenceStart(); } @Override - public Difference_ getLength() { + public @NonNull Difference_ getLength() { /* * Difference_ is a custom type, hidden deep within the object tree. * Allowing for deserialization of this would have significantly complicated the code, diff --git a/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableLoadBalance.java b/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableLoadBalance.java index 97ad7294cf..0d3fef69bc 100644 --- a/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableLoadBalance.java +++ b/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableLoadBalance.java @@ -5,10 +5,12 @@ import ai.timefold.solver.core.api.score.stream.common.LoadBalance; +import org.jspecify.annotations.NonNull; + record DeserializableLoadBalance(BigDecimal unfairness) implements LoadBalance { @Override - public Map loads() { + public @NonNull Map loads() { throw new UnsupportedOperationException("Deserialization of loads is not supported."); } diff --git a/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableSequence.java b/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableSequence.java index b22160d021..4036b49685 100644 --- a/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableSequence.java +++ b/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableSequence.java @@ -6,6 +6,9 @@ import ai.timefold.solver.core.api.score.stream.common.Break; import ai.timefold.solver.core.api.score.stream.common.Sequence; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + import com.fasterxml.jackson.annotation.JsonProperty; record DeserializableSequence>( @@ -16,12 +19,12 @@ record DeserializableSequence { @Override - public Value_ getFirstItem() { + public @NonNull Value_ getFirstItem() { return items.get(0); } @Override - public Value_ getLastItem() { + public @NonNull Value_ getLastItem() { return items.get(items.size() - 1); } @@ -36,17 +39,17 @@ public boolean isLast() { } @Override - public Break getPreviousBreak() { + public @Nullable Break getPreviousBreak() { return previousBreak(); } @Override - public Break getNextBreak() { + public @Nullable Break getNextBreak() { return nextBreak(); } @Override - public Collection getItems() { + public @NonNull Collection getItems() { return items(); } @@ -56,7 +59,7 @@ public int getCount() { } @Override - public Difference_ getLength() { + public @NonNull Difference_ getLength() { /* * Difference_ is a custom type, hidden deep within the object tree. * Allowing for deserialization of this would have significantly complicated the code, diff --git a/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableSequenceChain.java b/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableSequenceChain.java index def305601d..09530c53c5 100644 --- a/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableSequenceChain.java +++ b/persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/stream/common/DeserializableSequenceChain.java @@ -8,18 +8,21 @@ import ai.timefold.solver.core.api.score.stream.common.Sequence; import ai.timefold.solver.core.api.score.stream.common.SequenceChain; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + record DeserializableSequenceChain>( List> sequences) implements SequenceChain { @Override - public Collection> getConsecutiveSequences() { + public @NonNull Collection> getConsecutiveSequences() { return Collections.unmodifiableCollection(sequences()); } @Override - public Collection> getBreaks() { + public @NonNull Collection> getBreaks() { throw new UnsupportedOperationException(""" Deserialized %s does not carry break information. It can be computed from the sequences.""" @@ -27,17 +30,17 @@ public Collection> getBreaks() { } @Override - public Sequence getFirstSequence() { + public @Nullable Sequence getFirstSequence() { return sequences().get(0); } @Override - public Sequence getLastSequence() { + public @Nullable Sequence getLastSequence() { return sequences().get(sequences().size() - 1); } @Override - public Break getFirstBreak() { + public @Nullable Break getFirstBreak() { throw new UnsupportedOperationException(""" Deserialized %s does not carry break information. It can be computed from the sequences.""" @@ -45,7 +48,7 @@ public Break getFirstBreak() { } @Override - public Break getLastBreak() { + public @Nullable Break getLastBreak() { throw new UnsupportedOperationException(""" Deserialized %s does not carry break information. It can be computed from the sequences.""" diff --git a/python/python-core/pom.xml b/python/python-core/pom.xml index 2eb813ab05..6300f3fbdc 100644 --- a/python/python-core/pom.xml +++ b/python/python-core/pom.xml @@ -82,6 +82,12 @@ mockito-core test + + + + org.jspecify + jspecify + diff --git a/python/python-core/src/main/java/ai/timefold/solver/python/PythonValueRangeFactory.java b/python/python-core/src/main/java/ai/timefold/solver/python/PythonValueRangeFactory.java index 7e9032d63b..980061b4f3 100644 --- a/python/python-core/src/main/java/ai/timefold/solver/python/PythonValueRangeFactory.java +++ b/python/python-core/src/main/java/ai/timefold/solver/python/PythonValueRangeFactory.java @@ -12,6 +12,8 @@ import ai.timefold.solver.core.api.domain.valuerange.CountableValueRange; import ai.timefold.solver.core.api.domain.valuerange.ValueRangeFactory; +import org.jspecify.annotations.NonNull; + @SuppressWarnings("unused") public class PythonValueRangeFactory { private PythonValueRangeFactory() { @@ -48,7 +50,7 @@ public To_ get(long index) { } @Override - public Iterator createOriginalIterator() { + public @NonNull Iterator createOriginalIterator() { return new IteratorMapper<>(sourceValueRange.createOriginalIterator(), valueConvertor); } @@ -63,7 +65,7 @@ public boolean contains(To_ value) { } @Override - public Iterator createRandomIterator(Random random) { + public @NonNull Iterator createRandomIterator(@NonNull Random random) { return new IteratorMapper<>(sourceValueRange.createRandomIterator(random), valueConvertor); } } diff --git a/quarkus-integration/quarkus-benchmark/deployment/src/test/java/ai/timefold/solver/benchmark/quarkus/testdata/normal/constraints/TestdataQuarkusConstraintProvider.java b/quarkus-integration/quarkus-benchmark/deployment/src/test/java/ai/timefold/solver/benchmark/quarkus/testdata/normal/constraints/TestdataQuarkusConstraintProvider.java index 92d6998d30..55fdd1351b 100644 --- a/quarkus-integration/quarkus-benchmark/deployment/src/test/java/ai/timefold/solver/benchmark/quarkus/testdata/normal/constraints/TestdataQuarkusConstraintProvider.java +++ b/quarkus-integration/quarkus-benchmark/deployment/src/test/java/ai/timefold/solver/benchmark/quarkus/testdata/normal/constraints/TestdataQuarkusConstraintProvider.java @@ -7,10 +7,12 @@ import ai.timefold.solver.core.api.score.stream.ConstraintProvider; import ai.timefold.solver.core.api.score.stream.Joiners; +import org.jspecify.annotations.NonNull; + public class TestdataQuarkusConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(TestdataQuarkusEntity.class) .join(TestdataQuarkusEntity.class, Joiners.equal(TestdataQuarkusEntity::getValue)) diff --git a/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/ai/timefold/solver/quarkus/benchmark/it/domain/StringLengthVariableListener.java b/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/ai/timefold/solver/quarkus/benchmark/it/domain/StringLengthVariableListener.java index 2753a77d62..7aeed818c0 100644 --- a/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/ai/timefold/solver/quarkus/benchmark/it/domain/StringLengthVariableListener.java +++ b/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/ai/timefold/solver/quarkus/benchmark/it/domain/StringLengthVariableListener.java @@ -3,30 +3,32 @@ import ai.timefold.solver.core.api.domain.variable.VariableListener; import ai.timefold.solver.core.api.score.director.ScoreDirector; +import org.jspecify.annotations.NonNull; + public class StringLengthVariableListener implements VariableListener { @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, - TestdataListValueShadowEntity entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataListValueShadowEntity entity) { /* Nothing to do */ } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataListValueShadowEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataListValueShadowEntity entity) { /* Nothing to do */ } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, - TestdataListValueShadowEntity entity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataListValueShadowEntity entity) { /* Nothing to do */ } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataListValueShadowEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataListValueShadowEntity entity) { int oldLength = (entity.getLength() != null) ? entity.getLength() : 0; int newLength = entity.getEntity() != null @@ -41,14 +43,14 @@ public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataListValueShadowEntity entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataListValueShadowEntity entity) { /* Nothing to do */ } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, - TestdataListValueShadowEntity entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataListValueShadowEntity entity) { /* Nothing to do */ } diff --git a/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/ai/timefold/solver/quarkus/benchmark/it/solver/TestdataStringLengthConstraintProvider.java b/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/ai/timefold/solver/quarkus/benchmark/it/solver/TestdataStringLengthConstraintProvider.java index 6a06886522..1d88bbf3e3 100644 --- a/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/ai/timefold/solver/quarkus/benchmark/it/solver/TestdataStringLengthConstraintProvider.java +++ b/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/ai/timefold/solver/quarkus/benchmark/it/solver/TestdataStringLengthConstraintProvider.java @@ -7,10 +7,12 @@ import ai.timefold.solver.quarkus.benchmark.it.domain.TestdataListValueShadowEntity; import ai.timefold.solver.quarkus.benchmark.it.domain.TestdataStringLengthShadowEntity; +import org.jspecify.annotations.NonNull; + public class TestdataStringLengthConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEachUniquePair(TestdataStringLengthShadowEntity.class) .filter((a, b) -> a.getValues().stream().anyMatch(v -> b.getValues().contains(v))) diff --git a/quarkus-integration/quarkus-jackson/integration-test/src/main/java/ai/timefold/solver/quarkus/jackson/it/solver/ITestdataPlanningConstraintProvider.java b/quarkus-integration/quarkus-jackson/integration-test/src/main/java/ai/timefold/solver/quarkus/jackson/it/solver/ITestdataPlanningConstraintProvider.java index 3b0607304e..f3e716bd91 100644 --- a/quarkus-integration/quarkus-jackson/integration-test/src/main/java/ai/timefold/solver/quarkus/jackson/it/solver/ITestdataPlanningConstraintProvider.java +++ b/quarkus-integration/quarkus-jackson/integration-test/src/main/java/ai/timefold/solver/quarkus/jackson/it/solver/ITestdataPlanningConstraintProvider.java @@ -7,10 +7,12 @@ import ai.timefold.solver.core.api.score.stream.Joiners; import ai.timefold.solver.quarkus.jackson.it.domain.ITestdataPlanningEntity; +import org.jspecify.annotations.NonNull; + public class ITestdataPlanningConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(ITestdataPlanningEntity.class) .join(ITestdataPlanningEntity.class, Joiners.equal(ITestdataPlanningEntity::getValue)) diff --git a/quarkus-integration/quarkus-jsonb/integration-test/src/main/java/ai/timefold/solver/quarkus/jsonb/it/solver/ITestdataPlanningConstraintProvider.java b/quarkus-integration/quarkus-jsonb/integration-test/src/main/java/ai/timefold/solver/quarkus/jsonb/it/solver/ITestdataPlanningConstraintProvider.java index a59450e061..4115c5f246 100644 --- a/quarkus-integration/quarkus-jsonb/integration-test/src/main/java/ai/timefold/solver/quarkus/jsonb/it/solver/ITestdataPlanningConstraintProvider.java +++ b/quarkus-integration/quarkus-jsonb/integration-test/src/main/java/ai/timefold/solver/quarkus/jsonb/it/solver/ITestdataPlanningConstraintProvider.java @@ -7,10 +7,12 @@ import ai.timefold.solver.core.api.score.stream.Joiners; import ai.timefold.solver.quarkus.jsonb.it.domain.ITestdataPlanningEntity; +import org.jspecify.annotations.NonNull; + public class ITestdataPlanningConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(ITestdataPlanningEntity.class) .join(ITestdataPlanningEntity.class, Joiners.equal(ITestdataPlanningEntity::getValue)) diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/TimefoldProcessorGeneratedGizmoSupplierTest.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/TimefoldProcessorGeneratedGizmoSupplierTest.java index 1cc1c51fe6..64eb6a8e05 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/TimefoldProcessorGeneratedGizmoSupplierTest.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/TimefoldProcessorGeneratedGizmoSupplierTest.java @@ -33,6 +33,7 @@ import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -118,7 +119,7 @@ public List splitWorkingSolution(ScoreDirector { @Override - public SimpleScore calculateScore(TestdataSolution testdataSolution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataSolution testdataSolution) { return null; } } @@ -126,49 +127,49 @@ public SimpleScore calculateScore(TestdataSolution testdataSolution) { public static class DummyIncrementalScoreCalculator implements IncrementalScoreCalculator { @Override - public void resetWorkingSolution(TestdataSolution workingSolution) { + public void resetWorkingSolution(@NonNull TestdataSolution workingSolution) { } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public SimpleScore calculateScore() { + public @NonNull SimpleScore calculateScore() { return null; } } public static class DummyConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[0]; } } diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/chained/constraints/TestdataChainedQuarkusConstraintProvider.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/chained/constraints/TestdataChainedQuarkusConstraintProvider.java index ee6e71692d..2a31f37670 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/chained/constraints/TestdataChainedQuarkusConstraintProvider.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/chained/constraints/TestdataChainedQuarkusConstraintProvider.java @@ -8,10 +8,12 @@ import ai.timefold.solver.quarkus.testdata.chained.domain.TestdataChainedQuarkusAnchor; import ai.timefold.solver.quarkus.testdata.chained.domain.TestdataChainedQuarkusEntity; +import org.jspecify.annotations.NonNull; + public class TestdataChainedQuarkusConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(TestdataChainedQuarkusAnchor.class) .ifNotExists(TestdataChainedQuarkusEntity.class, diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusEasyScoreCalculator.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusEasyScoreCalculator.java index ed60048a31..5b4aba47b8 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusEasyScoreCalculator.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusEasyScoreCalculator.java @@ -4,9 +4,11 @@ import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; import ai.timefold.solver.quarkus.testdata.normal.domain.TestdataQuarkusSolution; +import org.jspecify.annotations.NonNull; + public class DummyTestdataQuarkusEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataQuarkusSolution testdataQuarkusSolution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataQuarkusSolution testdataQuarkusSolution) { return null; } } diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusIncrementalScoreCalculator.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusIncrementalScoreCalculator.java index 1c96ea0e50..5df94cdf9e 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusIncrementalScoreCalculator.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusIncrementalScoreCalculator.java @@ -3,45 +3,47 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.api.score.calculator.IncrementalScoreCalculator; +import org.jspecify.annotations.NonNull; + public class DummyTestdataQuarkusIncrementalScoreCalculator implements IncrementalScoreCalculator { @Override - public void resetWorkingSolution(Object workingSolution) { + public void resetWorkingSolution(@NonNull Object workingSolution) { } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public Score calculateScore() { + public @NonNull Score calculateScore() { return null; } } diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusShadowVariableEasyScoreCalculator.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusShadowVariableEasyScoreCalculator.java index e523c34956..ce608e2313 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusShadowVariableEasyScoreCalculator.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusShadowVariableEasyScoreCalculator.java @@ -4,10 +4,12 @@ import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; import ai.timefold.solver.quarkus.testdata.shadowvariable.domain.TestdataQuarkusShadowVariableSolution; +import org.jspecify.annotations.NonNull; + public class DummyTestdataQuarkusShadowVariableEasyScoreCalculator implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataQuarkusShadowVariableSolution testdataQuarkusSolution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataQuarkusShadowVariableSolution testdataQuarkusSolution) { return null; } } diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusShadowVariableIncrementalScoreCalculator.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusShadowVariableIncrementalScoreCalculator.java index e3dc9afad0..44ad54d906 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusShadowVariableIncrementalScoreCalculator.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/dummy/DummyTestdataQuarkusShadowVariableIncrementalScoreCalculator.java @@ -3,45 +3,47 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.api.score.calculator.IncrementalScoreCalculator; +import org.jspecify.annotations.NonNull; + public class DummyTestdataQuarkusShadowVariableIncrementalScoreCalculator implements IncrementalScoreCalculator { @Override - public void resetWorkingSolution(Object workingSolution) { + public void resetWorkingSolution(@NonNull Object workingSolution) { } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public Score calculateScore() { + public @NonNull Score calculateScore() { return null; } } diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/extended/TestdataExtendedShadowSolutionConstraintProvider.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/extended/TestdataExtendedShadowSolutionConstraintProvider.java index 082c0930e6..2cc18f19a2 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/extended/TestdataExtendedShadowSolutionConstraintProvider.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/extended/TestdataExtendedShadowSolutionConstraintProvider.java @@ -6,9 +6,11 @@ import ai.timefold.solver.core.api.score.stream.ConstraintProvider; import ai.timefold.solver.core.impl.testdata.domain.extendedshadow.TestdataExtendedShadowEntity; +import org.jspecify.annotations.NonNull; + public class TestdataExtendedShadowSolutionConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { constraintFactory.forEach(TestdataExtendedShadowEntity.class) .filter(e -> e.myPlanningVariable.id != e.desiredId) diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/gizmo/DummyConstraintProvider.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/gizmo/DummyConstraintProvider.java index 22ff08fc34..5aa6df5e03 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/gizmo/DummyConstraintProvider.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/gizmo/DummyConstraintProvider.java @@ -4,10 +4,12 @@ import ai.timefold.solver.core.api.score.stream.ConstraintFactory; import ai.timefold.solver.core.api.score.stream.ConstraintProvider; +import org.jspecify.annotations.NonNull; + public class DummyConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[0]; } } diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/gizmo/DummyVariableListener.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/gizmo/DummyVariableListener.java index 6a5cec0993..05e993515e 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/gizmo/DummyVariableListener.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/gizmo/DummyVariableListener.java @@ -3,35 +3,37 @@ import ai.timefold.solver.core.api.domain.variable.VariableListener; import ai.timefold.solver.core.api.score.director.ScoreDirector; +import org.jspecify.annotations.NonNull; + public class DummyVariableListener implements VariableListener { @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object o) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object o) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, Object o) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, Object o) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object o) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object o) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { } } diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/gizmo/PrivateNoArgsConstructorConstraintProvider.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/gizmo/PrivateNoArgsConstructorConstraintProvider.java index 9303a8746c..6b1c446293 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/gizmo/PrivateNoArgsConstructorConstraintProvider.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/gizmo/PrivateNoArgsConstructorConstraintProvider.java @@ -6,13 +6,15 @@ import ai.timefold.solver.core.api.score.stream.ConstraintProvider; import ai.timefold.solver.core.api.score.stream.Joiners; +import org.jspecify.annotations.NonNull; + public class PrivateNoArgsConstructorConstraintProvider implements ConstraintProvider { private PrivateNoArgsConstructorConstraintProvider() { } @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { constraintFactory.forEachUniquePair(PrivateNoArgsConstructorEntity.class, Joiners.equal(p -> p.value)) diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/interfaceentity/constraints/TestdataInterfaceEntityConstraintProvider.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/interfaceentity/constraints/TestdataInterfaceEntityConstraintProvider.java index 642a16c991..1222972436 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/interfaceentity/constraints/TestdataInterfaceEntityConstraintProvider.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/interfaceentity/constraints/TestdataInterfaceEntityConstraintProvider.java @@ -6,10 +6,12 @@ import ai.timefold.solver.core.api.score.stream.ConstraintProvider; import ai.timefold.solver.quarkus.testdata.interfaceentity.domain.TestdataInterfaceEntity; +import org.jspecify.annotations.NonNull; + public class TestdataInterfaceEntityConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { constraintFactory.forEach(TestdataInterfaceEntity.class) .penalize(SimpleScore.ONE, TestdataInterfaceEntity::getValue) diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/invalid/inverserelation/constraints/TestdataInvalidQuarkusConstraintProvider.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/invalid/inverserelation/constraints/TestdataInvalidQuarkusConstraintProvider.java index 95c927c05f..bdb41babf0 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/invalid/inverserelation/constraints/TestdataInvalidQuarkusConstraintProvider.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/invalid/inverserelation/constraints/TestdataInvalidQuarkusConstraintProvider.java @@ -6,10 +6,12 @@ import ai.timefold.solver.core.api.score.stream.ConstraintProvider; import ai.timefold.solver.quarkus.testdata.invalid.inverserelation.domain.TestdataInvalidInverseRelationValue; +import org.jspecify.annotations.NonNull; + public class TestdataInvalidQuarkusConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(TestdataInvalidInverseRelationValue.class) .filter(room -> room.getEntityList().size() > 1) diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/normal/constraints/TestdataQuarkusConstraintProvider.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/normal/constraints/TestdataQuarkusConstraintProvider.java index 2147429e11..08415e7bdb 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/normal/constraints/TestdataQuarkusConstraintProvider.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/normal/constraints/TestdataQuarkusConstraintProvider.java @@ -7,10 +7,12 @@ import ai.timefold.solver.core.api.score.stream.Joiners; import ai.timefold.solver.quarkus.testdata.normal.domain.TestdataQuarkusEntity; +import org.jspecify.annotations.NonNull; + public class TestdataQuarkusConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(TestdataQuarkusEntity.class) .join(TestdataQuarkusEntity.class, Joiners.equal(TestdataQuarkusEntity::getValue)) diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/shadowvariable/constraints/TestdataQuarkusShadowVariableConstraintProvider.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/shadowvariable/constraints/TestdataQuarkusShadowVariableConstraintProvider.java index ecf1ba0791..9828101558 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/shadowvariable/constraints/TestdataQuarkusShadowVariableConstraintProvider.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/shadowvariable/constraints/TestdataQuarkusShadowVariableConstraintProvider.java @@ -7,10 +7,12 @@ import ai.timefold.solver.core.api.score.stream.Joiners; import ai.timefold.solver.quarkus.testdata.shadowvariable.domain.TestdataQuarkusShadowVariableEntity; +import org.jspecify.annotations.NonNull; + public class TestdataQuarkusShadowVariableConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(TestdataQuarkusShadowVariableEntity.class) .join(TestdataQuarkusShadowVariableEntity.class, diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/shadowvariable/domain/TestdataQuarkusShadowVariableListener.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/shadowvariable/domain/TestdataQuarkusShadowVariableListener.java index 82508ffc61..a65a5b6022 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/shadowvariable/domain/TestdataQuarkusShadowVariableListener.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/shadowvariable/domain/TestdataQuarkusShadowVariableListener.java @@ -3,41 +3,43 @@ import ai.timefold.solver.core.api.domain.variable.VariableListener; import ai.timefold.solver.core.api.score.director.ScoreDirector; +import org.jspecify.annotations.NonNull; + public class TestdataQuarkusShadowVariableListener implements VariableListener { @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, - TestdataQuarkusShadowVariableEntity testdataQuarkusShadowVariableEntity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataQuarkusShadowVariableEntity testdataQuarkusShadowVariableEntity) { } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataQuarkusShadowVariableEntity testdataQuarkusShadowVariableEntity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataQuarkusShadowVariableEntity testdataQuarkusShadowVariableEntity) { update(scoreDirector, testdataQuarkusShadowVariableEntity); } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, - TestdataQuarkusShadowVariableEntity testdataQuarkusShadowVariableEntity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataQuarkusShadowVariableEntity testdataQuarkusShadowVariableEntity) { } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, - TestdataQuarkusShadowVariableEntity testdataQuarkusShadowVariableEntity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataQuarkusShadowVariableEntity testdataQuarkusShadowVariableEntity) { } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, - TestdataQuarkusShadowVariableEntity testdataQuarkusShadowVariableEntity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataQuarkusShadowVariableEntity testdataQuarkusShadowVariableEntity) { } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataQuarkusShadowVariableEntity testdataQuarkusShadowVariableEntity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataQuarkusShadowVariableEntity testdataQuarkusShadowVariableEntity) { update(scoreDirector, testdataQuarkusShadowVariableEntity); } diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/superclass/constraints/DummyConstraintProvider.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/superclass/constraints/DummyConstraintProvider.java index 619983f9ca..b8b520ba0b 100644 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/superclass/constraints/DummyConstraintProvider.java +++ b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdata/superclass/constraints/DummyConstraintProvider.java @@ -4,10 +4,12 @@ import ai.timefold.solver.core.api.score.stream.ConstraintFactory; import ai.timefold.solver.core.api.score.stream.ConstraintProvider; +import org.jspecify.annotations.NonNull; + public class DummyConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] {}; } diff --git a/quarkus-integration/quarkus/devui-integration-test/src/main/java/ai/timefold/solver/quarkus/it/devui/domain/StringLengthVariableListener.java b/quarkus-integration/quarkus/devui-integration-test/src/main/java/ai/timefold/solver/quarkus/it/devui/domain/StringLengthVariableListener.java index 99f284d5e6..735b4eb828 100644 --- a/quarkus-integration/quarkus/devui-integration-test/src/main/java/ai/timefold/solver/quarkus/it/devui/domain/StringLengthVariableListener.java +++ b/quarkus-integration/quarkus/devui-integration-test/src/main/java/ai/timefold/solver/quarkus/it/devui/domain/StringLengthVariableListener.java @@ -3,30 +3,32 @@ import ai.timefold.solver.core.api.domain.variable.VariableListener; import ai.timefold.solver.core.api.score.director.ScoreDirector; +import org.jspecify.annotations.NonNull; + public class StringLengthVariableListener implements VariableListener { @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, - TestdataStringLengthShadowEntity entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataStringLengthShadowEntity entity) { /* Nothing to do */ } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataStringLengthShadowEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataStringLengthShadowEntity entity) { /* Nothing to do */ } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, - TestdataStringLengthShadowEntity entity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataStringLengthShadowEntity entity) { /* Nothing to do */ } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataStringLengthShadowEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataStringLengthShadowEntity entity) { int oldLength = (entity.getLength() != null) ? entity.getLength() : 0; int newLength = getLength(entity.getValue()); if (oldLength != newLength) { @@ -37,14 +39,14 @@ public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataStringLengthShadowEntity entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataStringLengthShadowEntity entity) { /* Nothing to do */ } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, - TestdataStringLengthShadowEntity entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataStringLengthShadowEntity entity) { /* Nothing to do */ } diff --git a/quarkus-integration/quarkus/devui-integration-test/src/main/java/ai/timefold/solver/quarkus/it/devui/solver/TestdataStringLengthConstraintProvider.java b/quarkus-integration/quarkus/devui-integration-test/src/main/java/ai/timefold/solver/quarkus/it/devui/solver/TestdataStringLengthConstraintProvider.java index bb8888c528..1269b6b803 100644 --- a/quarkus-integration/quarkus/devui-integration-test/src/main/java/ai/timefold/solver/quarkus/it/devui/solver/TestdataStringLengthConstraintProvider.java +++ b/quarkus-integration/quarkus/devui-integration-test/src/main/java/ai/timefold/solver/quarkus/it/devui/solver/TestdataStringLengthConstraintProvider.java @@ -7,10 +7,12 @@ import ai.timefold.solver.core.api.score.stream.Joiners; import ai.timefold.solver.quarkus.it.devui.domain.TestdataStringLengthShadowEntity; +import org.jspecify.annotations.NonNull; + public class TestdataStringLengthConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(TestdataStringLengthShadowEntity.class) .join(TestdataStringLengthShadowEntity.class, Joiners.equal(TestdataStringLengthShadowEntity::getValue)) diff --git a/quarkus-integration/quarkus/integration-test/src/main/java/ai/timefold/solver/quarkus/it/domain/StringLengthVariableListener.java b/quarkus-integration/quarkus/integration-test/src/main/java/ai/timefold/solver/quarkus/it/domain/StringLengthVariableListener.java index 31e68bbad1..eb9dfd3021 100644 --- a/quarkus-integration/quarkus/integration-test/src/main/java/ai/timefold/solver/quarkus/it/domain/StringLengthVariableListener.java +++ b/quarkus-integration/quarkus/integration-test/src/main/java/ai/timefold/solver/quarkus/it/domain/StringLengthVariableListener.java @@ -3,30 +3,32 @@ import ai.timefold.solver.core.api.domain.variable.VariableListener; import ai.timefold.solver.core.api.score.director.ScoreDirector; +import org.jspecify.annotations.NonNull; + public class StringLengthVariableListener implements VariableListener { @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, - TestdataStringLengthShadowEntity entity) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataStringLengthShadowEntity entity) { /* Nothing to do */ } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, - TestdataStringLengthShadowEntity entity) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataStringLengthShadowEntity entity) { /* Nothing to do */ } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, - TestdataStringLengthShadowEntity entity) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataStringLengthShadowEntity entity) { /* Nothing to do */ } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataStringLengthShadowEntity entity) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataStringLengthShadowEntity entity) { int oldLength = (entity.getLength() != null) ? entity.getLength() : 0; int newLength = getLength(entity.getValue()); if (oldLength != newLength) { @@ -37,14 +39,14 @@ public void afterVariableChanged(ScoreDirector scoreDirector, - TestdataStringLengthShadowEntity entity) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataStringLengthShadowEntity entity) { /* Nothing to do */ } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, - TestdataStringLengthShadowEntity entity) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, + @NonNull TestdataStringLengthShadowEntity entity) { /* Nothing to do */ } diff --git a/quarkus-integration/quarkus/integration-test/src/main/java/ai/timefold/solver/quarkus/it/solver/TestdataStringLengthConstraintProvider.java b/quarkus-integration/quarkus/integration-test/src/main/java/ai/timefold/solver/quarkus/it/solver/TestdataStringLengthConstraintProvider.java index 86d8c69b68..18cf3f1cf3 100644 --- a/quarkus-integration/quarkus/integration-test/src/main/java/ai/timefold/solver/quarkus/it/solver/TestdataStringLengthConstraintProvider.java +++ b/quarkus-integration/quarkus/integration-test/src/main/java/ai/timefold/solver/quarkus/it/solver/TestdataStringLengthConstraintProvider.java @@ -7,10 +7,12 @@ import ai.timefold.solver.core.api.score.stream.Joiners; import ai.timefold.solver.quarkus.it.domain.TestdataStringLengthShadowEntity; +import org.jspecify.annotations.NonNull; + public class TestdataStringLengthConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(TestdataStringLengthShadowEntity.class) .join(TestdataStringLengthShadowEntity.class, Joiners.equal(TestdataStringLengthShadowEntity::getValue)) diff --git a/quarkus-integration/quarkus/reflection-integration-test/src/main/java/ai/timefold/solver/quarkus/it/reflection/solver/TestdataStringLengthConstraintProvider.java b/quarkus-integration/quarkus/reflection-integration-test/src/main/java/ai/timefold/solver/quarkus/it/reflection/solver/TestdataStringLengthConstraintProvider.java index 70f26fa42f..e512bf80b7 100644 --- a/quarkus-integration/quarkus/reflection-integration-test/src/main/java/ai/timefold/solver/quarkus/it/reflection/solver/TestdataStringLengthConstraintProvider.java +++ b/quarkus-integration/quarkus/reflection-integration-test/src/main/java/ai/timefold/solver/quarkus/it/reflection/solver/TestdataStringLengthConstraintProvider.java @@ -7,10 +7,12 @@ import ai.timefold.solver.core.api.score.stream.Joiners; import ai.timefold.solver.quarkus.it.reflection.domain.TestdataReflectionEntity; +import org.jspecify.annotations.NonNull; + public class TestdataStringLengthConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(TestdataReflectionEntity.class) .join(TestdataReflectionEntity.class, Joiners.equal(TestdataReflectionEntity::getMethodValue)) diff --git a/spring-integration/spring-boot-autoconfigure/pom.xml b/spring-integration/spring-boot-autoconfigure/pom.xml index a45ee8e50a..2b45d02390 100644 --- a/spring-integration/spring-boot-autoconfigure/pom.xml +++ b/spring-integration/spring-boot-autoconfigure/pom.xml @@ -138,6 +138,13 @@ snakeyaml test + + + + org.jspecify + jspecify + test + diff --git a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/chained/constraints/TestdataChainedSpringConstraintProvider.java b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/chained/constraints/TestdataChainedSpringConstraintProvider.java index aed146fdc8..ce55fbf70f 100644 --- a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/chained/constraints/TestdataChainedSpringConstraintProvider.java +++ b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/chained/constraints/TestdataChainedSpringConstraintProvider.java @@ -8,10 +8,12 @@ import ai.timefold.solver.spring.boot.autoconfigure.chained.domain.TestdataChainedSpringAnchor; import ai.timefold.solver.spring.boot.autoconfigure.chained.domain.TestdataChainedSpringEntity; +import org.jspecify.annotations.NonNull; + public class TestdataChainedSpringConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(TestdataChainedSpringAnchor.class) .ifNotExists(TestdataChainedSpringEntity.class, diff --git a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/chained/constraints/easy/DummyChainedSpringEasyScore.java b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/chained/constraints/easy/DummyChainedSpringEasyScore.java index 1df05ea0d8..e0cb930696 100644 --- a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/chained/constraints/easy/DummyChainedSpringEasyScore.java +++ b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/chained/constraints/easy/DummyChainedSpringEasyScore.java @@ -4,9 +4,11 @@ import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; import ai.timefold.solver.spring.boot.autoconfigure.chained.domain.TestdataChainedSpringSolution; +import org.jspecify.annotations.NonNull; + public class DummyChainedSpringEasyScore implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataChainedSpringSolution testdataSpringSolution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataChainedSpringSolution testdataSpringSolution) { return null; } } diff --git a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/chained/constraints/incremental/DummyChainedSpringIncrementalScore.java b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/chained/constraints/incremental/DummyChainedSpringIncrementalScore.java index 92342e8879..46148da108 100644 --- a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/chained/constraints/incremental/DummyChainedSpringIncrementalScore.java +++ b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/chained/constraints/incremental/DummyChainedSpringIncrementalScore.java @@ -3,44 +3,46 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.api.score.calculator.IncrementalScoreCalculator; +import org.jspecify.annotations.NonNull; + public class DummyChainedSpringIncrementalScore implements IncrementalScoreCalculator { @Override - public void resetWorkingSolution(Object workingSolution) { + public void resetWorkingSolution(@NonNull Object workingSolution) { } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public Score calculateScore() { + public @NonNull Score calculateScore() { return null; } } diff --git a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/normal/constraints/easy/DummySpringEasyScore.java b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/normal/constraints/easy/DummySpringEasyScore.java index c17ed5de29..8061ed0581 100644 --- a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/normal/constraints/easy/DummySpringEasyScore.java +++ b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/normal/constraints/easy/DummySpringEasyScore.java @@ -4,9 +4,11 @@ import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; import ai.timefold.solver.spring.boot.autoconfigure.normal.domain.TestdataSpringSolution; +import org.jspecify.annotations.NonNull; + public class DummySpringEasyScore implements EasyScoreCalculator { @Override - public SimpleScore calculateScore(TestdataSpringSolution testdataSpringSolution) { + public @NonNull SimpleScore calculateScore(@NonNull TestdataSpringSolution testdataSpringSolution) { return null; } } diff --git a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/normal/constraints/incremental/DummySpringIncrementalScore.java b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/normal/constraints/incremental/DummySpringIncrementalScore.java index c2a52c9bf2..9827de46d4 100644 --- a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/normal/constraints/incremental/DummySpringIncrementalScore.java +++ b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/dummy/normal/constraints/incremental/DummySpringIncrementalScore.java @@ -3,44 +3,46 @@ import ai.timefold.solver.core.api.score.Score; import ai.timefold.solver.core.api.score.calculator.IncrementalScoreCalculator; +import org.jspecify.annotations.NonNull; + public class DummySpringIncrementalScore implements IncrementalScoreCalculator { @Override - public void resetWorkingSolution(Object workingSolution) { + public void resetWorkingSolution(@NonNull Object workingSolution) { } @Override - public void beforeEntityAdded(Object entity) { + public void beforeEntityAdded(@NonNull Object entity) { } @Override - public void afterEntityAdded(Object entity) { + public void afterEntityAdded(@NonNull Object entity) { } @Override - public void beforeVariableChanged(Object entity, String variableName) { + public void beforeVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void afterVariableChanged(Object entity, String variableName) { + public void afterVariableChanged(@NonNull Object entity, @NonNull String variableName) { } @Override - public void beforeEntityRemoved(Object entity) { + public void beforeEntityRemoved(@NonNull Object entity) { } @Override - public void afterEntityRemoved(Object entity) { + public void afterEntityRemoved(@NonNull Object entity) { } @Override - public Score calculateScore() { + public @NonNull Score calculateScore() { return null; } } diff --git a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/gizmo/constraints/TestdataGizmoConstraintProvider.java b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/gizmo/constraints/TestdataGizmoConstraintProvider.java index aac7bf00d2..fa67bcc548 100644 --- a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/gizmo/constraints/TestdataGizmoConstraintProvider.java +++ b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/gizmo/constraints/TestdataGizmoConstraintProvider.java @@ -7,10 +7,12 @@ import ai.timefold.solver.core.api.score.stream.Joiners; import ai.timefold.solver.spring.boot.autoconfigure.gizmo.domain.TestdataGizmoSpringEntity; +import org.jspecify.annotations.NonNull; + public class TestdataGizmoConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(TestdataGizmoSpringEntity.class) .join(TestdataGizmoSpringEntity.class, Joiners.equal(TestdataGizmoSpringEntity::getValue)) diff --git a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/invalid/VariableListener.java b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/invalid/VariableListener.java index 30d726f76e..e7b4a1146d 100644 --- a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/invalid/VariableListener.java +++ b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/invalid/VariableListener.java @@ -2,34 +2,36 @@ import ai.timefold.solver.core.api.score.director.ScoreDirector; +import org.jspecify.annotations.NonNull; + public class VariableListener implements ai.timefold.solver.core.api.domain.variable.VariableListener { @Override - public void beforeEntityAdded(ScoreDirector scoreDirector, Object o) { + public void beforeEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { } @Override - public void afterEntityAdded(ScoreDirector scoreDirector, Object o) { + public void afterEntityAdded(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { } @Override - public void beforeEntityRemoved(ScoreDirector scoreDirector, Object o) { + public void beforeEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { } @Override - public void afterEntityRemoved(ScoreDirector scoreDirector, Object o) { + public void afterEntityRemoved(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { } @Override - public void beforeVariableChanged(ScoreDirector scoreDirector, Object o) { + public void beforeVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { } @Override - public void afterVariableChanged(ScoreDirector scoreDirector, Object o) { + public void afterVariableChanged(@NonNull ScoreDirector scoreDirector, @NonNull Object o) { } } diff --git a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/normal/constraints/TestdataSpringConstraintProvider.java b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/normal/constraints/TestdataSpringConstraintProvider.java index a0c800f812..bcc72d37fb 100644 --- a/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/normal/constraints/TestdataSpringConstraintProvider.java +++ b/spring-integration/spring-boot-autoconfigure/src/test/java/ai/timefold/solver/spring/boot/autoconfigure/normal/constraints/TestdataSpringConstraintProvider.java @@ -7,10 +7,12 @@ import ai.timefold.solver.core.api.score.stream.Joiners; import ai.timefold.solver.spring.boot.autoconfigure.normal.domain.TestdataSpringEntity; +import org.jspecify.annotations.NonNull; + public class TestdataSpringConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory factory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory factory) { return new Constraint[] { factory.forEach(TestdataSpringEntity.class) .join(TestdataSpringEntity.class, Joiners.equal(TestdataSpringEntity::getValue)) diff --git a/spring-integration/spring-boot-integration-test/src/main/java/ai/timefold/solver/spring/boot/it/solver/IntegrationTestConstraintProvider.java b/spring-integration/spring-boot-integration-test/src/main/java/ai/timefold/solver/spring/boot/it/solver/IntegrationTestConstraintProvider.java index 120b7b9445..9ccae98768 100644 --- a/spring-integration/spring-boot-integration-test/src/main/java/ai/timefold/solver/spring/boot/it/solver/IntegrationTestConstraintProvider.java +++ b/spring-integration/spring-boot-integration-test/src/main/java/ai/timefold/solver/spring/boot/it/solver/IntegrationTestConstraintProvider.java @@ -6,9 +6,11 @@ import ai.timefold.solver.core.api.score.stream.ConstraintProvider; import ai.timefold.solver.spring.boot.it.domain.IntegrationTestEntity; +import org.jspecify.annotations.NonNull; + public class IntegrationTestConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { constraintFactory.forEach(IntegrationTestEntity.class) .filter(entity -> !entity.getId().equals(entity.getValue().id())) diff --git a/test/pom.xml b/test/pom.xml index ea478902bd..84b4f62114 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -61,6 +61,11 @@ assertj-core test + + + org.jspecify + jspecify + diff --git a/test/src/main/java/ai/timefold/solver/test/api/solver/change/MockProblemChangeDirector.java b/test/src/main/java/ai/timefold/solver/test/api/solver/change/MockProblemChangeDirector.java index 7807aa7123..670cde52c2 100644 --- a/test/src/main/java/ai/timefold/solver/test/api/solver/change/MockProblemChangeDirector.java +++ b/test/src/main/java/ai/timefold/solver/test/api/solver/change/MockProblemChangeDirector.java @@ -7,6 +7,9 @@ import ai.timefold.solver.core.api.solver.change.ProblemChangeDirector; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; + /** * Use for unit-testing {@link ai.timefold.solver.core.api.solver.change.ProblemChange}s. * @@ -30,33 +33,36 @@ public class MockProblemChangeDirector implements ProblemChangeDirector { private Map lookUpTable = new IdentityHashMap<>(); @Override - public void addEntity(Entity entity, Consumer entityConsumer) { + public void addEntity(@NonNull Entity entity, @NonNull Consumer entityConsumer) { entityConsumer.accept(lookUpWorkingObjectOrFail(entity)); } @Override - public void removeEntity(Entity entity, Consumer entityConsumer) { + public void removeEntity(@NonNull Entity entity, Consumer entityConsumer) { entityConsumer.accept(lookUpWorkingObjectOrFail(entity)); } @Override - public void changeVariable(Entity entity, String variableName, Consumer entityConsumer) { + public void changeVariable(@NonNull Entity entity, @NonNull String variableName, + @NonNull Consumer entityConsumer) { entityConsumer.accept(lookUpWorkingObjectOrFail(entity)); } @Override - public void addProblemFact(ProblemFact problemFact, Consumer problemFactConsumer) { + public void addProblemFact(@NonNull ProblemFact problemFact, + @NonNull Consumer problemFactConsumer) { problemFactConsumer.accept(lookUpWorkingObjectOrFail(problemFact)); } @Override - public void removeProblemFact(ProblemFact problemFact, Consumer problemFactConsumer) { + public void removeProblemFact(@NonNull ProblemFact problemFact, + @NonNull Consumer problemFactConsumer) { problemFactConsumer.accept(lookUpWorkingObjectOrFail(problemFact)); } @Override - public void changeProblemProperty(EntityOrProblemFact problemFactOrEntity, - Consumer problemFactOrEntityConsumer) { + public void changeProblemProperty(@NonNull EntityOrProblemFact problemFactOrEntity, + @NonNull Consumer problemFactOrEntityConsumer) { problemFactOrEntityConsumer.accept(lookUpWorkingObjectOrFail(problemFactOrEntity)); } @@ -67,7 +73,8 @@ public void changeProblemProperty(EntityOrProblemFact prob * @param externalObject entity or problem fact to look up */ @Override - public EntityOrProblemFact lookUpWorkingObjectOrFail(EntityOrProblemFact externalObject) { + public @Nullable EntityOrProblemFact + lookUpWorkingObjectOrFail(@Nullable EntityOrProblemFact externalObject) { EntityOrProblemFact entityOrProblemFact = (EntityOrProblemFact) lookUpTable.get(externalObject); return entityOrProblemFact == null ? externalObject : entityOrProblemFact; } @@ -80,7 +87,7 @@ public EntityOrProblemFact lookUpWorkingObjectOrFail(Entit */ @Override public Optional - lookUpWorkingObject(EntityOrProblemFact externalObject) { + lookUpWorkingObject(@Nullable EntityOrProblemFact externalObject) { return Optional.ofNullable((EntityOrProblemFact) lookUpTable.get(externalObject)); } diff --git a/test/src/test/java/ai/timefold/solver/test/api/score/stream/MultiConstraintAssertionTest.java b/test/src/test/java/ai/timefold/solver/test/api/score/stream/MultiConstraintAssertionTest.java index 320e78c652..ab471b2602 100644 --- a/test/src/test/java/ai/timefold/solver/test/api/score/stream/MultiConstraintAssertionTest.java +++ b/test/src/test/java/ai/timefold/solver/test/api/score/stream/MultiConstraintAssertionTest.java @@ -24,6 +24,7 @@ import ai.timefold.solver.test.api.score.stream.testdata.TestdataConstraintVerifierFirstEntity; import ai.timefold.solver.test.api.score.stream.testdata.TestdataConstraintVerifierSecondEntity; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Test; class MultiConstraintAssertionTest { @@ -79,7 +80,7 @@ void listVarUnassignedWhileAllowsUnassigned() { private static final class TestdataAllowsUnassignedListConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { penalizeEveryAssignedValue(constraintFactory), penalizeEveryValue(constraintFactory) @@ -131,7 +132,7 @@ void listVarUnassignedWhileDisallowsUnassigned() { private static final class TestdataDisallowsUnassignedListConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { penalizeEveryAssignedValue(constraintFactory), penalizeEveryValue(constraintFactory) @@ -184,7 +185,7 @@ private static final class TestdataDisallowsUnassignedListWithoutInverseShadowVa implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { penalizeEveryAssignedValue(constraintFactory), penalizeEveryValue(constraintFactory) diff --git a/test/src/test/java/ai/timefold/solver/test/api/score/stream/SingleConstraintAssertionTest.java b/test/src/test/java/ai/timefold/solver/test/api/score/stream/SingleConstraintAssertionTest.java index 0518430a0e..4d2d860301 100644 --- a/test/src/test/java/ai/timefold/solver/test/api/score/stream/SingleConstraintAssertionTest.java +++ b/test/src/test/java/ai/timefold/solver/test/api/score/stream/SingleConstraintAssertionTest.java @@ -28,6 +28,7 @@ import ai.timefold.solver.test.api.score.stream.testdata.justification.TestFirstJustification; import ai.timefold.solver.test.api.score.stream.testdata.justification.TestSecondJustification; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Test; class SingleConstraintAssertionTest { @@ -481,7 +482,7 @@ void listVarUnassignedWhileAllowsUnassigned() { private static final class TestdataAllowsUnassignedListConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { penalizeEveryAssignedValue(constraintFactory), penalizeEveryValue(constraintFactory) @@ -529,7 +530,7 @@ void listVarUnassignedWhileDisallowsUnassigned() { private static final class TestdataDisallowsUnassignedListConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { penalizeEveryAssignedValue(constraintFactory), penalizeEveryValue(constraintFactory) @@ -578,7 +579,7 @@ private static final class TestdataDisallowsUnassignedListWithoutInverseShadowVa implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { penalizeEveryAssignedValue(constraintFactory), penalizeEveryValue(constraintFactory) diff --git a/test/src/test/java/ai/timefold/solver/test/api/score/stream/testdata/TestdataConstraintVerifierConstraintProvider.java b/test/src/test/java/ai/timefold/solver/test/api/score/stream/testdata/TestdataConstraintVerifierConstraintProvider.java index 47de711bc9..c0f6db560b 100644 --- a/test/src/test/java/ai/timefold/solver/test/api/score/stream/testdata/TestdataConstraintVerifierConstraintProvider.java +++ b/test/src/test/java/ai/timefold/solver/test/api/score/stream/testdata/TestdataConstraintVerifierConstraintProvider.java @@ -8,9 +8,11 @@ import ai.timefold.solver.core.api.score.stream.ConstraintProvider; import ai.timefold.solver.core.api.score.stream.Joiners; +import org.jspecify.annotations.NonNull; + public final class TestdataConstraintVerifierConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { penalizeEveryEntity(constraintFactory), rewardEveryEntity(constraintFactory), diff --git a/test/src/test/java/ai/timefold/solver/test/api/score/stream/testdata/TestdataConstraintVerifierDuplicateConstraintProvider.java b/test/src/test/java/ai/timefold/solver/test/api/score/stream/testdata/TestdataConstraintVerifierDuplicateConstraintProvider.java index d96b9b5305..79bc3340b1 100644 --- a/test/src/test/java/ai/timefold/solver/test/api/score/stream/testdata/TestdataConstraintVerifierDuplicateConstraintProvider.java +++ b/test/src/test/java/ai/timefold/solver/test/api/score/stream/testdata/TestdataConstraintVerifierDuplicateConstraintProvider.java @@ -5,9 +5,11 @@ import ai.timefold.solver.core.api.score.stream.ConstraintFactory; import ai.timefold.solver.core.api.score.stream.ConstraintProvider; +import org.jspecify.annotations.NonNull; + public final class TestdataConstraintVerifierDuplicateConstraintProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { penalizeEveryEntity(constraintFactory), penalizeEveryEntity(constraintFactory) diff --git a/test/src/test/java/ai/timefold/solver/test/api/score/stream/testdata/TestdataConstraintVerifierJustificationProvider.java b/test/src/test/java/ai/timefold/solver/test/api/score/stream/testdata/TestdataConstraintVerifierJustificationProvider.java index 6e7f194e3d..5fe5683ae8 100644 --- a/test/src/test/java/ai/timefold/solver/test/api/score/stream/testdata/TestdataConstraintVerifierJustificationProvider.java +++ b/test/src/test/java/ai/timefold/solver/test/api/score/stream/testdata/TestdataConstraintVerifierJustificationProvider.java @@ -8,9 +8,11 @@ import ai.timefold.solver.core.api.score.stream.ConstraintProvider; import ai.timefold.solver.test.api.score.stream.testdata.justification.TestFirstJustification; +import org.jspecify.annotations.NonNull; + public final class TestdataConstraintVerifierJustificationProvider implements ConstraintProvider { @Override - public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) { return new Constraint[] { justifyWithFirstJustification(constraintFactory), justifyWithNoJustifications(constraintFactory)

    * This method has overloaded methods with multiple {@link TriJoiner} parameters. * - * @param otherClass never null - * @param joiner never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner} is true */ - default BiConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, TriJoiner joiner) { + default @NonNull BiConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull TriJoiner joiner) { return ifNotExistsIncludingUnassigned(otherClass, new TriJoiner[] { joiner }); } @@ -739,15 +645,13 @@ default BiConstraintStream ifNotExistsIncludingUnassigned(Class oth * As defined by {@link #ifNotExistsIncludingUnassigned(Class, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner}s are true */ - default BiConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2) { + default @NonNull BiConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2) { return ifNotExistsIncludingUnassigned(otherClass, new TriJoiner[] { joiner1, joiner2 }); } @@ -755,16 +659,13 @@ default BiConstraintStream ifNotExistsIncludingUnassigned(Class oth * As defined by {@link #ifNotExistsIncludingUnassigned(Class, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner}s are true */ - default BiConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3) { + default @NonNull BiConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull TriJoiner joiner1, + @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3) { return ifNotExistsIncludingUnassigned(otherClass, new TriJoiner[] { joiner1, joiner2, joiner3 }); } @@ -772,17 +673,13 @@ default BiConstraintStream ifNotExistsIncludingUnassigned(Class oth * As defined by {@link #ifNotExistsIncludingUnassigned(Class, TriJoiner)}. * For performance reasons, indexing joiners must be placed before filtering joiners. * - * @param otherClass never null - * @param joiner1 never null - * @param joiner2 never null - * @param joiner3 never null - * @param joiner4 never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner}s are true */ - default BiConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, TriJoiner joiner1, - TriJoiner joiner2, TriJoiner joiner3, TriJoiner joiner4) { + default @NonNull BiConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull TriJoiner joiner1, @NonNull TriJoiner joiner2, @NonNull TriJoiner joiner3, + @NonNull TriJoiner joiner4) { return ifNotExistsIncludingUnassigned(otherClass, new TriJoiner[] { joiner1, joiner2, joiner3, joiner4 }); } @@ -794,13 +691,12 @@ default BiConstraintStream ifNotExistsIncludingUnassigned(Class oth * but we can't fix it with a {@link SafeVarargs} annotation because it's an interface method. * Therefore, there are overloaded methods with up to 4 {@link TriJoiner} parameters. * - * @param otherClass never null - * @param joiners never null * @param the type of the third matched fact - * @return never null, a stream that matches every pair of A and B where C does not exist for which the + * @return a stream that matches every pair of A and B where C does not exist for which the * {@link TriJoiner}s are true */ - BiConstraintStream ifNotExistsIncludingUnassigned(Class otherClass, TriJoiner... joiners); + @NonNull BiConstraintStream ifNotExistsIncludingUnassigned(@NonNull Class otherClass, + @NonNull TriJoiner... joiners); // ************************************************************************ // Group by @@ -810,42 +706,40 @@ default BiConstraintStream ifNotExistsIncludingUnassigned(Class oth * Runs all tuples of the stream through a given @{@link BiConstraintCollector} and converts them into a new * {@link UniConstraintStream} which only has a single tuple, the result of applying {@link BiConstraintCollector}. * - * @param collector never null, the collector to perform the grouping operation with + * @param collector the collector to perform the grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of a fact in the destination {@link UniConstraintStream}'s tuple - * @return never null */ - UniConstraintStream groupBy( - BiConstraintCollector collector); + @NonNull UniConstraintStream groupBy( + @NonNull BiConstraintCollector collector); /** * Convert the {@link BiConstraintStream} to a {@link BiConstraintStream}, containing only a single tuple, * the result of applying two {@link BiConstraintCollector}s. * - * @param collectorA never null, the collector to perform the first grouping operation with + * @param collectorA the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorB never null, the collector to perform the second grouping operation with + * @param collectorB the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the first fact in the destination {@link BiConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the second fact in the destination {@link BiConstraintStream}'s tuple - * @return never null */ - BiConstraintStream groupBy( - BiConstraintCollector collectorA, - BiConstraintCollector collectorB); + @NonNull BiConstraintStream groupBy( + @NonNull BiConstraintCollector collectorA, + @NonNull BiConstraintCollector collectorB); /** * Convert the {@link BiConstraintStream} to a {@link TriConstraintStream}, containing only a single tuple, * the result of applying three {@link BiConstraintCollector}s. * - * @param collectorA never null, the collector to perform the first grouping operation with + * @param collectorA the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorB never null, the collector to perform the second grouping operation with + * @param collectorB the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorC never null, the collector to perform the third grouping operation with + * @param collectorC the collector to perform the third grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the first fact in the destination {@link TriConstraintStream}'s tuple @@ -853,25 +747,24 @@ BiConstraintStream the type of the second fact in the destination {@link TriConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the third fact in the destination {@link TriConstraintStream}'s tuple - * @return never null */ - TriConstraintStream groupBy( - BiConstraintCollector collectorA, - BiConstraintCollector collectorB, - BiConstraintCollector collectorC); + @NonNull TriConstraintStream groupBy( + @NonNull BiConstraintCollector collectorA, + @NonNull BiConstraintCollector collectorB, + @NonNull BiConstraintCollector collectorC); /** * Convert the {@link BiConstraintStream} to a {@link QuadConstraintStream}, containing only a single tuple, * the result of applying four {@link BiConstraintCollector}s. * - * @param collectorA never null, the collector to perform the first grouping operation with + * @param collectorA the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorB never null, the collector to perform the second grouping operation with + * @param collectorB the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorC never null, the collector to perform the third grouping operation with + * @param collectorC the collector to perform the third grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorD never null, the collector to perform the fourth grouping operation with + * @param collectorD the collector to perform the fourth grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the first fact in the destination {@link QuadConstraintStream}'s tuple @@ -881,25 +774,23 @@ TriConstraintStream groupBy( * @param the type of the third fact in the destination {@link QuadConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream groupBy( - BiConstraintCollector collectorA, - BiConstraintCollector collectorB, - BiConstraintCollector collectorC, - BiConstraintCollector collectorD); + @NonNull QuadConstraintStream groupBy( + @NonNull BiConstraintCollector collectorA, + @NonNull BiConstraintCollector collectorB, + @NonNull BiConstraintCollector collectorC, + @NonNull BiConstraintCollector collectorD); /** * Convert the {@link BiConstraintStream} to a {@link UniConstraintStream}, containing the set of tuples resulting * from applying the group key mapping function on all tuples of the original stream. * Neither tuple of the new stream {@link Objects#equals(Object, Object)} any other. * - * @param groupKeyMapping never null, mapping function to convert each element in the stream to a different element + * @param groupKeyMapping mapping function to convert each element in the stream to a different element * @param the type of a fact in the destination {@link UniConstraintStream}'s tuple - * @return never null */ - UniConstraintStream groupBy(BiFunction groupKeyMapping); + @NonNull UniConstraintStream groupBy(@NonNull BiFunction groupKeyMapping); /** * Convert the {@link BiConstraintStream} to a different {@link BiConstraintStream}, consisting of unique tuples. @@ -908,18 +799,17 @@ QuadConstraintStream groupBy( * The second fact is the return value of a given {@link BiConstraintCollector} applied on all incoming tuples with * the same first fact. * - * @param groupKeyMapping never null, function to convert the fact in the original tuple to a different fact - * @param collector never null, the collector to perform the grouping operation with + * @param groupKeyMapping function to convert the fact in the original tuple to a different fact + * @param collector the collector to perform the grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the type of the first fact in the destination {@link BiConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the second fact in the destination {@link BiConstraintStream}'s tuple - * @return never null */ - BiConstraintStream groupBy( - BiFunction groupKeyMapping, - BiConstraintCollector collector); + @NonNull BiConstraintStream groupBy( + @NonNull BiFunction groupKeyMapping, + @NonNull BiConstraintCollector collector); /** * Convert the {@link BiConstraintStream} to a {@link TriConstraintStream}, consisting of unique tuples with three @@ -929,10 +819,10 @@ BiConstraintStream gr * The remaining facts are the return value of the respective {@link BiConstraintCollector} applied on all * incoming tuples with the same first fact. * - * @param groupKeyMapping never null, function to convert the fact in the original tuple to a different fact - * @param collectorB never null, the collector to perform the first grouping operation with + * @param groupKeyMapping function to convert the fact in the original tuple to a different fact + * @param collectorB the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorC never null, the collector to perform the second grouping operation with + * @param collectorC the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the type of the first fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -940,13 +830,12 @@ BiConstraintStream gr * @param the type of the second fact in the destination {@link TriConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the third fact in the destination {@link TriConstraintStream}'s tuple - * @return never null */ - TriConstraintStream groupBy( - BiFunction groupKeyMapping, - BiConstraintCollector collectorB, - BiConstraintCollector collectorC); + @NonNull TriConstraintStream groupBy( + @NonNull BiFunction groupKeyMapping, + @NonNull BiConstraintCollector collectorB, + @NonNull BiConstraintCollector collectorC); /** * Convert the {@link BiConstraintStream} to a {@link QuadConstraintStream}, consisting of unique tuples with four @@ -956,12 +845,12 @@ TriConstraintStream groupBy( * The remaining facts are the return value of the respective {@link BiConstraintCollector} applied on all * incoming tuples with the same first fact. * - * @param groupKeyMapping never null, function to convert the fact in the original tuple to a different fact - * @param collectorB never null, the collector to perform the first grouping operation with + * @param groupKeyMapping function to convert the fact in the original tuple to a different fact + * @param collectorB the collector to perform the first grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorC never null, the collector to perform the second grouping operation with + * @param collectorC the collector to perform the second grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. - * @param collectorD never null, the collector to perform the third grouping operation with + * @param collectorD the collector to perform the third grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the type of the first fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -971,14 +860,13 @@ TriConstraintStream groupBy( * @param the type of the third fact in the destination {@link QuadConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream groupBy( - BiFunction groupKeyMapping, - BiConstraintCollector collectorB, - BiConstraintCollector collectorC, - BiConstraintCollector collectorD); + @NonNull QuadConstraintStream groupBy( + @NonNull BiFunction groupKeyMapping, + @NonNull BiConstraintCollector collectorB, + @NonNull BiConstraintCollector collectorC, + @NonNull BiConstraintCollector collectorD); /** * Convert the {@link BiConstraintStream} to a different {@link BiConstraintStream}, consisting of unique tuples. @@ -987,16 +875,15 @@ QuadConstraintStream groupBy( * The second fact is the return value of the second group key mapping function, applied on all incoming tuples with * the same first fact. * - * @param groupKeyAMapping never null, function to convert the facts in the original tuple to a new fact - * @param groupKeyBMapping never null, function to convert the facts in the original tuple to another new fact + * @param groupKeyAMapping function to convert the facts in the original tuple to a new fact + * @param groupKeyBMapping function to convert the facts in the original tuple to another new fact * @param the type of the first fact in the destination {@link BiConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the second fact in the destination {@link BiConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. - * @return never null */ - BiConstraintStream groupBy( - BiFunction groupKeyAMapping, BiFunction groupKeyBMapping); + @NonNull BiConstraintStream groupBy( + @NonNull BiFunction groupKeyAMapping, @NonNull BiFunction groupKeyBMapping); /** * Combines the semantics of {@link #groupBy(BiFunction, BiFunction)} and {@link #groupBy(BiConstraintCollector)}. @@ -1004,9 +891,9 @@ BiConstraintStream groupBy( * and the third fact is the result of applying {@link BiConstraintCollector#finisher()} on all the tuples of the * original {@link UniConstraintStream} that belong to the group. * - * @param groupKeyAMapping never null, function to convert the original tuple into a first fact - * @param groupKeyBMapping never null, function to convert the original tuple into a second fact - * @param collector never null, the collector to perform the grouping operation with + * @param groupKeyAMapping function to convert the original tuple into a first fact + * @param groupKeyBMapping function to convert the original tuple into a second fact + * @param collector the collector to perform the grouping operation with * See {@link ConstraintCollectors} for common operations, such as {@code count()}, {@code sum()} and others. * @param the type of the first fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -1014,11 +901,10 @@ BiConstraintStream groupBy( * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the third fact in the destination {@link TriConstraintStream}'s tuple - * @return never null */ - TriConstraintStream groupBy( - BiFunction groupKeyAMapping, BiFunction groupKeyBMapping, - BiConstraintCollector collector); + @NonNull TriConstraintStream groupBy( + @NonNull BiFunction groupKeyAMapping, @NonNull BiFunction groupKeyBMapping, + @NonNull BiConstraintCollector collector); /** * Combines the semantics of {@link #groupBy(BiFunction, BiFunction)} and {@link #groupBy(BiConstraintCollector)}. @@ -1028,11 +914,11 @@ TriConstraintStream the type of the first fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -1042,13 +928,13 @@ TriConstraintStream the type of the third fact in the destination {@link QuadConstraintStream}'s tuple * @param the mutable accumulation type (often hidden as an implementation detail) * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream groupBy( - BiFunction groupKeyAMapping, BiFunction groupKeyBMapping, - BiConstraintCollector collectorC, - BiConstraintCollector collectorD); + @NonNull QuadConstraintStream groupBy( + @NonNull BiFunction groupKeyAMapping, + @NonNull BiFunction groupKeyBMapping, + @NonNull BiConstraintCollector collectorC, + @NonNull BiConstraintCollector collectorD); /** * Convert the {@link BiConstraintStream} to a {@link TriConstraintStream}, consisting of unique tuples with three @@ -1060,20 +946,19 @@ QuadConstraintStream groupBy( * The third fact is the return value of the third group key mapping function, applied on all incoming tuples with * the same first fact. * - * @param groupKeyAMapping never null, function to convert the original tuple into a first fact - * @param groupKeyBMapping never null, function to convert the original tuple into a second fact - * @param groupKeyCMapping never null, function to convert the original tuple into a third fact + * @param groupKeyAMapping function to convert the original tuple into a first fact + * @param groupKeyBMapping function to convert the original tuple into a second fact + * @param groupKeyCMapping function to convert the original tuple into a third fact * @param the type of the first fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the second fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the third fact in the destination {@link TriConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. - * @return never null */ - TriConstraintStream groupBy( - BiFunction groupKeyAMapping, BiFunction groupKeyBMapping, - BiFunction groupKeyCMapping); + @NonNull TriConstraintStream groupBy( + @NonNull BiFunction groupKeyAMapping, @NonNull BiFunction groupKeyBMapping, + @NonNull BiFunction groupKeyCMapping); /** * Combines the semantics of {@link #groupBy(BiFunction, BiFunction)} and {@link #groupBy(BiConstraintCollector)}. @@ -1081,10 +966,10 @@ TriConstraintStream the type of the first fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. @@ -1094,13 +979,13 @@ TriConstraintStream the mutable accumulation type (often hidden as an implementation detail) * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream groupBy( - BiFunction groupKeyAMapping, BiFunction groupKeyBMapping, - BiFunction groupKeyCMapping, - BiConstraintCollector collectorD); + @NonNull QuadConstraintStream groupBy( + @NonNull BiFunction groupKeyAMapping, + @NonNull BiFunction groupKeyBMapping, + @NonNull BiFunction groupKeyCMapping, + @NonNull BiConstraintCollector collectorD); /** * Convert the {@link BiConstraintStream} to a {@link QuadConstraintStream}, consisting of unique tuples with four @@ -1114,10 +999,10 @@ QuadConstraintStream groupBy( * The fourth fact is the return value of the fourth group key mapping function, applied on all incoming tuples with * the same first fact. * - * @param groupKeyAMapping never null, function to convert the original tuple into a first fact - * @param groupKeyBMapping never null, function to convert the original tuple into a second fact - * @param groupKeyCMapping never null, function to convert the original tuple into a third fact - * @param groupKeyDMapping never null, function to convert the original tuple into a fourth fact + * @param groupKeyAMapping function to convert the original tuple into a first fact + * @param groupKeyBMapping function to convert the original tuple into a second fact + * @param groupKeyCMapping function to convert the original tuple into a third fact + * @param groupKeyDMapping function to convert the original tuple into a fourth fact * @param the type of the first fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the second fact in the destination {@link QuadConstraintStream}'s tuple; @@ -1126,12 +1011,13 @@ QuadConstraintStream groupBy( * must honor {@link Object#hashCode() the general contract of hashCode}. * @param the type of the fourth fact in the destination {@link QuadConstraintStream}'s tuple; * must honor {@link Object#hashCode() the general contract of hashCode}. - * @return never null */ - QuadConstraintStream groupBy( - BiFunction groupKeyAMapping, BiFunction groupKeyBMapping, - BiFunction groupKeyCMapping, BiFunction groupKeyDMapping); + @NonNull QuadConstraintStream groupBy( + @NonNull BiFunction groupKeyAMapping, + @NonNull BiFunction groupKeyBMapping, + @NonNull BiFunction groupKeyCMapping, + @NonNull BiFunction groupKeyDMapping); // ************************************************************************ // Operations with duplicate tuple possibility @@ -1140,54 +1026,53 @@ QuadConstraintStream groupBy( /** * As defined by {@link UniConstraintStream#map(Function)}. * - * @param mapping never null, function to convert the original tuple into the new tuple + * @param mapping function to convert the original tuple into the new tuple * @param the type of the only fact in the resulting {@link UniConstraintStream}'s tuple - * @return never null */ - UniConstraintStream map(BiFunction mapping); + @NonNull UniConstraintStream map(@NonNull BiFunction mapping); /** * As defined by {@link #map(BiFunction)}, only resulting in {@link BiConstraintStream}. * - * @param mappingA never null, function to convert the original tuple into the first fact of a new tuple - * @param mappingB never null, function to convert the original tuple into the second fact of a new tuple + * @param mappingA function to convert the original tuple into the first fact of a new tuple + * @param mappingB function to convert the original tuple into the second fact of a new tuple * @param the type of the first fact in the resulting {@link BiConstraintStream}'s tuple * @param the type of the first fact in the resulting {@link BiConstraintStream}'s tuple - * @return never null */ - BiConstraintStream map(BiFunction mappingA, - BiFunction mappingB); + @NonNull BiConstraintStream map( + @NonNull BiFunction mappingA, + @NonNull BiFunction mappingB); /** * As defined by {@link #map(BiFunction)}, only resulting in {@link TriConstraintStream}. * - * @param mappingA never null, function to convert the original tuple into the first fact of a new tuple - * @param mappingB never null, function to convert the original tuple into the second fact of a new tuple - * @param mappingC never null, function to convert the original tuple into the third fact of a new tuple + * @param mappingA function to convert the original tuple into the first fact of a new tuple + * @param mappingB function to convert the original tuple into the second fact of a new tuple + * @param mappingC function to convert the original tuple into the third fact of a new tuple * @param the type of the first fact in the resulting {@link TriConstraintStream}'s tuple * @param the type of the first fact in the resulting {@link TriConstraintStream}'s tuple * @param the type of the third fact in the resulting {@link TriConstraintStream}'s tuple - * @return never null */ - TriConstraintStream map(BiFunction mappingA, - BiFunction mappingB, BiFunction mappingC); + @NonNull TriConstraintStream map( + @NonNull BiFunction mappingA, + @NonNull BiFunction mappingB, @NonNull BiFunction mappingC); /** * As defined by {@link #map(BiFunction)}, only resulting in {@link QuadConstraintStream}. * - * @param mappingA never null, function to convert the original tuple into the first fact of a new tuple - * @param mappingB never null, function to convert the original tuple into the second fact of a new tuple - * @param mappingC never null, function to convert the original tuple into the third fact of a new tuple - * @param mappingD never null, function to convert the original tuple into the fourth fact of a new tuple + * @param mappingA function to convert the original tuple into the first fact of a new tuple + * @param mappingB function to convert the original tuple into the second fact of a new tuple + * @param mappingC function to convert the original tuple into the third fact of a new tuple + * @param mappingD function to convert the original tuple into the fourth fact of a new tuple * @param the type of the first fact in the resulting {@link QuadConstraintStream}'s tuple * @param the type of the first fact in the resulting {@link QuadConstraintStream}'s tuple * @param the type of the third fact in the resulting {@link QuadConstraintStream}'s tuple * @param the type of the third fact in the resulting {@link QuadConstraintStream}'s tuple - * @return never null */ - QuadConstraintStream map( - BiFunction mappingA, BiFunction mappingB, BiFunction mappingC, - BiFunction mappingD); + @NonNull QuadConstraintStream map( + @NonNull BiFunction mappingA, @NonNull BiFunction mappingB, + @NonNull BiFunction mappingC, + @NonNull BiFunction mappingD); /** * Takes each tuple and applies a mapping on the last fact, which turns it into {@link Iterable}. @@ -1210,15 +1095,14 @@ QuadConstraintStream the type of the last fact in the resulting tuples. * It is recommended that this type be deeply immutable. * Not following this recommendation may lead to hard-to-debug hashing issues down the stream, * especially if this value is ever used as a group key. - * @return never null */ - BiConstraintStream flattenLast(Function> mapping); + @NonNull BiConstraintStream flattenLast(@NonNull Function> mapping); /** * Transforms the stream in such a way that all the tuples going through it are distinct. @@ -1230,8 +1114,8 @@ QuadConstraintStream distinct(); /** @@ -1245,11 +1129,8 @@ QuadConstraintStream * This operation can be thought of as an or between streams. - * - * @param otherStream never null - * @return never null */ - default BiConstraintStream concat(UniConstraintStream otherStream) { + default @NonNull BiConstraintStream concat(@NonNull UniConstraintStream otherStream) { return concat(otherStream, uniConstantNull()); } @@ -1266,11 +1147,10 @@ default BiConstraintStream concat(UniConstraintStream otherStream) { *