Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions build/build-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -447,14 +447,11 @@
<target>${maven.compiler.release}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<compilerArgs>
<!-- Visit https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javac.html
to learn more about javac warnings -->
<arg>-Xmaxwarns</arg>
<arg>100</arg>
<arg>-Xlint</arg>
<arg>-Xlint:-rawtypes</arg>
<arg>-Xlint:-serial</arg>
<arg>-Xlint:-unchecked</arg>
<!--
Suppress warnings about generated code to reduce log length.
Warnings are primarily dealt with during development in the IDE.
-->
<compilerArgument>-Xlint:none</compilerArgument>
Comment on lines +450 to +454
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compiler configuration disables all warnings with -Xlint:none, but the comment suggests warnings should be handled in the IDE. However, this approach may allow warnings to accumulate in the codebase since they won't be visible during CI builds. Consider using a more targeted approach that suppresses only specific unavoidable warnings while keeping critical warnings enabled.

Copilot uses AI. Check for mistakes.
</compilerArgs>
</configuration>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package ai.timefold.solver.core.api.score.constraint;

import java.util.Objects;
import ai.timefold.solver.core.impl.score.stream.common.AbstractConstraintBuilder;

import org.jspecify.annotations.NullMarked;

Expand All @@ -24,7 +24,7 @@ public static ConstraintRef of(String constraintName) {
}

