diff --git a/persistence/common/src/main/java/ai/timefold/solver/persistence/common/api/domain/solution/SolutionFileIO.java b/core/src/main/java/ai/timefold/solver/core/api/domain/solution/SolutionFileIO.java
similarity index 94%
rename from persistence/common/src/main/java/ai/timefold/solver/persistence/common/api/domain/solution/SolutionFileIO.java
rename to core/src/main/java/ai/timefold/solver/core/api/domain/solution/SolutionFileIO.java
index 0efe23fc346..453e902120f 100644
--- a/persistence/common/src/main/java/ai/timefold/solver/persistence/common/api/domain/solution/SolutionFileIO.java
+++ b/core/src/main/java/ai/timefold/solver/core/api/domain/solution/SolutionFileIO.java
@@ -1,9 +1,7 @@
-package ai.timefold.solver.persistence.common.api.domain.solution;
+package ai.timefold.solver.core.api.domain.solution;
import java.io.File;
-import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
-
/**
* Reads or writes a {@link PlanningSolution} from or to a {@link File}.
*
diff --git a/core/src/main/java/ai/timefold/solver/core/config/heuristic/selector/move/factory/MoveIteratorFactoryConfig.java b/core/src/main/java/ai/timefold/solver/core/config/heuristic/selector/move/factory/MoveIteratorFactoryConfig.java
index 77b738d3aee..636cf7ac030 100644
--- a/core/src/main/java/ai/timefold/solver/core/config/heuristic/selector/move/factory/MoveIteratorFactoryConfig.java
+++ b/core/src/main/java/ai/timefold/solver/core/config/heuristic/selector/move/factory/MoveIteratorFactoryConfig.java
@@ -9,7 +9,7 @@
import ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig;
import ai.timefold.solver.core.config.util.ConfigUtils;
import ai.timefold.solver.core.impl.heuristic.selector.move.factory.MoveIteratorFactory;
-import ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbCustomPropertiesAdapter;
+import ai.timefold.solver.core.impl.io.jaxb.JaxbCustomPropertiesAdapter;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
@@ -25,7 +25,7 @@ public class MoveIteratorFactoryConfig extends MoveSelectorConfig moveIteratorFactoryClass = null;
@XmlJavaTypeAdapter(JaxbCustomPropertiesAdapter.class)
- protected Map moveIteratorFactoryCustomProperties = null;
+ protected @Nullable Map moveIteratorFactoryCustomProperties = null;
public @Nullable Class extends MoveIteratorFactory> getMoveIteratorFactoryClass() {
return moveIteratorFactoryClass;
diff --git a/core/src/main/java/ai/timefold/solver/core/config/heuristic/selector/move/factory/MoveListFactoryConfig.java b/core/src/main/java/ai/timefold/solver/core/config/heuristic/selector/move/factory/MoveListFactoryConfig.java
index 57d6323a735..b8b4b2392de 100644
--- a/core/src/main/java/ai/timefold/solver/core/config/heuristic/selector/move/factory/MoveListFactoryConfig.java
+++ b/core/src/main/java/ai/timefold/solver/core/config/heuristic/selector/move/factory/MoveListFactoryConfig.java
@@ -9,7 +9,7 @@
import ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig;
import ai.timefold.solver.core.config.util.ConfigUtils;
import ai.timefold.solver.core.impl.heuristic.selector.move.factory.MoveListFactory;
-import ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbCustomPropertiesAdapter;
+import ai.timefold.solver.core.impl.io.jaxb.JaxbCustomPropertiesAdapter;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
diff --git a/core/src/main/java/ai/timefold/solver/core/config/partitionedsearch/PartitionedSearchPhaseConfig.java b/core/src/main/java/ai/timefold/solver/core/config/partitionedsearch/PartitionedSearchPhaseConfig.java
index c3cb27d9bb3..746f523e839 100644
--- a/core/src/main/java/ai/timefold/solver/core/config/partitionedsearch/PartitionedSearchPhaseConfig.java
+++ b/core/src/main/java/ai/timefold/solver/core/config/partitionedsearch/PartitionedSearchPhaseConfig.java
@@ -16,7 +16,7 @@
import ai.timefold.solver.core.config.phase.PhaseConfig;
import ai.timefold.solver.core.config.phase.custom.CustomPhaseConfig;
import ai.timefold.solver.core.config.util.ConfigUtils;
-import ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbCustomPropertiesAdapter;
+import ai.timefold.solver.core.impl.io.jaxb.JaxbCustomPropertiesAdapter;
import ai.timefold.solver.core.impl.partitionedsearch.partitioner.SolutionPartitioner;
import org.jspecify.annotations.NonNull;
diff --git a/core/src/main/java/ai/timefold/solver/core/config/phase/custom/CustomPhaseConfig.java b/core/src/main/java/ai/timefold/solver/core/config/phase/custom/CustomPhaseConfig.java
index a77f53d7c00..f6604a4c018 100644
--- a/core/src/main/java/ai/timefold/solver/core/config/phase/custom/CustomPhaseConfig.java
+++ b/core/src/main/java/ai/timefold/solver/core/config/phase/custom/CustomPhaseConfig.java
@@ -15,7 +15,7 @@
import ai.timefold.solver.core.api.solver.phase.PhaseCommand;
import ai.timefold.solver.core.config.phase.PhaseConfig;
import ai.timefold.solver.core.config.util.ConfigUtils;
-import ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbCustomPropertiesAdapter;
+import ai.timefold.solver.core.impl.io.jaxb.JaxbCustomPropertiesAdapter;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
diff --git a/core/src/main/java/ai/timefold/solver/core/config/score/director/ScoreDirectorFactoryConfig.java b/core/src/main/java/ai/timefold/solver/core/config/score/director/ScoreDirectorFactoryConfig.java
index 1ff051377e9..2eefc09a9d9 100644
--- a/core/src/main/java/ai/timefold/solver/core/config/score/director/ScoreDirectorFactoryConfig.java
+++ b/core/src/main/java/ai/timefold/solver/core/config/score/director/ScoreDirectorFactoryConfig.java
@@ -12,7 +12,7 @@
import ai.timefold.solver.core.api.score.stream.ConstraintProvider;
import ai.timefold.solver.core.config.AbstractConfig;
import ai.timefold.solver.core.config.util.ConfigUtils;
-import ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbCustomPropertiesAdapter;
+import ai.timefold.solver.core.impl.io.jaxb.JaxbCustomPropertiesAdapter;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
diff --git a/core/src/main/java/ai/timefold/solver/core/config/solver/termination/DiminishedReturnsTerminationConfig.java b/core/src/main/java/ai/timefold/solver/core/config/solver/termination/DiminishedReturnsTerminationConfig.java
index 06372a64596..a7d6a5dfb87 100644
--- a/core/src/main/java/ai/timefold/solver/core/config/solver/termination/DiminishedReturnsTerminationConfig.java
+++ b/core/src/main/java/ai/timefold/solver/core/config/solver/termination/DiminishedReturnsTerminationConfig.java
@@ -10,7 +10,7 @@
import ai.timefold.solver.core.config.AbstractConfig;
import ai.timefold.solver.core.config.util.ConfigUtils;
-import ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbDurationAdapter;
+import ai.timefold.solver.core.impl.io.jaxb.JaxbDurationAdapter;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
diff --git a/core/src/main/java/ai/timefold/solver/core/config/solver/termination/TerminationConfig.java b/core/src/main/java/ai/timefold/solver/core/config/solver/termination/TerminationConfig.java
index efef5f90cec..64f1418f7a2 100644
--- a/core/src/main/java/ai/timefold/solver/core/config/solver/termination/TerminationConfig.java
+++ b/core/src/main/java/ai/timefold/solver/core/config/solver/termination/TerminationConfig.java
@@ -11,7 +11,7 @@
import ai.timefold.solver.core.config.AbstractConfig;
import ai.timefold.solver.core.config.util.ConfigUtils;
-import ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbDurationAdapter;
+import ai.timefold.solver.core.impl.io.jaxb.JaxbDurationAdapter;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/GenericJaxbIO.java b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/GenericJaxbIO.java
index 7cc7ac44b08..1be600af3d9 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/GenericJaxbIO.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/GenericJaxbIO.java
@@ -43,7 +43,7 @@
import org.xml.sax.SAXNotSupportedException;
@NullMarked
-public final class GenericJaxbIO implements JaxbIO {
+public final class GenericJaxbIO {
public static DocumentBuilderFactory createDocumentBuilderFactory() {
try {
@@ -122,7 +122,6 @@ public GenericJaxbIO(Class rootClass, int indentation) {
}
}
- @Override
public T read(Reader reader) {
try {
return (T) createUnmarshaller().unmarshal(reader);
@@ -265,7 +264,6 @@ public void validate(Document document, Schema schema) {
}
}
- @Override
public void write(T root, Writer writer) {
write(root, writer, null);
}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbAdaptedMap.java b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbAdaptedMap.java
new file mode 100644
index 00000000000..527eb311616
--- /dev/null
+++ b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbAdaptedMap.java
@@ -0,0 +1,33 @@
+package ai.timefold.solver.core.impl.io.jaxb;
+
+import java.util.List;
+
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlType;
+
+import ai.timefold.solver.core.config.solver.SolverConfig;
+
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+// Required to generate the XSD type in the same namespace.
+@NullMarked
+@XmlType(namespace = SolverConfig.XML_NAMESPACE)
+public final class JaxbAdaptedMap {
+
+ @XmlElement(name = "property", namespace = SolverConfig.XML_NAMESPACE)
+ private @Nullable List entries;
+
+ public JaxbAdaptedMap() {
+ // Required by JAXB
+ }
+
+ public JaxbAdaptedMap(@Nullable List entries) {
+ this.entries = entries;
+ }
+
+ public @Nullable List getEntries() {
+ return entries;
+ }
+
+}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbAdaptedMapEntry.java b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbAdaptedMapEntry.java
new file mode 100644
index 00000000000..dab72eba045
--- /dev/null
+++ b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbAdaptedMapEntry.java
@@ -0,0 +1,37 @@
+package ai.timefold.solver.core.impl.io.jaxb;
+
+import jakarta.xml.bind.annotation.XmlAttribute;
+import jakarta.xml.bind.annotation.XmlType;
+
+import ai.timefold.solver.core.config.solver.SolverConfig;
+
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+// Required to generate the XSD type in the same namespace.
+@NullMarked
+@XmlType(namespace = SolverConfig.XML_NAMESPACE)
+public final class JaxbAdaptedMapEntry {
+
+ @XmlAttribute
+ private @Nullable String name;
+
+ @XmlAttribute
+ private @Nullable String value;
+
+ public JaxbAdaptedMapEntry() {
+ }
+
+ public JaxbAdaptedMapEntry(@Nullable String name, @Nullable String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public @Nullable String getName() {
+ return name;
+ }
+
+ public @Nullable String getValue() {
+ return value;
+ }
+}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbCustomPropertiesAdapter.java b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbCustomPropertiesAdapter.java
new file mode 100644
index 00000000000..057e83e64b2
--- /dev/null
+++ b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbCustomPropertiesAdapter.java
@@ -0,0 +1,39 @@
+package ai.timefold.solver.core.impl.io.jaxb;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import jakarta.xml.bind.annotation.adapters.XmlAdapter;
+
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+@NullMarked
+public class JaxbCustomPropertiesAdapter extends XmlAdapter> {
+
+ @Override
+ public @Nullable Map unmarshal(@Nullable JaxbAdaptedMap jaxbAdaptedMap) {
+ if (jaxbAdaptedMap == null) {
+ return null;
+ }
+ var entries = jaxbAdaptedMap.getEntries();
+ if (entries == null || entries.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ return entries.stream()
+ .collect(Collectors.toMap(JaxbAdaptedMapEntry::getName, JaxbAdaptedMapEntry::getValue));
+ }
+
+ @Override
+ public @Nullable JaxbAdaptedMap marshal(@Nullable Map originalMap) {
+ if (originalMap == null) {
+ return null;
+ }
+ var entries = originalMap.entrySet().stream()
+ .map(entry -> new JaxbAdaptedMapEntry(entry.getKey(), entry.getValue()))
+ .toList();
+ return new JaxbAdaptedMap(entries);
+ }
+
+}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbDurationAdapter.java b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbDurationAdapter.java
similarity index 59%
rename from core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbDurationAdapter.java
rename to core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbDurationAdapter.java
index 19e44ee2cfc..b8792af874b 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbDurationAdapter.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbDurationAdapter.java
@@ -1,14 +1,17 @@
-package ai.timefold.solver.core.impl.io.jaxb.adapter;
+package ai.timefold.solver.core.impl.io.jaxb;
import java.time.Duration;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
-// TODO: Move the code to the jaxb-ri
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+@NullMarked
public class JaxbDurationAdapter extends XmlAdapter {
@Override
- public Duration unmarshal(String durationString) {
+ public @Nullable Duration unmarshal(@Nullable String durationString) {
if (durationString == null) {
return null;
}
@@ -16,7 +19,7 @@ public Duration unmarshal(String durationString) {
}
@Override
- public String marshal(Duration duration) {
+ public @Nullable String marshal(@Nullable Duration duration) {
if (duration == null) {
return null;
}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbIO.java b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbIO.java
deleted file mode 100644
index 770c26dc6b4..00000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbIO.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package ai.timefold.solver.core.impl.io.jaxb;
-
-import java.io.Reader;
-import java.io.Writer;
-
-public interface JaxbIO {
-
- T read(Reader reader);
-
- void write(T root, Writer writer);
-}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbLocaleAdapter.java b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbLocaleAdapter.java
similarity index 60%
rename from core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbLocaleAdapter.java
rename to core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbLocaleAdapter.java
index 14ee2b8a0f8..20c647f257b 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbLocaleAdapter.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbLocaleAdapter.java
@@ -1,13 +1,17 @@
-package ai.timefold.solver.core.impl.io.jaxb.adapter;
+package ai.timefold.solver.core.impl.io.jaxb;
import java.util.Locale;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+@NullMarked
public class JaxbLocaleAdapter extends XmlAdapter {
@Override
- public Locale unmarshal(String localeString) {
+ public @Nullable Locale unmarshal(@Nullable String localeString) {
if (localeString == null) {
return null;
}
@@ -15,7 +19,7 @@ public Locale unmarshal(String localeString) {
}
@Override
- public String marshal(Locale locale) {
+ public @Nullable String marshal(@Nullable Locale locale) {
if (locale == null) {
return null;
}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbOffsetDateTimeAdapter.java b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbOffsetDateTimeAdapter.java
similarity index 79%
rename from core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbOffsetDateTimeAdapter.java
rename to core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbOffsetDateTimeAdapter.java
index b37424154ec..cfd62629637 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbOffsetDateTimeAdapter.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/JaxbOffsetDateTimeAdapter.java
@@ -1,4 +1,4 @@
-package ai.timefold.solver.core.impl.io.jaxb.adapter;
+package ai.timefold.solver.core.impl.io.jaxb;
import java.time.DateTimeException;
import java.time.OffsetDateTime;
@@ -8,8 +8,12 @@
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
-// TODO: Move the code to the jaxb-ri
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
+
+@NullMarked
public class JaxbOffsetDateTimeAdapter extends XmlAdapter {
+
private final DateTimeFormatter formatter;
public JaxbOffsetDateTimeAdapter() {
@@ -21,7 +25,7 @@ public JaxbOffsetDateTimeAdapter() {
}
@Override
- public OffsetDateTime unmarshal(String offsetDateTimeString) {
+ public @Nullable OffsetDateTime unmarshal(@Nullable String offsetDateTimeString) {
if (offsetDateTimeString == null) {
return null;
}
@@ -34,7 +38,7 @@ public OffsetDateTime unmarshal(String offsetDateTimeString) {
}
@Override
- public String marshal(OffsetDateTime offsetDateTimeObject) {
+ public @Nullable String marshal(@Nullable OffsetDateTime offsetDateTimeObject) {
if (offsetDateTimeObject == null) {
return null;
}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/SolverConfigIO.java b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/SolverConfigIO.java
index cb9f8a47048..f99192451e6 100644
--- a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/SolverConfigIO.java
+++ b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/SolverConfigIO.java
@@ -5,13 +5,14 @@
import ai.timefold.solver.core.config.solver.SolverConfig;
+import org.jspecify.annotations.NullMarked;
import org.w3c.dom.Document;
-public class SolverConfigIO implements JaxbIO {
+@NullMarked
+public class SolverConfigIO {
private static final String SOLVER_XSD_RESOURCE = "/solver.xsd";
private final GenericJaxbIO genericJaxbIO = new GenericJaxbIO<>(SolverConfig.class);
- @Override
public SolverConfig read(Reader reader) {
Document document = genericJaxbIO.parseXml(reader);
String rootElementNamespace = document.getDocumentElement().getNamespaceURI();
@@ -29,8 +30,8 @@ public SolverConfig read(Reader reader) {
}
}
- @Override
public void write(SolverConfig solverConfig, Writer writer) {
genericJaxbIO.writeWithoutNamespaces(solverConfig, writer);
}
+
}
diff --git a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbCustomPropertiesAdapter.java b/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbCustomPropertiesAdapter.java
deleted file mode 100644
index 0b14a37c0fe..00000000000
--- a/core/src/main/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbCustomPropertiesAdapter.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package ai.timefold.solver.core.impl.io.jaxb.adapter;
-
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import jakarta.xml.bind.annotation.XmlAttribute;
-import jakarta.xml.bind.annotation.XmlElement;
-import jakarta.xml.bind.annotation.XmlType;
-import jakarta.xml.bind.annotation.adapters.XmlAdapter;
-
-import ai.timefold.solver.core.config.solver.SolverConfig;
-
-public class JaxbCustomPropertiesAdapter extends XmlAdapter> {
-
- @Override
- public Map unmarshal(JaxbAdaptedMap jaxbAdaptedMap) {
- if (jaxbAdaptedMap == null) {
- return null;
- }
- return jaxbAdaptedMap.entries.stream()
- .collect(Collectors.toMap(JaxbAdaptedMapEntry::getName, JaxbAdaptedMapEntry::getValue));
- }
-
- @Override
- public JaxbAdaptedMap marshal(Map originalMap) {
- if (originalMap == null) {
- return null;
- }
- List entries = originalMap.entrySet().stream()
- .map(entry -> new JaxbCustomPropertiesAdapter.JaxbAdaptedMapEntry(entry.getKey(), entry.getValue()))
- .collect(Collectors.toList());
- return new JaxbAdaptedMap(entries);
- }
-
- // Required to generate the XSD type in the same namespace.
- @XmlType(namespace = SolverConfig.XML_NAMESPACE)
- static class JaxbAdaptedMap {
-
- @XmlElement(name = "property", namespace = SolverConfig.XML_NAMESPACE)
- private List entries;
-
- private JaxbAdaptedMap() {
- // Required by JAXB
- }
-
- public JaxbAdaptedMap(List entries) {
- this.entries = entries;
- }
- }
-
- // Required to generate the XSD type in the same namespace.
- @XmlType(namespace = SolverConfig.XML_NAMESPACE)
- static class JaxbAdaptedMapEntry {
-
- @XmlAttribute
- private String name;
-
- @XmlAttribute
- private String value;
-
- public JaxbAdaptedMapEntry() {
- }
-
- public JaxbAdaptedMapEntry(String name, String value) {
- this.name = name;
- this.value = value;
- }
-
- public String getName() {
- return name;
- }
-
- public String getValue() {
- return value;
- }
- }
-}
diff --git a/core/src/main/java/module-info.java b/core/src/main/java/module-info.java
new file mode 100644
index 00000000000..8456e1a9159
--- /dev/null
+++ b/core/src/main/java/module-info.java
@@ -0,0 +1,258 @@
+// Divided into categories, in which the packages are sorted alphabetically.
+module ai.timefold.solver.core {
+
+ // Public APIs
+ exports ai.timefold.solver.core.api.domain.common;
+ exports ai.timefold.solver.core.api.domain.entity;
+ exports ai.timefold.solver.core.api.domain.solution;
+ exports ai.timefold.solver.core.api.domain.solution.cloner;
+ exports ai.timefold.solver.core.api.domain.valuerange;
+ exports ai.timefold.solver.core.api.domain.variable;
+ exports ai.timefold.solver.core.api.function;
+ exports ai.timefold.solver.core.api.score;
+ exports ai.timefold.solver.core.api.score.analysis;
+ exports ai.timefold.solver.core.api.score.constraint;
+ exports ai.timefold.solver.core.api.score.stream;
+ exports ai.timefold.solver.core.api.score.stream.common;
+ exports ai.timefold.solver.core.api.score.stream.uni;
+ exports ai.timefold.solver.core.api.score.stream.bi;
+ exports ai.timefold.solver.core.api.score.stream.tri;
+ exports ai.timefold.solver.core.api.score.stream.quad;
+ exports ai.timefold.solver.core.api.score.stream.penta;
+ exports ai.timefold.solver.core.api.score.stream.test;
+ exports ai.timefold.solver.core.api.score.calculator;
+ exports ai.timefold.solver.core.api.solver;
+ exports ai.timefold.solver.core.api.solver.change;
+ exports ai.timefold.solver.core.api.solver.event;
+ exports ai.timefold.solver.core.api.solver.phase;
+
+ // Config APIs; need to be open to JAXB for XML config parsing, happens below.
+ exports ai.timefold.solver.core.config;
+ exports ai.timefold.solver.core.config.constructionheuristic;
+ exports ai.timefold.solver.core.config.constructionheuristic.decider.forager;
+ exports ai.timefold.solver.core.config.constructionheuristic.placer;
+ exports ai.timefold.solver.core.config.exhaustivesearch;
+ exports ai.timefold.solver.core.config.heuristic.selector.common;
+ exports ai.timefold.solver.core.config.heuristic.selector.common.decorator;
+ exports ai.timefold.solver.core.config.heuristic.selector.common.nearby;
+ exports ai.timefold.solver.core.config.heuristic.selector.entity;
+ exports ai.timefold.solver.core.config.heuristic.selector.entity.pillar;
+ exports ai.timefold.solver.core.config.heuristic.selector.list;
+ exports ai.timefold.solver.core.config.heuristic.selector.move;
+ exports ai.timefold.solver.core.config.heuristic.selector.move.composite;
+ exports ai.timefold.solver.core.config.heuristic.selector.move.factory;
+ exports ai.timefold.solver.core.config.heuristic.selector.move.generic;
+ exports ai.timefold.solver.core.config.heuristic.selector.move.generic.list;
+ exports ai.timefold.solver.core.config.heuristic.selector.value;
+ exports ai.timefold.solver.core.config.localsearch;
+ exports ai.timefold.solver.core.config.localsearch.decider.acceptor;
+ exports ai.timefold.solver.core.config.localsearch.decider.acceptor.stepcountinghillclimbing;
+ exports ai.timefold.solver.core.config.localsearch.decider.forager;
+ exports ai.timefold.solver.core.config.partitionedsearch;
+ exports ai.timefold.solver.core.config.phase;
+ exports ai.timefold.solver.core.config.phase.custom;
+ exports ai.timefold.solver.core.config.score.director;
+ exports ai.timefold.solver.core.config.score.trend;
+ exports ai.timefold.solver.core.config.solver;
+ exports ai.timefold.solver.core.config.solver.monitoring;
+ exports ai.timefold.solver.core.config.solver.random;
+ exports ai.timefold.solver.core.config.solver.termination;
+ exports ai.timefold.solver.core.config.util;
+ exports ai.timefold.solver.core.enterprise;
+
+ // Preview APIs
+ exports ai.timefold.solver.core.preview.api.domain.metamodel;
+ exports ai.timefold.solver.core.preview.api.domain.solution.diff;
+ exports ai.timefold.solver.core.preview.api.move;
+ exports ai.timefold.solver.core.preview.api.move.builtin;
+ exports ai.timefold.solver.core.preview.api.move.test;
+ exports ai.timefold.solver.core.preview.api.neighborhood;
+ exports ai.timefold.solver.core.preview.api.neighborhood.stream;
+ exports ai.timefold.solver.core.preview.api.neighborhood.stream.enumerating;
+ exports ai.timefold.solver.core.preview.api.neighborhood.stream.function;
+ exports ai.timefold.solver.core.preview.api.neighborhood.stream.joiner;
+ exports ai.timefold.solver.core.preview.api.neighborhood.stream.sampling;
+ exports ai.timefold.solver.core.preview.api.neighborhood.test;
+
+ // Exporting move selectors and associated code as semi-public API;
+ // people are using them for custom moves since 1.x.
+ exports ai.timefold.solver.core.impl.score.director;
+ exports ai.timefold.solver.core.impl.heuristic.selector.list;
+ exports ai.timefold.solver.core.impl.heuristic.selector.move;
+ exports ai.timefold.solver.core.impl.heuristic.selector.move.factory;
+ exports ai.timefold.solver.core.impl.heuristic.selector.move.generic;
+ exports ai.timefold.solver.core.impl.heuristic.selector.move.generic.list;
+ exports ai.timefold.solver.core.impl.heuristic.selector.move.generic.list.kopt;
+ exports ai.timefold.solver.core.impl.heuristic.selector.move.generic.list.ruin;
+
+ // explicit exports to other modules
+ exports ai.timefold.solver.core.impl.constructionheuristic.event to
+ ai.timefold.solver.jackson, ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.constructionheuristic.scope to
+ ai.timefold.solver.jackson, ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.domain.solution.cloner.gizmo
+ to ai.timefold.solver.quarkus.deployment;
+ exports ai.timefold.solver.core.impl.domain.common.accessor
+ to ai.timefold.solver.quarkus.deployment, ai.timefold.solver.quarkus;
+ exports ai.timefold.solver.core.impl.domain.common
+ to ai.timefold.solver.quarkus.deployment;
+ exports ai.timefold.solver.core.impl.domain.common.accessor.gizmo
+ to ai.timefold.solver.quarkus.deployment;
+ exports ai.timefold.solver.core.impl.domain.entity.descriptor
+ to ai.timefold.solver.jackson, ai.timefold.solver.jaxb, ai.timefold.solver.benchmark,
+ ai.timefold.solver.spring.boot.autoconfigure, ai.timefold.solver.quarkus.integration.test,
+ ai.timefold.solver.quarkus,
+ ai.timefold.solver.quarkus.jackson,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.domain.solution to ai.timefold.solver.jackson, ai.timefold.solver.quarkus.jackson,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.domain.variable.declarative
+ to ai.timefold.solver.quarkus.deployment, ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.domain.variable.descriptor
+ to ai.timefold.solver.jackson, ai.timefold.solver.jaxb, ai.timefold.solver.benchmark,
+ ai.timefold.solver.quarkus, ai.timefold.solver.quarkus.jackson,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic.move
+ to ai.timefold.solver.benchmark, ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic.selector to ai.timefold.solver.jackson, ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic.selector.common.decorator to ai.timefold.solver.quarkus.deployment,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic.selector.common.nearby
+ to ai.timefold.solver.jackson,
+ ai.timefold.solver.benchmark,
+ ai.timefold.solver.benchmark.aggregator,
+ ai.timefold.solver.spring.boot.autoconfigure, ai.timefold.solver.quarkus.deployment,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic.selector.entity to ai.timefold.solver.jackson, ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic.selector.entity.pillar
+ to ai.timefold.solver.jackson, ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic.selector.value to ai.timefold.solver.jackson, ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.localsearch.event to ai.timefold.solver.jackson, ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.localsearch.scope
+ to ai.timefold.solver.enterprise.core, ai.timefold.solver.benchmark;
+ exports ai.timefold.solver.core.impl.partitionedsearch.partitioner to ai.timefold.solver.quarkus.deployment,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.phase.event to ai.timefold.solver.jackson, ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.phase.scope to ai.timefold.solver.jackson, ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.score to ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.score.constraint to ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.score.definition
+ to ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.score.director.easy to ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.score.director.incremental to ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.score.stream to ai.timefold.solver.jackson,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.score.stream.common
+ to ai.timefold.solver.quarkus, ai.timefold.solver.spring.boot.autoconfigure;
+ exports ai.timefold.solver.core.impl.score.stream.collector
+ to ai.timefold.solver.jackson, ai.timefold.solver.quarkus.jackson,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.score.stream.test
+ to ai.timefold.solver.quarkus.deployment;
+ exports ai.timefold.solver.core.impl.score.trend
+ to ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.solver
+ to ai.timefold.solver.jackson, ai.timefold.solver.spring.boot.autoconfigure, ai.timefold.solver.benchmark,
+ ai.timefold.solver.quarkus,
+ ai.timefold.solver.quarkus.deployment, ai.timefold.solver.quarkus.integration.test,
+ ai.timefold.solver.quarkus.jackson,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.solver.monitoring to ai.timefold.solver.benchmark,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.solver.scope to
+ ai.timefold.solver.jackson, ai.timefold.solver.benchmark, ai.timefold.solver.spring.boot.autoconfigure,
+ ai.timefold.solver.quarkus.deployment, ai.timefold.solver.quarkus.integration.test,
+ ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.solver.thread
+ to ai.timefold.solver.enterprise.core, ai.timefold.solver.benchmark;
+ exports ai.timefold.solver.core.impl.util
+ to ai.timefold.solver.jackson, ai.timefold.solver.benchmark,
+ ai.timefold.solver.quarkus.deployment, ai.timefold.solver.quarkus.jackson,
+ ai.timefold.solver.enterprise.core;
+
+ // enterprise-specific exports
+ exports ai.timefold.solver.core.impl.bavet.common to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.constructionheuristic.decider to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.constructionheuristic.decider.forager to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.domain.variable to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.domain.variable.supply to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.domain.variable.listener.support to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic.selector.common to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic.selector.common.iterator to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic.selector.entity.mimic to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic.selector.list.mimic to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.heuristic.selector.value.mimic to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.localsearch.decider to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.localsearch.decider.acceptor to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.localsearch.decider.forager to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.move to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.neighborhood to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.partitionedsearch to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.phase to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.solver.recaller to ai.timefold.solver.enterprise.core;
+ exports ai.timefold.solver.core.impl.solver.event to ai.timefold.solver.enterprise.core;
+
+ // Broad impl usage
+ exports ai.timefold.solver.core.impl.io.jaxb;
+ exports ai.timefold.solver.core.impl.domain.solution.descriptor;
+ exports ai.timefold.solver.core.impl.solver.termination;
+
+ // Open configs to JAXB
+ opens ai.timefold.solver.core.impl.io.jaxb;
+ opens ai.timefold.solver.core.config to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.constructionheuristic to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.constructionheuristic.decider.forager to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.constructionheuristic.placer to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.exhaustivesearch to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.heuristic.selector.common to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.heuristic.selector.common.decorator to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.heuristic.selector.common.nearby to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.heuristic.selector.entity to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.heuristic.selector.entity.pillar to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.heuristic.selector.list to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.heuristic.selector.move to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.heuristic.selector.move.composite to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.heuristic.selector.move.factory to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.heuristic.selector.move.generic to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.heuristic.selector.move.generic.list to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.heuristic.selector.value to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.localsearch to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.localsearch.decider.acceptor to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.localsearch.decider.acceptor.stepcountinghillclimbing
+ to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.localsearch.decider.forager to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.partitionedsearch to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.phase to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.phase.custom to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.score.director to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.score.trend to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.solver to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.solver.monitoring to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.solver.random to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.solver.termination to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+ opens ai.timefold.solver.core.config.util to jakarta.xml.bind, org.glassfish.jaxb.runtime;
+
+ requires commons.math3;
+ requires jakarta.xml.bind;
+ requires java.xml;
+ requires micrometer.core;
+ requires org.jspecify;
+ requires org.slf4j;
+ requires io.quarkus.gizmo2;
+}
\ No newline at end of file
diff --git a/core/src/main/resources/solver.xsd b/core/src/main/resources/solver.xsd
index 3aff40417d8..59b1d167617 100644
--- a/core/src/main/resources/solver.xsd
+++ b/core/src/main/resources/solver.xsd
@@ -123,7 +123,7 @@
-
+
@@ -133,7 +133,7 @@
-
+
diff --git a/core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbCustomPropertiesAdapterTest.java b/core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/JaxbCustomPropertiesAdapterTest.java
similarity index 97%
rename from core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbCustomPropertiesAdapterTest.java
rename to core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/JaxbCustomPropertiesAdapterTest.java
index 69b23b4c26d..4c7670753bb 100644
--- a/core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbCustomPropertiesAdapterTest.java
+++ b/core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/JaxbCustomPropertiesAdapterTest.java
@@ -1,4 +1,4 @@
-package ai.timefold.solver.core.impl.io.jaxb.adapter;
+package ai.timefold.solver.core.impl.io.jaxb;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbDurationAdapterTest.java b/core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/JaxbDurationAdapterTest.java
similarity index 93%
rename from core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbDurationAdapterTest.java
rename to core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/JaxbDurationAdapterTest.java
index 1e9e2dd3c6f..cc88eb6c355 100644
--- a/core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbDurationAdapterTest.java
+++ b/core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/JaxbDurationAdapterTest.java
@@ -1,4 +1,4 @@
-package ai.timefold.solver.core.impl.io.jaxb.adapter;
+package ai.timefold.solver.core.impl.io.jaxb;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbOffsetDateTimeAdapterTest.java b/core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/JaxbOffsetDateTimeAdapterTest.java
similarity index 94%
rename from core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbOffsetDateTimeAdapterTest.java
rename to core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/JaxbOffsetDateTimeAdapterTest.java
index fce217f1294..0275e6bf193 100644
--- a/core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/adapter/JaxbOffsetDateTimeAdapterTest.java
+++ b/core/src/test/java/ai/timefold/solver/core/impl/io/jaxb/JaxbOffsetDateTimeAdapterTest.java
@@ -1,4 +1,4 @@
-package ai.timefold.solver.core.impl.io.jaxb.adapter;
+package ai.timefold.solver.core.impl.io.jaxb;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/docs/TODO.md b/docs/TODO.md
index 39a72b2d111..d120d2edf6c 100644
--- a/docs/TODO.md
+++ b/docs/TODO.md
@@ -42,5 +42,6 @@
- [ ] `timefold-solver-test` is no more
- [ ] `MockProblemChangeDirector` and `ConstraintVerifier` have moved.
- [ ] `MoveTester` and `NeighborhoodTester` have moved.
+- [ ] `persistence-common` module is no more, `SolutionFileIO` is now in `core`.
Remove this file when done.
\ No newline at end of file
diff --git a/docs/src/modules/ROOT/pages/using-timefold-solver/benchmarking-and-tweaking.adoc b/docs/src/modules/ROOT/pages/using-timefold-solver/benchmarking-and-tweaking.adoc
index f6bf714186f..5dfb44766ac 100644
--- a/docs/src/modules/ROOT/pages/using-timefold-solver/benchmarking-and-tweaking.adoc
+++ b/docs/src/modules/ROOT/pages/using-timefold-solver/benchmarking-and-tweaking.adoc
@@ -191,7 +191,6 @@ public interface SolutionFileIO {
}
----
-The `SolutionFileIO` interface is in the `timefold-persistence-common` jar (which is a dependency of the `timefold-solver-benchmark` jar).
There are several ways to serialize a solution.
diff --git a/persistence/common/pom.xml b/persistence/common/pom.xml
deleted file mode 100644
index b262fe4404d..00000000000
--- a/persistence/common/pom.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
- 4.0.0
-
- ai.timefold.solver
- timefold-solver-persistence-parent
- 999-SNAPSHOT
-
-
- timefold-solver-persistence-common
-
- Timefold Solver persistence common
-
- Timefold solves planning problems.
- This lightweight, embeddable planning engine implements powerful and scalable algorithms
- to optimize business resource scheduling and planning.
-
- This module contains the common persistence integration.
-
- https://solver.timefold.ai
-
-
- ai.timefold.solver.persistence.common
-
-
-
-
-
- ai.timefold.solver
- timefold-solver-core
-
-
- ai.timefold.solver
- timefold-solver-core
- test-jar
- test
-
-
-
-
-
-
- maven-dependency-plugin
-
-
-
- ai.timefold.solver:timefold-solver-core:jar
-
-
-
-
-
-
-
diff --git a/persistence/common/src/test/resources/logback-test.xml b/persistence/common/src/test/resources/logback-test.xml
deleted file mode 100644
index 53393e6deb7..00000000000
--- a/persistence/common/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
- %d{HH:mm:ss.SSS} [%-12.12t] %-5p %m%n
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/persistence/jackson/pom.xml b/persistence/jackson/pom.xml
index a7dd3904e24..0032afa7350 100644
--- a/persistence/jackson/pom.xml
+++ b/persistence/jackson/pom.xml
@@ -21,20 +21,12 @@
https://solver.timefold.ai
-
- ai.timefold.solver.jackson
-
-
ai.timefold.solver
timefold-solver-core
-
- ai.timefold.solver
- timefold-solver-persistence-common
-
ai.timefold.solver
timefold-solver-core
diff --git a/persistence/jackson/src/main/java/ai/timefold/solver/jackson/impl/domain/solution/JacksonSolutionFileIO.java b/persistence/jackson/src/main/java/ai/timefold/solver/jackson/impl/domain/solution/JacksonSolutionFileIO.java
index 6dbbc53c903..126b1aeff39 100644
--- a/persistence/jackson/src/main/java/ai/timefold/solver/jackson/impl/domain/solution/JacksonSolutionFileIO.java
+++ b/persistence/jackson/src/main/java/ai/timefold/solver/jackson/impl/domain/solution/JacksonSolutionFileIO.java
@@ -4,7 +4,7 @@
import java.io.InputStream;
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
-import ai.timefold.solver.persistence.common.api.domain.solution.SolutionFileIO;
+import ai.timefold.solver.core.api.domain.solution.SolutionFileIO;
import tools.jackson.core.JacksonException;
import tools.jackson.databind.ObjectMapper;
diff --git a/persistence/jackson/src/main/java/module-info.java b/persistence/jackson/src/main/java/module-info.java
new file mode 100644
index 00000000000..8def882aa4b
--- /dev/null
+++ b/persistence/jackson/src/main/java/module-info.java
@@ -0,0 +1,12 @@
+module ai.timefold.solver.jackson {
+ exports ai.timefold.solver.jackson.api;
+
+ provides tools.jackson.databind.JacksonModule with
+ ai.timefold.solver.jackson.api.TimefoldJacksonModule;
+
+ requires ai.timefold.solver.core;
+ requires org.jspecify;
+ requires tools.jackson.databind;
+
+ uses tools.jackson.databind.JacksonModule;
+}
\ No newline at end of file
diff --git a/persistence/jaxb/pom.xml b/persistence/jaxb/pom.xml
index 268368df565..4a7741aae4b 100644
--- a/persistence/jaxb/pom.xml
+++ b/persistence/jaxb/pom.xml
@@ -21,10 +21,6 @@
https://solver.timefold.ai
-
- ai.timefold.solver.jaxb
-
-
@@ -37,10 +33,6 @@
test-jar
test
-
- ai.timefold.solver
- timefold-solver-persistence-common
-
diff --git a/persistence/jaxb/src/main/java/ai/timefold/solver/jaxb/impl/domain/solution/JaxbSolutionFileIO.java b/persistence/jaxb/src/main/java/ai/timefold/solver/jaxb/impl/domain/solution/JaxbSolutionFileIO.java
index 756cd3eb06f..e6483260dc3 100644
--- a/persistence/jaxb/src/main/java/ai/timefold/solver/jaxb/impl/domain/solution/JaxbSolutionFileIO.java
+++ b/persistence/jaxb/src/main/java/ai/timefold/solver/jaxb/impl/domain/solution/JaxbSolutionFileIO.java
@@ -16,7 +16,7 @@
import jakarta.xml.bind.Unmarshaller;
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
-import ai.timefold.solver.persistence.common.api.domain.solution.SolutionFileIO;
+import ai.timefold.solver.core.api.domain.solution.SolutionFileIO;
/**
* @param the solution type, the class with the {@link PlanningSolution} annotation
diff --git a/persistence/jaxb/src/main/java/module-info.java b/persistence/jaxb/src/main/java/module-info.java
new file mode 100644
index 00000000000..7496205975c
--- /dev/null
+++ b/persistence/jaxb/src/main/java/module-info.java
@@ -0,0 +1,7 @@
+module ai.timefold.solver.jaxb {
+ exports ai.timefold.solver.jaxb.api.score;
+
+ requires ai.timefold.solver.core;
+ requires jakarta.xml.bind;
+
+}
\ No newline at end of file
diff --git a/persistence/jpa/pom.xml b/persistence/jpa/pom.xml
index 4851f4256fe..6979344a60f 100644
--- a/persistence/jpa/pom.xml
+++ b/persistence/jpa/pom.xml
@@ -22,7 +22,6 @@
https://solver.timefold.ai
- ai.timefold.solver.jpa
false
diff --git a/persistence/jpa/src/main/java/module-info.java b/persistence/jpa/src/main/java/module-info.java
new file mode 100644
index 00000000000..dace4a9b621
--- /dev/null
+++ b/persistence/jpa/src/main/java/module-info.java
@@ -0,0 +1,6 @@
+module ai.timefold.solver.jpa {
+ requires jakarta.persistence;
+ requires ai.timefold.solver.core;
+
+ exports ai.timefold.solver.jpa.api.score;
+}
\ No newline at end of file
diff --git a/persistence/pom.xml b/persistence/pom.xml
index e3be007b77d..d18ba0875b1 100644
--- a/persistence/pom.xml
+++ b/persistence/pom.xml
@@ -24,7 +24,6 @@
https://solver.timefold.ai
- common
jaxb
jackson
jpa
diff --git a/quarkus-integration/pom.xml b/quarkus-integration/pom.xml
index 91eec00eeec..31194accda2 100644
--- a/quarkus-integration/pom.xml
+++ b/quarkus-integration/pom.xml
@@ -40,6 +40,7 @@
maven-surefire-plugin
+ false
org.jboss.logmanager.LogManager
@@ -48,6 +49,7 @@
maven-failsafe-plugin
+ false
org.jboss.logmanager.LogManager
diff --git a/quarkus-integration/quarkus-benchmark/deployment/pom.xml b/quarkus-integration/quarkus-benchmark/deployment/pom.xml
index 1312e53f719..5b30e5dd342 100644
--- a/quarkus-integration/quarkus-benchmark/deployment/pom.xml
+++ b/quarkus-integration/quarkus-benchmark/deployment/pom.xml
@@ -13,10 +13,6 @@
Quarkus deployment module for timefold-solver-quarkus-benchmark.
https://solver.timefold.ai
-
- ai.timefold.solver.quarkus.benchmark.deployment
-
-
io.quarkus
@@ -26,10 +22,6 @@
io.quarkus
quarkus-arc-deployment
-
- io.quarkus
- quarkus-awt-deployment
-
ai.timefold.solver
timefold-solver-quarkus-deployment
diff --git a/quarkus-integration/quarkus-benchmark/deployment/src/main/java/ai/timefold/solver/benchmark/quarkus/deployment/TimefoldBenchmarkProcessor.java b/quarkus-integration/quarkus-benchmark/deployment/src/main/java/ai/timefold/solver/benchmark/quarkus/deployment/TimefoldBenchmarkProcessor.java
index 866e1bb61bb..78fa4d8b3e9 100644
--- a/quarkus-integration/quarkus-benchmark/deployment/src/main/java/ai/timefold/solver/benchmark/quarkus/deployment/TimefoldBenchmarkProcessor.java
+++ b/quarkus-integration/quarkus-benchmark/deployment/src/main/java/ai/timefold/solver/benchmark/quarkus/deployment/TimefoldBenchmarkProcessor.java
@@ -8,7 +8,7 @@
import ai.timefold.solver.benchmark.quarkus.UnavailableTimefoldBenchmarkBeanProvider;
import ai.timefold.solver.benchmark.quarkus.config.TimefoldBenchmarkRuntimeConfig;
import ai.timefold.solver.core.config.solver.SolverConfig;
-import ai.timefold.solver.quarkus.deployment.SolverConfigBuildItem;
+import ai.timefold.solver.quarkus.deployment.api.SolverConfigBuildItem;
import org.jboss.logging.Logger;
diff --git a/quarkus-integration/quarkus-benchmark/deployment/src/main/java/module-info.java b/quarkus-integration/quarkus-benchmark/deployment/src/main/java/module-info.java
new file mode 100644
index 00000000000..7bf6d12453c
--- /dev/null
+++ b/quarkus-integration/quarkus-benchmark/deployment/src/main/java/module-info.java
@@ -0,0 +1,18 @@
+module ai.timefold.solver.quarkus.benchmark.deployment {
+
+ // Friendly exports.
+ exports ai.timefold.solver.benchmark.quarkus.deployment
+ to ai.timefold.solver.enterprise.quarkus.deployment;
+
+ requires ai.timefold.solver.benchmark;
+ requires ai.timefold.solver.core;
+ requires ai.timefold.solver.quarkus.benchmark;
+ requires io.smallrye.config;
+ requires org.jboss.logging;
+ requires quarkus.arc.deployment;
+ requires quarkus.builder;
+ requires quarkus.core;
+ requires quarkus.core.deployment;
+ requires ai.timefold.solver.quarkus.deployment;
+
+}
\ No newline at end of file
diff --git a/quarkus-integration/quarkus-benchmark/integration-test/pom.xml b/quarkus-integration/quarkus-benchmark/integration-test/pom.xml
index 95f9149a053..356ebaa872a 100644
--- a/quarkus-integration/quarkus-benchmark/integration-test/pom.xml
+++ b/quarkus-integration/quarkus-benchmark/integration-test/pom.xml
@@ -15,7 +15,6 @@
https://solver.timefold.ai
- ai.timefold.solver.quarkus.benchmark
**/*
diff --git a/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/module-info.java b/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/module-info.java
new file mode 100644
index 00000000000..c69ac3a2895
--- /dev/null
+++ b/quarkus-integration/quarkus-benchmark/integration-test/src/main/java/module-info.java
@@ -0,0 +1,9 @@
+module ai.timefold.solver.quarkus.benchmark.integration.test {
+
+ requires ai.timefold.solver.core;
+ requires ai.timefold.solver.benchmark;
+ requires jakarta.inject;
+ requires jakarta.ws.rs;
+ requires org.jspecify;
+
+}
\ No newline at end of file
diff --git a/quarkus-integration/quarkus-benchmark/pom.xml b/quarkus-integration/quarkus-benchmark/pom.xml
index 50da0f8e744..abacfea5619 100644
--- a/quarkus-integration/quarkus-benchmark/pom.xml
+++ b/quarkus-integration/quarkus-benchmark/pom.xml
@@ -21,4 +21,22 @@
integration-test
+
+
+
+
+ org.eclipse.microprofile.config
+ microprofile-config-api
+ ${version.org.eclipse.microprofile.config}
+ compile
+
+
+
+
+
+ org.eclipse.microprofile.config
+ microprofile-config-api
+
+
+
diff --git a/quarkus-integration/quarkus-benchmark/runtime/pom.xml b/quarkus-integration/quarkus-benchmark/runtime/pom.xml
index 6de0a508296..512287d2c1e 100644
--- a/quarkus-integration/quarkus-benchmark/runtime/pom.xml
+++ b/quarkus-integration/quarkus-benchmark/runtime/pom.xml
@@ -14,10 +14,6 @@
Benchmark an Timefold project to power tweak the solver configuration for speed and scalability.
https://solver.timefold.ai
-
- ai.timefold.solver.quarkus.benchmark
-
-
io.quarkus
@@ -32,20 +28,9 @@
ai.timefold.solver
timefold-solver-quarkus
-
- io.quarkus
- quarkus-awt
-
-
ai.timefold.solver
timefold-solver-benchmark
-
-
- ai.timefold.solver
- timefold-solver-core
-
-
diff --git a/quarkus-integration/quarkus-benchmark/runtime/src/main/java/module-info.java b/quarkus-integration/quarkus-benchmark/runtime/src/main/java/module-info.java
new file mode 100644
index 00000000000..44f17277ff4
--- /dev/null
+++ b/quarkus-integration/quarkus-benchmark/runtime/src/main/java/module-info.java
@@ -0,0 +1,16 @@
+module ai.timefold.solver.quarkus.benchmark {
+
+ exports ai.timefold.solver.benchmark.quarkus;
+ exports ai.timefold.solver.benchmark.quarkus.config;
+
+ requires ai.timefold.solver.benchmark;
+ requires ai.timefold.solver.core;
+ requires ai.timefold.solver.quarkus;
+ requires arc;
+ requires io.smallrye.config;
+ requires jakarta.cdi;
+ requires jakarta.inject;
+ requires org.eclipse.microprofile.config;
+ requires quarkus.core;
+
+}
\ No newline at end of file
diff --git a/quarkus-integration/quarkus-jackson/deployment/pom.xml b/quarkus-integration/quarkus-jackson/deployment/pom.xml
index 3fdb8d8f8e9..35a86130262 100644
--- a/quarkus-integration/quarkus-jackson/deployment/pom.xml
+++ b/quarkus-integration/quarkus-jackson/deployment/pom.xml
@@ -14,10 +14,6 @@
Quarkus deployment module for timefold-solver-quarkus-jackson.
https://solver.timefold.ai
-
- ai.timefold.solver.quarkus.jackson.deployment
-
-
io.quarkus
diff --git a/quarkus-integration/quarkus-jackson/deployment/src/main/java/module-info.java b/quarkus-integration/quarkus-jackson/deployment/src/main/java/module-info.java
new file mode 100644
index 00000000000..ed0cae68dd9
--- /dev/null
+++ b/quarkus-integration/quarkus-jackson/deployment/src/main/java/module-info.java
@@ -0,0 +1,6 @@
+module ai.timefold.solver.quarkus.jackson.deployment {
+ requires quarkus.core.deployment;
+ requires quarkus.jackson.spi;
+ requires ai.timefold.solver.quarkus.jackson;
+ requires quarkus.core;
+}
\ No newline at end of file
diff --git a/quarkus-integration/quarkus-jackson/integration-test/pom.xml b/quarkus-integration/quarkus-jackson/integration-test/pom.xml
index 58e79808289..8aa386bb97b 100644
--- a/quarkus-integration/quarkus-jackson/integration-test/pom.xml
+++ b/quarkus-integration/quarkus-jackson/integration-test/pom.xml
@@ -15,7 +15,6 @@
https://solver.timefold.ai
- ai.timefold.solver.quarkus.jackson.integrationtest
**/*
diff --git a/quarkus-integration/quarkus-jackson/integration-test/src/main/java/module-info.java b/quarkus-integration/quarkus-jackson/integration-test/src/main/java/module-info.java
new file mode 100644
index 00000000000..90b8883a924
--- /dev/null
+++ b/quarkus-integration/quarkus-jackson/integration-test/src/main/java/module-info.java
@@ -0,0 +1,6 @@
+module ai.timefold.solver.quarkus.jackson.integration.test {
+ requires ai.timefold.solver.core;
+ requires jakarta.inject;
+ requires jakarta.ws.rs;
+ requires org.jspecify;
+}
\ No newline at end of file
diff --git a/quarkus-integration/quarkus-jackson/runtime/pom.xml b/quarkus-integration/quarkus-jackson/runtime/pom.xml
index cce3fe39366..b26078f9fb5 100644
--- a/quarkus-integration/quarkus-jackson/runtime/pom.xml
+++ b/quarkus-integration/quarkus-jackson/runtime/pom.xml
@@ -14,10 +14,6 @@
Activate Jackson bindings for Timefold's Score classes
https://solver.timefold.ai
-
- ai.timefold.solver.quarkus.jackson
-
-
@@ -30,10 +26,6 @@
test-jar
test
-
- ai.timefold.solver
- timefold-solver-persistence-common
-
io.quarkus
diff --git a/quarkus-integration/quarkus-jackson/runtime/src/main/java/ai/timefold/solver/quarkus/jackson/solution/JacksonSolutionFileIO.java b/quarkus-integration/quarkus-jackson/runtime/src/main/java/ai/timefold/solver/quarkus/jackson/solution/JacksonSolutionFileIO.java
index 7e208c80d1e..c502b0ed70a 100644
--- a/quarkus-integration/quarkus-jackson/runtime/src/main/java/ai/timefold/solver/quarkus/jackson/solution/JacksonSolutionFileIO.java
+++ b/quarkus-integration/quarkus-jackson/runtime/src/main/java/ai/timefold/solver/quarkus/jackson/solution/JacksonSolutionFileIO.java
@@ -5,7 +5,7 @@
import java.io.InputStream;
import ai.timefold.solver.core.api.domain.solution.PlanningSolution;
-import ai.timefold.solver.persistence.common.api.domain.solution.SolutionFileIO;
+import ai.timefold.solver.core.api.domain.solution.SolutionFileIO;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
diff --git a/quarkus-integration/quarkus-jackson/runtime/src/main/java/module-info.java b/quarkus-integration/quarkus-jackson/runtime/src/main/java/module-info.java
new file mode 100644
index 00000000000..6e3cb6592dd
--- /dev/null
+++ b/quarkus-integration/quarkus-jackson/runtime/src/main/java/module-info.java
@@ -0,0 +1,7 @@
+module ai.timefold.solver.quarkus.jackson {
+ exports ai.timefold.solver.quarkus.jackson;
+
+ requires ai.timefold.solver.core;
+ requires com.fasterxml.jackson.databind;
+ requires org.jspecify;
+}
\ No newline at end of file
diff --git a/quarkus-integration/quarkus/deployment/pom.xml b/quarkus-integration/quarkus/deployment/pom.xml
index e77ade56f95..f02a9e7e0c1 100644
--- a/quarkus-integration/quarkus/deployment/pom.xml
+++ b/quarkus-integration/quarkus/deployment/pom.xml
@@ -14,10 +14,6 @@
Quarkus deployment module for timefold-solver-quarkus.
https://solver.timefold.ai
-
- ai.timefold.solver.quarkus.deployment
-
-
io.quarkus
diff --git a/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/GeneratedGizmoClasses.java b/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/GeneratedGizmoClasses.java
deleted file mode 100644
index 71f468c8901..00000000000
--- a/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/GeneratedGizmoClasses.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package ai.timefold.solver.quarkus.deployment;
-
-import java.util.Set;
-
-public class GeneratedGizmoClasses {
- Set generatedGizmoMemberAccessorClassSet;
- Set generatedGizmoSolutionClonerClassSet;
-
- public GeneratedGizmoClasses(Set generatedGizmoMemberAccessorClassSet,
- Set generatedGizmoSolutionClonerClassSet) {
- this.generatedGizmoMemberAccessorClassSet = generatedGizmoMemberAccessorClassSet;
- this.generatedGizmoSolutionClonerClassSet = generatedGizmoSolutionClonerClassSet;
- }
-}
diff --git a/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/TimefoldProcessor.java b/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/TimefoldProcessor.java
index e2fa1df722d..89756aed1f0 100644
--- a/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/TimefoldProcessor.java
+++ b/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/TimefoldProcessor.java
@@ -52,6 +52,8 @@
import ai.timefold.solver.quarkus.bean.UnavailableTimefoldBeanProvider;
import ai.timefold.solver.quarkus.config.TimefoldRuntimeConfig;
import ai.timefold.solver.quarkus.deployment.api.ConstraintMetaModelBuildItem;
+import ai.timefold.solver.quarkus.deployment.api.GeneratedGizmoClasses;
+import ai.timefold.solver.quarkus.deployment.api.SolverConfigBuildItem;
import ai.timefold.solver.quarkus.deployment.config.SolverBuildTimeConfig;
import ai.timefold.solver.quarkus.deployment.config.TimefoldBuildTimeConfig;
import ai.timefold.solver.quarkus.devui.DevUISolverConfig;
@@ -636,10 +638,10 @@ void recordAndRegisterRuntimeBeans(TimefoldRecorder recorder, RecorderContext re
.supplier(recorder.solverConfigSupplier(key, value,
GizmoMemberAccessorEntityEnhancer.getGeneratedGizmoMemberAccessorMap(recorderContext,
solverConfigBuildItem
- .getGeneratedGizmoClasses().generatedGizmoMemberAccessorClassSet),
+ .getGeneratedGizmoClasses().memberAccessorClassSet()),
GizmoMemberAccessorEntityEnhancer.getGeneratedSolutionClonerMap(recorderContext,
solverConfigBuildItem
- .getGeneratedGizmoClasses().generatedGizmoSolutionClonerClassSet)))
+ .getGeneratedGizmoClasses().solutionClonerClassSet())))
.setRuntimeInit()
.defaultBean()
.done());
@@ -664,10 +666,10 @@ void recordAndRegisterRuntimeBeans(TimefoldRecorder recorder, RecorderContext re
.supplier(recorder.solverManager(key, value,
GizmoMemberAccessorEntityEnhancer.getGeneratedGizmoMemberAccessorMap(recorderContext,
solverConfigBuildItem
- .getGeneratedGizmoClasses().generatedGizmoMemberAccessorClassSet),
+ .getGeneratedGizmoClasses().memberAccessorClassSet()),
GizmoMemberAccessorEntityEnhancer.getGeneratedSolutionClonerMap(recorderContext,
solverConfigBuildItem
- .getGeneratedGizmoClasses().generatedGizmoSolutionClonerClassSet)))
+ .getGeneratedGizmoClasses().solutionClonerClassSet())))
.setRuntimeInit()
.named(key)
.done());
@@ -699,10 +701,10 @@ public void recordAndRegisterDevUIBean(
.supplier(devUIRecorder.solverConfigSupplier(solverConfigBuildItem.getSolverConfigMap(),
GizmoMemberAccessorEntityEnhancer.getGeneratedGizmoMemberAccessorMap(recorderContext,
solverConfigBuildItem
- .getGeneratedGizmoClasses().generatedGizmoMemberAccessorClassSet),
+ .getGeneratedGizmoClasses().memberAccessorClassSet()),
GizmoMemberAccessorEntityEnhancer.getGeneratedSolutionClonerMap(recorderContext,
solverConfigBuildItem
- .getGeneratedGizmoClasses().generatedGizmoSolutionClonerClassSet)))
+ .getGeneratedGizmoClasses().solutionClonerClassSet())))
.defaultBean()
.setRuntimeInit()
.done());
diff --git a/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/api/ConstraintMetaModelBuildItem.java b/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/api/ConstraintMetaModelBuildItem.java
index dc3a060db64..9bd36f353ae 100644
--- a/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/api/ConstraintMetaModelBuildItem.java
+++ b/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/api/ConstraintMetaModelBuildItem.java
@@ -7,8 +7,7 @@
import io.quarkus.builder.item.SimpleBuildItem;
/**
- * Represents a {@link ai.timefold.solver.core.api.score.stream.ConstraintMetaModel} at the build time for the purpose
- * of Quarkus augmentation.
+ * Represents a {@link ConstraintMetaModel} at the build time for the purpose of Quarkus augmentation.
*/
public final class ConstraintMetaModelBuildItem extends SimpleBuildItem {
diff --git a/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/api/GeneratedGizmoClasses.java b/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/api/GeneratedGizmoClasses.java
new file mode 100644
index 00000000000..64ab926ad99
--- /dev/null
+++ b/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/api/GeneratedGizmoClasses.java
@@ -0,0 +1,12 @@
+package ai.timefold.solver.quarkus.deployment.api;
+
+import java.util.Set;
+
+public record GeneratedGizmoClasses(Set memberAccessorClassSet, Set solutionClonerClassSet) {
+
+ public GeneratedGizmoClasses {
+ memberAccessorClassSet = Set.copyOf(memberAccessorClassSet);
+ solutionClonerClassSet = Set.copyOf(solutionClonerClassSet);
+ }
+
+}
diff --git a/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/SolverConfigBuildItem.java b/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/api/SolverConfigBuildItem.java
similarity index 95%
rename from quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/SolverConfigBuildItem.java
rename to quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/api/SolverConfigBuildItem.java
index 83296258982..388f6199909 100644
--- a/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/SolverConfigBuildItem.java
+++ b/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/api/SolverConfigBuildItem.java
@@ -1,4 +1,4 @@
-package ai.timefold.solver.quarkus.deployment;
+package ai.timefold.solver.quarkus.deployment.api;
import java.util.Map;
diff --git a/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/config/SolverBuildTimeConfig.java b/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/config/SolverBuildTimeConfig.java
index 1984e2fbf2a..a4c4b628494 100644
--- a/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/config/SolverBuildTimeConfig.java
+++ b/quarkus-integration/quarkus/deployment/src/main/java/ai/timefold/solver/quarkus/deployment/config/SolverBuildTimeConfig.java
@@ -3,6 +3,7 @@
import java.util.Optional;
import java.util.Set;
+import ai.timefold.solver.core.api.score.stream.ConstraintProvider;
import ai.timefold.solver.core.config.solver.PreviewFeature;
import ai.timefold.solver.core.config.solver.SolverConfig;
import ai.timefold.solver.quarkus.config.SolverRuntimeConfig;
@@ -28,6 +29,10 @@ public interface SolverBuildTimeConfig {
/**
* Enable the Nearby Selection quick configuration.
+ *
+ * Note: this setting is only available
+ * for Timefold Solver
+ * Enterprise Edition.
*/
// Build time - visited by SolverConfig.visitReferencedClasses
// which generates the constructor used by Quarkus
@@ -42,18 +47,23 @@ public interface SolverBuildTimeConfig {
/**
* If constraint profiling is enabled. Defaults to false.
+ *
+ * Note: this setting is only available
+ * for Timefold Solver
+ * Enterprise Edition.
*/
Optional constraintStreamProfilingEnabled();
/**
- * Note: this setting is only available
- * for Timefold Solver
- * Enterprise Edition.
- * Enable rewriting the {@link ai.timefold.solver.core.api.score.stream.ConstraintProvider} class
+ * Enable rewriting the {@link ConstraintProvider} class
* so nodes share lambdas when possible, improving performance.
- * When enabled, breakpoints placed in the {@link ai.timefold.solver.core.api.score.stream.ConstraintProvider}
+ * When enabled, breakpoints placed in the {@link ConstraintProvider}
* will no longer be triggered.
* Defaults to "false".
+ *
+ * Note: this setting is only available
+ * for Timefold Solver
+ * Enterprise Edition.
*/
// Build time - modifies the ConstraintProvider class if set
Optional constraintStreamAutomaticNodeSharing();
diff --git a/quarkus-integration/quarkus/deployment/src/main/java/module-info.java b/quarkus-integration/quarkus/deployment/src/main/java/module-info.java
new file mode 100644
index 00000000000..3a94ef46bd3
--- /dev/null
+++ b/quarkus-integration/quarkus/deployment/src/main/java/module-info.java
@@ -0,0 +1,30 @@
+module ai.timefold.solver.quarkus.deployment {
+
+ // Friendly exports.
+ exports ai.timefold.solver.quarkus.deployment
+ to ai.timefold.solver.enterprise.quarkus.deployment;
+ exports ai.timefold.solver.quarkus.deployment.config
+ to ai.timefold.solver.enterprise.quarkus.deployment;
+ exports ai.timefold.solver.quarkus.deployment.api
+ to ai.timefold.solver.enterprise.quarkus.deployment,
+ ai.timefold.solver.quarkus.benchmark.deployment,
+ ai.timefold.sdk.quarkus.deployment;
+
+ requires ai.timefold.solver.quarkus;
+ requires quarkus.arc.deployment;
+ requires quarkus.builder;
+ requires quarkus.core.deployment;
+ requires quarkus.devui.deployment.spi;
+ requires ai.timefold.solver.core;
+ requires io.quarkus.gizmo2;
+ requires jakarta.cdi;
+ requires quarkus.core;
+ requires arc.processor;
+ requires org.jspecify;
+ requires io.quarkus.gizmo;
+ requires org.jboss.jandex;
+ requires io.smallrye.config;
+ requires org.objectweb.asm;
+ requires org.jboss.logging;
+
+}
\ No newline at end of file
diff --git a/quarkus-integration/quarkus/devui-integration-test/pom.xml b/quarkus-integration/quarkus/devui-integration-test/pom.xml
index 84dd9156189..641fc019e83 100644
--- a/quarkus-integration/quarkus/devui-integration-test/pom.xml
+++ b/quarkus-integration/quarkus/devui-integration-test/pom.xml
@@ -15,7 +15,6 @@
https://solver.timefold.ai
- ai.timefold.solver.quarkus
**/*
diff --git a/quarkus-integration/quarkus/devui-integration-test/src/main/java/module-info.java b/quarkus-integration/quarkus/devui-integration-test/src/main/java/module-info.java
new file mode 100644
index 00000000000..49e9c0433a2
--- /dev/null
+++ b/quarkus-integration/quarkus/devui-integration-test/src/main/java/module-info.java
@@ -0,0 +1,4 @@
+module ai.timefold.solver.quarkus.devui.integration.test {
+ requires ai.timefold.solver.core;
+ requires org.jspecify;
+}
\ No newline at end of file
diff --git a/quarkus-integration/quarkus/integration-test/pom.xml b/quarkus-integration/quarkus/integration-test/pom.xml
index 8fba7489238..dead8201847 100644
--- a/quarkus-integration/quarkus/integration-test/pom.xml
+++ b/quarkus-integration/quarkus/integration-test/pom.xml
@@ -15,7 +15,6 @@
https://solver.timefold.ai
- ai.timefold.solver.quarkus
**/*
diff --git a/quarkus-integration/quarkus/integration-test/src/main/java/module-info.java b/quarkus-integration/quarkus/integration-test/src/main/java/module-info.java
new file mode 100644
index 00000000000..a123ebdef78
--- /dev/null
+++ b/quarkus-integration/quarkus/integration-test/src/main/java/module-info.java
@@ -0,0 +1,6 @@
+module ai.timefold.solver.quarkus.integration.test {
+ requires ai.timefold.solver.core;
+ requires jakarta.inject;
+ requires jakarta.ws.rs;
+ requires org.jspecify;
+}
\ No newline at end of file
diff --git a/quarkus-integration/quarkus/pom.xml b/quarkus-integration/quarkus/pom.xml
index 8d18f218942..8a918ba56f7 100644
--- a/quarkus-integration/quarkus/pom.xml
+++ b/quarkus-integration/quarkus/pom.xml
@@ -22,4 +22,22 @@
reflection-integration-test
devui-integration-test
+
+
+
+
+
+ org.eclipse.microprofile.config
+ microprofile-config-api
+ ${version.org.eclipse.microprofile.config}
+ compile
+
+
+
+
+
+ org.eclipse.microprofile.config
+ microprofile-config-api
+
+
diff --git a/quarkus-integration/quarkus/reflection-integration-test/pom.xml b/quarkus-integration/quarkus/reflection-integration-test/pom.xml
index 2dcf6fc81ba..ba56b300fc3 100644
--- a/quarkus-integration/quarkus/reflection-integration-test/pom.xml
+++ b/quarkus-integration/quarkus/reflection-integration-test/pom.xml
@@ -15,7 +15,6 @@
https://solver.timefold.ai
- ai.timefold.solver.quarkus
**/*
diff --git a/quarkus-integration/quarkus/reflection-integration-test/src/main/java/module-info.java b/quarkus-integration/quarkus/reflection-integration-test/src/main/java/module-info.java
new file mode 100644
index 00000000000..61acd4909bf
--- /dev/null
+++ b/quarkus-integration/quarkus/reflection-integration-test/src/main/java/module-info.java
@@ -0,0 +1,6 @@
+module ai.timefold.solver.quarkus.reflection.integration.test {
+ requires ai.timefold.solver.core;
+ requires jakarta.inject;
+ requires jakarta.ws.rs;
+ requires org.jspecify;
+}
\ No newline at end of file
diff --git a/quarkus-integration/quarkus/runtime/pom.xml b/quarkus-integration/quarkus/runtime/pom.xml
index 845f1a0867d..67764b7c1cc 100644
--- a/quarkus-integration/quarkus/runtime/pom.xml
+++ b/quarkus-integration/quarkus/runtime/pom.xml
@@ -14,10 +14,6 @@
Solve planning and scheduling with AI constraint optimization of vehicle routes, employee rosters, maintenance, tasks, lessons, conferences, ...
https://solver.timefold.ai
-
- ai.timefold.solver.quarkus
-
-
io.quarkus
diff --git a/quarkus-integration/quarkus/runtime/src/main/java/module-info.java b/quarkus-integration/quarkus/runtime/src/main/java/module-info.java
new file mode 100644
index 00000000000..16ada9da6fa
--- /dev/null
+++ b/quarkus-integration/quarkus/runtime/src/main/java/module-info.java
@@ -0,0 +1,21 @@
+module ai.timefold.solver.quarkus {
+
+ exports ai.timefold.solver.quarkus.bean;
+ exports ai.timefold.solver.quarkus;
+ exports ai.timefold.solver.quarkus.config;
+ exports ai.timefold.solver.quarkus.devui;
+ exports ai.timefold.solver.quarkus.gizmo;
+
+ requires ai.timefold.solver.core;
+ requires arc;
+ requires io.vertx.core;
+ requires jakarta.cdi;
+ requires jakarta.inject;
+ requires org.graalvm.nativeimage;
+ requires org.jspecify;
+ requires quarkus.core;
+ requires io.smallrye.config;
+ requires org.jboss.logging;
+ requires org.eclipse.microprofile.config;
+
+}
\ No newline at end of file
diff --git a/spring-integration/spring-boot-autoconfigure/pom.xml b/spring-integration/spring-boot-autoconfigure/pom.xml
index 5df558d5a40..a90838c3e3f 100644
--- a/spring-integration/spring-boot-autoconfigure/pom.xml
+++ b/spring-integration/spring-boot-autoconfigure/pom.xml
@@ -21,10 +21,6 @@
https://solver.timefold.ai
-
- ai.timefold.solver.spring.boot.autoconfigure
-
-
diff --git a/spring-integration/spring-boot-autoconfigure/src/main/java/module-info.java b/spring-integration/spring-boot-autoconfigure/src/main/java/module-info.java
new file mode 100644
index 00000000000..fea246c2072
--- /dev/null
+++ b/spring-integration/spring-boot-autoconfigure/src/main/java/module-info.java
@@ -0,0 +1,14 @@
+module ai.timefold.solver.spring.boot.autoconfigure {
+ requires ai.timefold.solver.jackson;
+ requires org.apache.commons.logging;
+ requires spring.beans;
+ requires spring.boot;
+ requires spring.boot.autoconfigure;
+ requires spring.boot.persistence;
+ requires spring.context;
+ requires spring.core;
+ requires tools.jackson.databind;
+ requires ai.timefold.solver.benchmark;
+ requires ai.timefold.solver.core;
+ requires org.jspecify;
+}
\ No newline at end of file
diff --git a/spring-integration/spring-boot-autoconfigure/src/main/resources/META-INF/native-image/ai.timefold.solver/timefold-solver-spring-boot-autoconfigure/reflect-config.json b/spring-integration/spring-boot-autoconfigure/src/main/resources/META-INF/native-image/ai.timefold.solver/timefold-solver-spring-boot-autoconfigure/reflect-config.json
index 7a0ac997a10..9d7eda704c9 100644
--- a/spring-integration/spring-boot-autoconfigure/src/main/resources/META-INF/native-image/ai.timefold.solver/timefold-solver-spring-boot-autoconfigure/reflect-config.json
+++ b/spring-integration/spring-boot-autoconfigure/src/main/resources/META-INF/native-image/ai.timefold.solver/timefold-solver-spring-boot-autoconfigure/reflect-config.json
@@ -9,7 +9,7 @@
]
},
{
- "name": "ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbCustomPropertiesAdapter",
+ "name": "ai.timefold.solver.core.impl.io.jaxb.JaxbCustomPropertiesAdapter",
"methods": [
{
"name": "",
@@ -18,7 +18,9 @@
]
},
{
- "name": "ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbDurationAdapter",
+ "name": "ai.timefold.solver.core.impl.io.jaxb.JaxbAdaptedMap",
+ "allDeclaredFields": true,
+ "queryAllDeclaredMethods": true,
"methods": [
{
"name": "",
@@ -27,7 +29,9 @@
]
},
{
- "name": "ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbLocaleAdapter",
+ "name": "ai.timefold.solver.core.impl.io.jaxb.JaxbAdaptedMapEntry",
+ "allDeclaredFields": true,
+ "queryAllDeclaredMethods": true,
"methods": [
{
"name": "",
@@ -36,7 +40,7 @@
]
},
{
- "name": "ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbOffsetDateTimeAdapter",
+ "name": "ai.timefold.solver.core.impl.io.jaxb.JaxbDurationAdapter",
"methods": [
{
"name": "",
@@ -45,12 +49,22 @@
]
},
{
- "name": "ai.timefold.solver.core.api.domain.common.DomainAccessType",
- "allDeclaredFields": true
+ "name": "ai.timefold.solver.core.impl.io.jaxb.JaxbLocaleAdapter",
+ "methods": [
+ {
+ "name": "",
+ "parameterTypes": []
+ }
+ ]
},
{
- "name": "ai.timefold.solver.core.api.score.stream.ConstraintStreamImplType",
- "allDeclaredFields": true
+ "name": "ai.timefold.solver.core.impl.io.jaxb.JaxbOffsetDateTimeAdapter",
+ "methods": [
+ {
+ "name": "",
+ "parameterTypes": []
+ }
+ ]
},
{
"name": "ai.timefold.solver.core.config.AbstractConfig",
@@ -625,37 +639,6 @@
}
]
},
- {
- "name": "ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbCustomPropertiesAdapter",
- "methods": [
- {
- "name": "",
- "parameterTypes": []
- }
- ]
- },
- {
- "name": "ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbCustomPropertiesAdapter$JaxbAdaptedMap",
- "allDeclaredFields": true,
- "queryAllDeclaredMethods": true,
- "methods": [
- {
- "name": "",
- "parameterTypes": []
- }
- ]
- },
- {
- "name": "ai.timefold.solver.core.impl.io.jaxb.adapter.JaxbCustomPropertiesAdapter$JaxbAdaptedMapEntry",
- "allDeclaredFields": true,
- "queryAllDeclaredMethods": true,
- "methods": [
- {
- "name": "",
- "parameterTypes": []
- }
- ]
- },
{
"name": "jakarta.xml.bind.Binder"
},
diff --git a/spring-integration/spring-boot-integration-test/pom.xml b/spring-integration/spring-boot-integration-test/pom.xml
index 0c59f978fc3..2b946fde7c7 100644
--- a/spring-integration/spring-boot-integration-test/pom.xml
+++ b/spring-integration/spring-boot-integration-test/pom.xml
@@ -15,7 +15,6 @@
Spring Boot integration tests for Timefold
- ai.timefold.solver.spring.boot
**/*
1.12.1
@@ -110,9 +109,6 @@
test