public ConstraintRef {
var sanitized = Objects.requireNonNull(constraintName).trim();
var sanitized = AbstractConstraintBuilder.sanitize("constraintName", constraintName);
if (sanitized.isEmpty()) {
throw new IllegalArgumentException("The %s cannot be empty."
.formatted("constraint name"));
Comment on lines 28 to 30
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The redundant check at line 28 is unnecessary since sanitize() at line 27 already validates non-empty strings. The sanitized value can never be empty at this point.

Copilot uses AI. Check for mistakes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import ai.timefold.solver.core.api.score.constraint.ConstraintMatchTotal;

import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.NullMarked;

@NullMarked
public interface ConstraintBuilder {

/**
Expand All @@ -12,29 +13,34 @@ public interface ConstraintBuilder {
*
* @param constraintName shows up in {@link ConstraintMatchTotal} during score justification
*/
default @NonNull Constraint asConstraint(@NonNull String constraintName) {
default Constraint asConstraint(String constraintName) {
return asConstraintDescribed(constraintName, "");
}

/**
* Builds a {@link Constraint} from the constraint stream.
* The constraint will be placed in the {@link Constraint#DEFAULT_CONSTRAINT_GROUP default constraint group}.
* As defined by {@link #asConstraintDescribed(String, String, String)},
* placing the constraint in the {@link Constraint#DEFAULT_CONSTRAINT_GROUP default constraint group}.
*
* @param constraintName shows up in {@link ConstraintMatchTotal} during score justification
*/
@NonNull
default Constraint asConstraintDescribed(@NonNull String constraintName, @NonNull String constraintDescription) {
default Constraint asConstraintDescribed(String constraintName, String constraintDescription) {
return asConstraintDescribed(constraintName, constraintDescription, Constraint.DEFAULT_CONSTRAINT_GROUP);
}

/**
* Builds a {@link Constraint} from the constraint stream.
* Both the constraint name and the constraint group are only allowed
* to contain alphanumeric characters, " ", "-" or "_".
* The constraint description can contain any character, but it is recommended to keep it short and concise.
* <p>
* Unlike the constraint name and group,
* the constraint description is unlikely to be used externally as an identifier,
* and therefore doesn't need to be URL-friendly, or protected against injection attacks.
*
* @param constraintName shows up in {@link ConstraintMatchTotal} during score justification
* @param constraintGroup only allows alphanumeric characters, "-" and "_"
* @param constraintGroup not used by the solver directly, but may be used by external tools to group constraints together,
* such as by their source or by their purpose
*/
@NonNull
Constraint asConstraintDescribed(@NonNull String constraintName, @NonNull String constraintDescription,
@NonNull String constraintGroup);
Constraint asConstraintDescribed(String constraintName, String constraintDescription, String constraintGroup);

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import ai.timefold.solver.core.api.score.stream.ConstraintBuilder;
import ai.timefold.solver.core.api.score.stream.ConstraintJustification;

import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.NullMarked;

/**
* Used to build a {@link Constraint} out of a {@link BiConstraintStream}, applying optional configuration.
Expand All @@ -25,6 +25,7 @@
* Unless {@link #indictWith(BiFunction)} is called, the default indicted objects' mapping will be used.
* The function takes the input arguments and converts them into a {@link java.util.List}.
*/
@NullMarked
public interface BiConstraintBuilder<A, B, Score_ extends Score<Score_>> extends ConstraintBuilder {

/**
Expand All @@ -33,9 +34,8 @@ public interface BiConstraintBuilder<A, B, Score_ extends Score<Score_>> extends
* @see ConstraintMatch
* @return this
*/
@NonNull
<ConstraintJustification_ extends ConstraintJustification> BiConstraintBuilder<A, B, Score_> justifyWith(
@NonNull TriFunction<A, B, Score_, ConstraintJustification_> justificationMapping);
TriFunction<A, B, Score_, ConstraintJustification_> justificationMapping);

/**
* Sets a custom function to mark any object returned by it as responsible for causing the constraint to match.
Expand All @@ -44,7 +44,6 @@ <ConstraintJustification_ extends ConstraintJustification> BiConstraintBuilder<A
*
* @return this
*/
@NonNull
BiConstraintBuilder<A, B, Score_> indictWith(@NonNull BiFunction<A, B, Collection<Object>> indictedObjectsMapping);
BiConstraintBuilder<A, B, Score_> indictWith(BiFunction<A, B, Collection<Object>> indictedObjectsMapping);

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import ai.timefold.solver.core.api.score.stream.ConstraintBuilder;
import ai.timefold.solver.core.api.score.stream.ConstraintJustification;

import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.NullMarked;

/**
* Used to build a {@link Constraint} out of a {@link QuadConstraintStream}, applying optional configuration.
Expand All @@ -24,6 +24,7 @@
* Unless {@link #indictWith(QuadFunction)} is called, the default indicted objects' mapping will be used.
* The function takes the input arguments and converts them into a {@link java.util.List}.
*/
@NullMarked
public interface QuadConstraintBuilder<A, B, C, D, Score_ extends Score<Score_>> extends ConstraintBuilder {

/**
Expand All @@ -32,8 +33,8 @@ public interface QuadConstraintBuilder<A, B, C, D, Score_ extends Score<Score_>>
* @return this
* @see ConstraintMatch
*/
<ConstraintJustification_ extends ConstraintJustification> @NonNull QuadConstraintBuilder<A, B, C, D, Score_> justifyWith(
@NonNull PentaFunction<A, B, C, D, Score_, ConstraintJustification_> justificationMapping);
<ConstraintJustification_ extends ConstraintJustification> QuadConstraintBuilder<A, B, C, D, Score_> justifyWith(
PentaFunction<A, B, C, D, Score_, ConstraintJustification_> justificationMapping);

/**
* Sets a custom function to mark any object returned by it as responsible for causing the constraint to match.
Expand All @@ -42,8 +43,7 @@ public interface QuadConstraintBuilder<A, B, C, D, Score_ extends Score<Score_>>
*
* @return this
*/
@NonNull
QuadConstraintBuilder<A, B, C, D, Score_> indictWith(
@NonNull QuadFunction<A, B, C, D, Collection<Object>> indictedObjectsMapping);
QuadFunction<A, B, C, D, Collection<Object>> indictedObjectsMapping);

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import ai.timefold.solver.core.api.score.stream.ConstraintBuilder;
import ai.timefold.solver.core.api.score.stream.ConstraintJustification;

import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.NullMarked;

/**
* Used to build a {@link Constraint} out of a {@link TriConstraintStream}, applying optional configuration.
Expand All @@ -24,6 +24,7 @@
* Unless {@link #indictWith(TriFunction)} is called, the default indicted objects' mapping will be used.
* The function takes the input arguments and converts them into a {@link java.util.List}.
*/
@NullMarked
public interface TriConstraintBuilder<A, B, C, Score_ extends Score<Score_>> extends ConstraintBuilder {

/**
Expand All @@ -32,8 +33,8 @@ public interface TriConstraintBuilder<A, B, C, Score_ extends Score<Score_>> ext
* @see ConstraintMatch
* @return this
*/
<ConstraintJustification_ extends ConstraintJustification> @NonNull TriConstraintBuilder<A, B, C, Score_> justifyWith(
@NonNull QuadFunction<A, B, C, Score_, ConstraintJustification_> justificationMapping);
<ConstraintJustification_ extends ConstraintJustification> TriConstraintBuilder<A, B, C, Score_> justifyWith(
QuadFunction<A, B, C, Score_, ConstraintJustification_> justificationMapping);

/**
* Sets a custom function to mark any object returned by it as responsible for causing the constraint to match.
Expand All @@ -42,7 +43,6 @@ public interface TriConstraintBuilder<A, B, C, Score_ extends Score<Score_>> ext
*
* @return this
*/
@NonNull
TriConstraintBuilder<A, B, C, Score_> indictWith(@NonNull TriFunction<A, B, C, Collection<Object>> indictedObjectsMapping);
TriConstraintBuilder<A, B, C, Score_> indictWith(TriFunction<A, B, C, Collection<Object>> indictedObjectsMapping);

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import ai.timefold.solver.core.api.score.stream.ConstraintBuilder;
import ai.timefold.solver.core.api.score.stream.ConstraintJustification;

import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.NullMarked;

/**
* Used to build a {@link Constraint} out of a {@link UniConstraintStream}, applying optional configuration.
Expand All @@ -24,6 +24,7 @@
* Unless {@link #indictWith(Function)} is called, the default indicted objects' mapping will be used.
* The function takes the input arguments and converts them into a {@link java.util.List}.
*/
@NullMarked
public interface UniConstraintBuilder<A, Score_ extends Score<Score_>> extends ConstraintBuilder {

/**
Expand All @@ -34,8 +35,8 @@ public interface UniConstraintBuilder<A, Score_ extends Score<Score_>> extends C
* @return this
* @see ConstraintMatch
*/
<ConstraintJustification_ extends ConstraintJustification> @NonNull UniConstraintBuilder<A, Score_> justifyWith(
@NonNull BiFunction<A, Score_, ConstraintJustification_> justificationMapping);
<ConstraintJustification_ extends ConstraintJustification> UniConstraintBuilder<A, Score_> justifyWith(
BiFunction<A, Score_, ConstraintJustification_> justificationMapping);

/**
* Sets a custom function to mark any object returned by it as responsible for causing the constraint to match.
Expand All @@ -44,7 +45,6 @@ public interface UniConstraintBuilder<A, Score_ extends Score<Score_>> extends C
*
* @return this
*/
@NonNull
UniConstraintBuilder<A, Score_> indictWith(@NonNull Function<A, Collection<Object>> indictedObjectsMapping);
UniConstraintBuilder<A, Score_> indictWith(Function<A, Collection<Object>> indictedObjectsMapping);

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Function;

import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
Expand Down Expand Up @@ -57,10 +56,9 @@ public interface SolutionManager<Solution_, Score_ extends Score<Score_>> {
*
* @param <Solution_> the solution type, the class with the {@link PlanningSolution} annotation
* @param <Score_> the actual score type
* @param <ProblemId_> the ID type of a submitted problem, such as {@link Long} or {@link UUID}
*/
static <Solution_, Score_ extends Score<Score_>, ProblemId_> SolutionManager<Solution_, Score_>
create(SolverManager<Solution_, ProblemId_> solverManager) {
static <Solution_, Score_ extends Score<Score_>> SolutionManager<Solution_, Score_>
create(SolverManager<Solution_> solverManager) {
return new DefaultSolutionManager<>(solverManager);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,42 @@
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;

import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
import ai.timefold.solver.core.api.solver.change.ProblemChange;

import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.NullMarked;

/**
* Represents a {@link PlanningSolution problem} that has been submitted to solve on the {@link SolverManager}.
*
* @param <Solution_> the solution type, the class with the {@link PlanningSolution} annotation
* @param <ProblemId_> the ID type of a submitted problem, such as {@link Long} or {@link UUID}.
*/
public interface SolverJob<Solution_, ProblemId_> {
@NullMarked
public interface SolverJob<Solution_> {

/**
* @return a value given to {@link SolverManager#solve(Object, Object, Consumer)}
* or {@link SolverManager#solveAndListen(Object, Object, Consumer)}
*/
@NonNull
ProblemId_ getProblemId();
Object getProblemId();

/**
* Returns whether the {@link Solver} is scheduled to solve, actively solving or not.
* <p>
* Returns {@link SolverStatus#NOT_SOLVING} if the solver already terminated.
*
*/
@NonNull
SolverStatus getSolverStatus();

/**
* As defined by {@link #addProblemChanges(List)}, only for a single problem change.
* Prefer to submit multiple {@link ProblemChange}s at once to reduce the considerable overhead of multiple calls.
*/
@NonNull
default CompletableFuture<Void> addProblemChange(@NonNull ProblemChange<Solution_> problemChange) {
default CompletableFuture<Void> addProblemChange(ProblemChange<Solution_> problemChange) {
return addProblemChanges(Collections.singletonList(problemChange));
}

Expand All @@ -56,8 +52,7 @@ default CompletableFuture<Void> addProblemChange(@NonNull ProblemChange<Solution
* state
* @see ProblemChange Learn more about problem change semantics.
*/
@NonNull
CompletableFuture<Void> addProblemChanges(@NonNull List<ProblemChange<Solution_>> problemChangeList);
CompletableFuture<Void> addProblemChanges(List<ProblemChange<Solution_>> problemChangeList);

/**
* Terminates the solver or cancels the solver job if it hasn't (re)started yet.
Expand Down Expand Up @@ -85,7 +80,6 @@ default CompletableFuture<Void> addProblemChange(@NonNull ProblemChange<Solution
* @throws InterruptedException if the current thread was interrupted while waiting
* @throws ExecutionException if the computation threw an exception
*/
@NonNull
Solution_ getFinalBestSolution() throws InterruptedException, ExecutionException;

/**
Expand All @@ -96,7 +90,6 @@ default CompletableFuture<Void> addProblemChange(@NonNull ProblemChange<Solution
*
* @return the {@link Duration} spent solving since the last (re)start, at least 0
*/
@NonNull
Duration getSolvingDuration();

/**
Expand Down Expand Up @@ -124,7 +117,6 @@ default CompletableFuture<Void> addProblemChange(@NonNull ProblemChange<Solution
* {@link SolverManager}.
*
*/
@NonNull
ProblemSizeStatistics getProblemSizeStatistics();

/**
Expand Down
Loading
Loading