ModelInputMetric class of the model
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ModelConfigParameter.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ModelConfigParameter.java
index 25f31e185b3..f54e74d5652 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ModelConfigParameter.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ModelConfigParameter.java
@@ -1,7 +1,7 @@
package ai.timefold.solver.service.definition.internal.descriptor;
-import ai.timefold.solver.service.definition.api.ModelConfigOverrides;
-import ai.timefold.solver.service.definition.api.domain.DataFormat;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelConfigOverrides;
+import ai.timefold.solver.service.definition.api.metrics.DataFormat;
import org.eclipse.microprofile.openapi.models.media.Schema.SchemaType;
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/ModelDescriptor.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ModelDescriptor.java
similarity index 93%
rename from service/definition/src/main/java/ai/timefold/solver/service/definition/api/ModelDescriptor.java
rename to service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ModelDescriptor.java
index 7b4875ccf4b..e3df8b4766d 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/ModelDescriptor.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ModelDescriptor.java
@@ -1,16 +1,10 @@
-package ai.timefold.solver.service.definition.api;
+package ai.timefold.solver.service.definition.internal.descriptor;
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import ai.timefold.solver.service.definition.internal.descriptor.ConstraintGroupDescriptor;
-import ai.timefold.solver.service.definition.internal.descriptor.DocumentationDescriptor;
-import ai.timefold.solver.service.definition.internal.descriptor.InputMetricDescriptor;
-import ai.timefold.solver.service.definition.internal.descriptor.ModelConfigDescriptor;
-import ai.timefold.solver.service.definition.internal.descriptor.OutputMetricDescriptor;
-import ai.timefold.solver.service.definition.internal.descriptor.UISupport;
-import ai.timefold.solver.service.definition.internal.descriptor.VisualizationPageDescriptor;
+import ai.timefold.solver.service.definition.api.description.ModelMaturityLevel;
import ai.timefold.solver.service.definition.internal.descriptor.usage.UniqueResource;
public class ModelDescriptor {
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/OutputMetricDescriptor.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/OutputMetricDescriptor.java
index d1f14fbd4fb..ecec2bf06b5 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/OutputMetricDescriptor.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/OutputMetricDescriptor.java
@@ -1,6 +1,6 @@
package ai.timefold.solver.service.definition.internal.descriptor;
-import ai.timefold.solver.service.definition.api.domain.DataFormat;
+import ai.timefold.solver.service.definition.api.metrics.DataFormat;
/**
* Defines Output Metric of the model where information is retrieved from ModelOutputMetrics class of the model
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ResourceType.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ResourceType.java
new file mode 100644
index 00000000000..87c60212372
--- /dev/null
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/ResourceType.java
@@ -0,0 +1,4 @@
+package ai.timefold.solver.service.definition.internal.descriptor;
+
+public record ResourceType(String value) {
+}
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/Resources.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/Resources.java
similarity index 61%
rename from service/definition/src/main/java/ai/timefold/solver/service/definition/api/Resources.java
rename to service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/Resources.java
index c8c1e605aa1..1e5a4c9901c 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/Resources.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/Resources.java
@@ -1,4 +1,4 @@
-package ai.timefold.solver.service.definition.api;
+package ai.timefold.solver.service.definition.internal.descriptor;
public record Resources(String memoryRequest, String memoryLimit, String cpuRequest, String cpuLimit) {
}
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/TrialConfig.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/TrialConfig.java
similarity index 86%
rename from service/definition/src/main/java/ai/timefold/solver/service/definition/api/TrialConfig.java
rename to service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/TrialConfig.java
index 73447423a6d..d721a4e1a3c 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/TrialConfig.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/descriptor/TrialConfig.java
@@ -1,4 +1,4 @@
-package ai.timefold.solver.service.definition.api;
+package ai.timefold.solver.service.definition.internal.descriptor;
/**
* Configuration of trial use of the model
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/AbstractDatasetEvent.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/AbstractDatasetEvent.java
index 0eb0546c21b..6b60a74a63e 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/AbstractDatasetEvent.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/AbstractDatasetEvent.java
@@ -1,6 +1,6 @@
package ai.timefold.solver.service.definition.internal.events;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
/**
* Event referencing the associated {@link Metadata}.
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/BestSolutionEvent.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/BestSolutionEvent.java
index 216542ecfdc..bbe8aaa9390 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/BestSolutionEvent.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/BestSolutionEvent.java
@@ -2,7 +2,7 @@
import ai.timefold.solver.core.api.solver.SolverJob;
import ai.timefold.solver.service.definition.api.SolverModel;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
/**
* This event is sent when a new best solution is found during the solving process.
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/DatasetComputedEvent.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/DatasetComputedEvent.java
index 1a6537ca041..4473943a1bc 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/DatasetComputedEvent.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/DatasetComputedEvent.java
@@ -1,7 +1,7 @@
package ai.timefold.solver.service.definition.internal.events;
import ai.timefold.solver.service.definition.api.SolverModel;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
/**
* Event sent when the outputs of a dataset are computed before solving.
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/DatasetCreatedEvent.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/DatasetCreatedEvent.java
index 161e1b5be53..973e38b4c90 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/DatasetCreatedEvent.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/DatasetCreatedEvent.java
@@ -1,6 +1,6 @@
package ai.timefold.solver.service.definition.internal.events;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
/**
* Event that a new dataset is submitted via the API.
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/DatasetValidatedEvent.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/DatasetValidatedEvent.java
index 2bf3c5603d1..4a635878063 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/DatasetValidatedEvent.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/DatasetValidatedEvent.java
@@ -1,6 +1,6 @@
package ai.timefold.solver.service.definition.internal.events;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
import ai.timefold.solver.service.definition.api.validation.ModelValidator;
/**
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/FailedSolutionEvent.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/FailedSolutionEvent.java
index 12ccb6aafd6..b4990a64599 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/FailedSolutionEvent.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/FailedSolutionEvent.java
@@ -1,7 +1,7 @@
package ai.timefold.solver.service.definition.internal.events;
import ai.timefold.solver.core.api.solver.SolverJob;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
/**
* Sent when a solver worker fails during solving.
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/FinalBestSolutionEvent.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/FinalBestSolutionEvent.java
index aa521e24e83..b296997c75d 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/FinalBestSolutionEvent.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/FinalBestSolutionEvent.java
@@ -2,7 +2,7 @@
import ai.timefold.solver.core.api.solver.SolverJob;
import ai.timefold.solver.service.definition.api.SolverModel;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
/**
* Sent when the solver worker produces the final best solution upon termination conditions.
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/InitSolutionEvent.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/InitSolutionEvent.java
index 1b41ade0301..464f22643d2 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/InitSolutionEvent.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/InitSolutionEvent.java
@@ -2,7 +2,7 @@
import ai.timefold.solver.core.api.solver.SolverJob;
import ai.timefold.solver.service.definition.api.SolverModel;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
/**
* Sent when a solver worker produces the first, initialized, solution.
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/ItemFailed.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/ItemFailed.java
index d38de28cf16..a02b2db1c4c 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/ItemFailed.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/ItemFailed.java
@@ -1,6 +1,6 @@
package ai.timefold.solver.service.definition.internal.events;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
/**
* Event that indicates a dataset has failed during processing.
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/ItemStarted.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/ItemStarted.java
index 8b9b49044ec..002b4332eaf 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/ItemStarted.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/ItemStarted.java
@@ -1,7 +1,7 @@
package ai.timefold.solver.service.definition.internal.events;
import ai.timefold.solver.service.definition.api.SolverModel;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
/**
* Event sent when the solver worker starts solving the dataset.
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/SolverWorkerEvent.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/SolverWorkerEvent.java
index b0e0bc4cf34..18bb0ad4c38 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/SolverWorkerEvent.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/SolverWorkerEvent.java
@@ -2,7 +2,7 @@
import ai.timefold.solver.core.api.solver.SolverJob;
import ai.timefold.solver.service.definition.api.SolverModel;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
/**
* Base class for events produced by the SolverWorker.
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/ValidationSummary.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/ValidationSummary.java
index bb8ce6283b6..7f581c742de 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/ValidationSummary.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/events/ValidationSummary.java
@@ -3,10 +3,10 @@
import java.util.HashMap;
import java.util.Map;
-import ai.timefold.solver.service.definition.api.validation.Issue;
-import ai.timefold.solver.service.definition.api.validation.IssueSeverity;
-import ai.timefold.solver.service.definition.api.validation.ValidationStatus;
-import ai.timefold.solver.service.definition.api.validation.dto.ValidationResult;
+import ai.timefold.solver.service.definition.api.dto.validation.ValidationResult;
+import ai.timefold.solver.service.definition.api.dto.validation.ValidationStatus;
+import ai.timefold.solver.service.definition.api.dto.validation.issue.Issue;
+import ai.timefold.solver.service.definition.api.dto.validation.issue.IssueSeverity;
/**
* A compact summary of a dataset validation, carrying the overall {@link ValidationStatus} and issue counts by
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/Headers.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/rest/Headers.java
similarity index 93%
rename from service/definition/src/main/java/ai/timefold/solver/service/definition/internal/Headers.java
rename to service/definition/src/main/java/ai/timefold/solver/service/definition/internal/rest/Headers.java
index d83e1332070..1e283cbbe34 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/Headers.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/rest/Headers.java
@@ -1,4 +1,4 @@
-package ai.timefold.solver.service.definition.internal;
+package ai.timefold.solver.service.definition.internal.rest;
public class Headers {
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/storage/AbstractStorageService.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/storage/AbstractStorageService.java
index f7d9a9a9b77..46bde87f485 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/storage/AbstractStorageService.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/storage/AbstractStorageService.java
@@ -16,26 +16,26 @@
import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
-import ai.timefold.solver.service.definition.api.ModelConfigOverrides;
-import ai.timefold.solver.service.definition.api.ModelConstraintJustification;
-import ai.timefold.solver.service.definition.api.ModelInput;
-import ai.timefold.solver.service.definition.api.ModelOutput;
-import ai.timefold.solver.service.definition.api.SolverInput;
-import ai.timefold.solver.service.definition.api.domain.Configuration;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
-import ai.timefold.solver.service.definition.api.domain.ModelInputPatchRequest;
-import ai.timefold.solver.service.definition.api.domain.ModelRequest;
-import ai.timefold.solver.service.definition.api.domain.ModelResponse;
-import ai.timefold.solver.service.definition.api.log.LogInfo;
+import ai.timefold.solver.service.definition.api.dto.dataset.Configuration;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelConfigOverrides;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelInput;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelOutput;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelRequest;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelResponse;
+import ai.timefold.solver.service.definition.api.dto.log.LogInfo;
+import ai.timefold.solver.service.definition.api.dto.patch.ModelInputPatchRequest;
+import ai.timefold.solver.service.definition.api.dto.scoreanalysis.ModelConstraintJustification;
+import ai.timefold.solver.service.definition.api.dto.validation.LegacyValidationResult;
+import ai.timefold.solver.service.definition.api.dto.validation.ValidationResult;
+import ai.timefold.solver.service.definition.api.dto.validation.issue.Issue;
import ai.timefold.solver.service.definition.api.metrics.ModelInputMetrics;
import ai.timefold.solver.service.definition.api.metrics.ModelOutputMetrics;
-import ai.timefold.solver.service.definition.api.validation.Issue;
-import ai.timefold.solver.service.definition.api.validation.LegacyValidationResult;
-import ai.timefold.solver.service.definition.api.validation.ValidationBuilder;
-import ai.timefold.solver.service.definition.api.validation.dto.ValidationResult;
+import ai.timefold.solver.service.definition.api.validation.model.ValidationBuilder;
import ai.timefold.solver.service.definition.impl.storage.CompressionUtils;
import ai.timefold.solver.service.definition.impl.storage.StorageObjectMapperWrapper;
import ai.timefold.solver.service.definition.impl.validation.JsonMappingError;
+import ai.timefold.solver.service.definition.internal.dataset.SolverInput;
import ai.timefold.solver.service.definition.internal.error.ErrorCodes;
import ai.timefold.solver.service.definition.internal.error.ItemNotFoundException;
import ai.timefold.solver.service.definition.internal.error.TimefoldRuntimeException;
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/validation/Validator.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/validation/schema/Validator.java
similarity index 75%
rename from service/definition/src/main/java/ai/timefold/solver/service/definition/api/validation/Validator.java
rename to service/definition/src/main/java/ai/timefold/solver/service/definition/internal/validation/schema/Validator.java
index b5ecc01c5b6..18c821a4944 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/validation/Validator.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/internal/validation/schema/Validator.java
@@ -1,4 +1,4 @@
-package ai.timefold.solver.service.definition.api.validation;
+package ai.timefold.solver.service.definition.internal.validation.schema;
import java.util.List;
import java.util.UUID;
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/data/AbstractBasicDemoDataGenerator.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/AbstractBasicDemoDataGenerator.java
similarity index 87%
rename from service/definition/src/main/java/ai/timefold/solver/service/definition/api/data/AbstractBasicDemoDataGenerator.java
rename to service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/AbstractBasicDemoDataGenerator.java
index 20302431df8..5088ef5e9ce 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/data/AbstractBasicDemoDataGenerator.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/AbstractBasicDemoDataGenerator.java
@@ -1,10 +1,10 @@
-package ai.timefold.solver.service.definition.api.data;
+package ai.timefold.solver.service.definition.preview.api.demo;
import java.util.List;
-import ai.timefold.solver.service.definition.api.ModelConfigOverrides;
-import ai.timefold.solver.service.definition.api.ModelInput;
-import ai.timefold.solver.service.definition.api.domain.ModelRequest;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelConfigOverrides;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelInput;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelRequest;
/**
* Default {@link DemoDataGenerator} implementation for models that provide only a single demo data set with ID
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/DemoData.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/DemoData.java
new file mode 100644
index 00000000000..29655871d63
--- /dev/null
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/DemoData.java
@@ -0,0 +1,9 @@
+package ai.timefold.solver.service.definition.preview.api.demo;
+
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelConfigOverrides;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelInput;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelRequest;
+
+public record DemoData(DemoMetaData metaData,
+ ModelRequest extends ModelInput, ? extends ModelConfigOverrides> modelRequest) {
+}
\ No newline at end of file
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/data/DemoDataConfigEntry.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/DemoDataConfigEntry.java
similarity index 85%
rename from service/definition/src/main/java/ai/timefold/solver/service/definition/api/data/DemoDataConfigEntry.java
rename to service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/DemoDataConfigEntry.java
index 6a9924253de..d015b9dab96 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/data/DemoDataConfigEntry.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/DemoDataConfigEntry.java
@@ -1,4 +1,4 @@
-package ai.timefold.solver.service.definition.api.data;
+package ai.timefold.solver.service.definition.preview.api.demo;
public record DemoDataConfigEntry(String key, String value) {
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/data/DemoDataGenerator.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/DemoDataGenerator.java
similarity index 95%
rename from service/definition/src/main/java/ai/timefold/solver/service/definition/api/data/DemoDataGenerator.java
rename to service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/DemoDataGenerator.java
index 2313f5160ea..6d24c8e99ab 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/data/DemoDataGenerator.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/DemoDataGenerator.java
@@ -1,4 +1,4 @@
-package ai.timefold.solver.service.definition.api.data;
+package ai.timefold.solver.service.definition.preview.api.demo;
import java.util.List;
import java.util.stream.Collectors;
diff --git a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/data/DemoMetaData.java b/service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/DemoMetaData.java
similarity index 90%
rename from service/definition/src/main/java/ai/timefold/solver/service/definition/api/data/DemoMetaData.java
rename to service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/DemoMetaData.java
index f70dc35a9c4..8507c0cf0ce 100644
--- a/service/definition/src/main/java/ai/timefold/solver/service/definition/api/data/DemoMetaData.java
+++ b/service/definition/src/main/java/ai/timefold/solver/service/definition/preview/api/demo/DemoMetaData.java
@@ -1,4 +1,4 @@
-package ai.timefold.solver.service.definition.api.data;
+package ai.timefold.solver.service.definition.preview.api.demo;
import java.util.List;
diff --git a/service/definition/src/test/java/ai/timefold/solver/service/definition/api/ModelMaturityLevelTest.java b/service/definition/src/test/java/ai/timefold/solver/service/definition/api/ModelMaturityLevelTest.java
index b2eac31252f..db6f28309e4 100644
--- a/service/definition/src/test/java/ai/timefold/solver/service/definition/api/ModelMaturityLevelTest.java
+++ b/service/definition/src/test/java/ai/timefold/solver/service/definition/api/ModelMaturityLevelTest.java
@@ -1,5 +1,7 @@
package ai.timefold.solver.service.definition.api;
+import ai.timefold.solver.service.definition.api.description.ModelMaturityLevel;
+
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
diff --git a/service/definition/src/test/java/ai/timefold/solver/service/definition/api/data/DemoMetaDataTest.java b/service/definition/src/test/java/ai/timefold/solver/service/definition/api/data/DemoMetaDataTest.java
index fd3b692f5fd..edaaf39ff85 100644
--- a/service/definition/src/test/java/ai/timefold/solver/service/definition/api/data/DemoMetaDataTest.java
+++ b/service/definition/src/test/java/ai/timefold/solver/service/definition/api/data/DemoMetaDataTest.java
@@ -4,6 +4,8 @@
import java.util.List;
+import ai.timefold.solver.service.definition.preview.api.demo.DemoMetaData;
+
import org.junit.jupiter.api.Test;
class DemoMetaDataTest {
diff --git a/service/definition/src/test/java/ai/timefold/solver/service/definition/api/domain/RunConfigurationTest.java b/service/definition/src/test/java/ai/timefold/solver/service/definition/api/domain/RunConfigurationTest.java
index dcbbc1023a4..eb599291938 100644
--- a/service/definition/src/test/java/ai/timefold/solver/service/definition/api/domain/RunConfigurationTest.java
+++ b/service/definition/src/test/java/ai/timefold/solver/service/definition/api/domain/RunConfigurationTest.java
@@ -6,7 +6,8 @@
import java.util.Map;
import java.util.Set;
-import ai.timefold.solver.service.definition.api.termination.SolverTerminationConfig;
+import ai.timefold.solver.service.definition.api.dto.dataset.RunConfiguration;
+import ai.timefold.solver.service.definition.api.dto.solve.SolverTerminationConfig;
import org.junit.jupiter.api.Test;
diff --git a/service/definition/src/test/java/ai/timefold/solver/service/definition/api/termination/SolverTerminationConfigTest.java b/service/definition/src/test/java/ai/timefold/solver/service/definition/api/termination/SolverTerminationConfigTest.java
index 53a43691aaa..aa2474edf35 100644
--- a/service/definition/src/test/java/ai/timefold/solver/service/definition/api/termination/SolverTerminationConfigTest.java
+++ b/service/definition/src/test/java/ai/timefold/solver/service/definition/api/termination/SolverTerminationConfigTest.java
@@ -5,6 +5,8 @@
import java.time.Duration;
+import ai.timefold.solver.service.definition.api.dto.solve.SolverTerminationConfig;
+
import org.junit.jupiter.api.Test;
class SolverTerminationConfigTest {
diff --git a/service/definition/src/test/java/ai/timefold/solver/service/definition/api/validation/ValidationIssueSerializationTest.java b/service/definition/src/test/java/ai/timefold/solver/service/definition/api/validation/ValidationIssueSerializationTest.java
index e773aad982e..248b76c4b0a 100644
--- a/service/definition/src/test/java/ai/timefold/solver/service/definition/api/validation/ValidationIssueSerializationTest.java
+++ b/service/definition/src/test/java/ai/timefold/solver/service/definition/api/validation/ValidationIssueSerializationTest.java
@@ -2,6 +2,11 @@
import java.util.List;
+import ai.timefold.solver.service.definition.api.dto.validation.issue.AbstractIssue;
+import ai.timefold.solver.service.definition.api.dto.validation.issue.IssueCode;
+import ai.timefold.solver.service.definition.api.dto.validation.issue.IssueSeverity;
+import ai.timefold.solver.service.definition.api.dto.validation.issue.IssueType;
+import ai.timefold.solver.service.definition.api.validation.model.ValidationBuilder;
import ai.timefold.solver.service.definition.impl.validation.AbstractLegacyIssue;
import org.assertj.core.api.Assertions;
diff --git a/service/definition/src/test/java/ai/timefold/solver/service/definition/internal/events/ValidationSummaryTest.java b/service/definition/src/test/java/ai/timefold/solver/service/definition/internal/events/ValidationSummaryTest.java
index ce21415f99c..c5bf3c80e61 100644
--- a/service/definition/src/test/java/ai/timefold/solver/service/definition/internal/events/ValidationSummaryTest.java
+++ b/service/definition/src/test/java/ai/timefold/solver/service/definition/internal/events/ValidationSummaryTest.java
@@ -5,11 +5,11 @@
import java.util.List;
import java.util.Map;
-import ai.timefold.solver.service.definition.api.validation.AbstractIssue;
-import ai.timefold.solver.service.definition.api.validation.IssueCode;
-import ai.timefold.solver.service.definition.api.validation.IssueSeverity;
-import ai.timefold.solver.service.definition.api.validation.ValidationStatus;
-import ai.timefold.solver.service.definition.api.validation.dto.ValidationResult;
+import ai.timefold.solver.service.definition.api.dto.validation.ValidationResult;
+import ai.timefold.solver.service.definition.api.dto.validation.ValidationStatus;
+import ai.timefold.solver.service.definition.api.dto.validation.issue.AbstractIssue;
+import ai.timefold.solver.service.definition.api.dto.validation.issue.IssueCode;
+import ai.timefold.solver.service.definition.api.dto.validation.issue.IssueSeverity;
import org.junit.jupiter.api.Test;
diff --git a/service/definition/src/test/java/ai/timefold/solver/service/definition/internal/storage/AbstractStorageServiceRetryTest.java b/service/definition/src/test/java/ai/timefold/solver/service/definition/internal/storage/AbstractStorageServiceRetryTest.java
index 0d93c691a5b..80b172ff5a0 100644
--- a/service/definition/src/test/java/ai/timefold/solver/service/definition/internal/storage/AbstractStorageServiceRetryTest.java
+++ b/service/definition/src/test/java/ai/timefold/solver/service/definition/internal/storage/AbstractStorageServiceRetryTest.java
@@ -13,11 +13,11 @@
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
-import ai.timefold.solver.service.definition.api.ModelConfigOverrides;
-import ai.timefold.solver.service.definition.api.ModelConstraintJustification;
-import ai.timefold.solver.service.definition.api.ModelInput;
-import ai.timefold.solver.service.definition.api.ModelOutput;
-import ai.timefold.solver.service.definition.api.domain.Configuration;
+import ai.timefold.solver.service.definition.api.dto.dataset.Configuration;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelConfigOverrides;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelInput;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelOutput;
+import ai.timefold.solver.service.definition.api.dto.scoreanalysis.ModelConstraintJustification;
import ai.timefold.solver.service.definition.api.metrics.ModelInputMetrics;
import ai.timefold.solver.service.definition.api.metrics.ModelOutputMetrics;
import ai.timefold.solver.service.definition.impl.storage.CompressionUtils;
diff --git a/service/json/src/main/java/ai/timefold/solver/service/json/internal/patch/JsonPatch.java b/service/json/src/main/java/ai/timefold/solver/service/json/internal/patch/JsonPatch.java
index 3302ce5c863..9b003d1ba68 100644
--- a/service/json/src/main/java/ai/timefold/solver/service/json/internal/patch/JsonPatch.java
+++ b/service/json/src/main/java/ai/timefold/solver/service/json/internal/patch/JsonPatch.java
@@ -3,7 +3,7 @@
import java.util.function.Function;
import java.util.regex.Matcher;
-import ai.timefold.solver.service.definition.api.ModelInputPatchOp;
+import ai.timefold.solver.service.definition.api.dto.patch.ModelInputPatchOp;
import ai.timefold.solver.service.json.impl.patch.AddByFilter;
import ai.timefold.solver.service.json.impl.patch.AddByIndex;
import ai.timefold.solver.service.json.impl.patch.JsonPatchConstants;
diff --git a/service/json/src/main/java/ai/timefold/solver/service/json/internal/schema/JsonSchemaValidator.java b/service/json/src/main/java/ai/timefold/solver/service/json/internal/schema/JsonSchemaValidator.java
index 333854f146e..6b9786db10b 100644
--- a/service/json/src/main/java/ai/timefold/solver/service/json/internal/schema/JsonSchemaValidator.java
+++ b/service/json/src/main/java/ai/timefold/solver/service/json/internal/schema/JsonSchemaValidator.java
@@ -12,7 +12,7 @@
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.ApplicationScoped;
-import ai.timefold.solver.service.definition.api.validation.Validator;
+import ai.timefold.solver.service.definition.internal.validation.schema.Validator;
import ai.timefold.solver.service.json.api.schema.LocalDateTimeFormat;
import ai.timefold.solver.service.json.api.schema.OffsetDateTimeFormat;
import ai.timefold.solver.service.json.api.schema.ZoneIdFormat;
diff --git a/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/MapServiceClientImpl.java b/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/MapServiceClientImpl.java
index f60d32b89cc..884f62fa435 100644
--- a/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/MapServiceClientImpl.java
+++ b/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/MapServiceClientImpl.java
@@ -1,14 +1,14 @@
package ai.timefold.solver.service.maps.service.client.impl;
-import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_CACHE_ID;
-import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_INVALIDATE_MATRIX_HEADER;
-import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_LOCATIONS_CHUNK_BYTES;
-import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_LOCATIONS_NOT_IN_MAP;
-import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_LOCATION_HEADER;
-import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_MATRIX_HASH_HEADER;
-import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_PROVIDER_HEADER;
-import static ai.timefold.solver.service.definition.internal.Headers.X_MAPS_RESPONSE_CHUNK_BYTES;
-import static ai.timefold.solver.service.definition.internal.Headers.X_TENANT_ID_HEADER;
+import static ai.timefold.solver.service.definition.internal.rest.Headers.X_MAPS_CACHE_ID;
+import static ai.timefold.solver.service.definition.internal.rest.Headers.X_MAPS_INVALIDATE_MATRIX_HEADER;
+import static ai.timefold.solver.service.definition.internal.rest.Headers.X_MAPS_LOCATIONS_CHUNK_BYTES;
+import static ai.timefold.solver.service.definition.internal.rest.Headers.X_MAPS_LOCATIONS_NOT_IN_MAP;
+import static ai.timefold.solver.service.definition.internal.rest.Headers.X_MAPS_LOCATION_HEADER;
+import static ai.timefold.solver.service.definition.internal.rest.Headers.X_MAPS_MATRIX_HASH_HEADER;
+import static ai.timefold.solver.service.definition.internal.rest.Headers.X_MAPS_PROVIDER_HEADER;
+import static ai.timefold.solver.service.definition.internal.rest.Headers.X_MAPS_RESPONSE_CHUNK_BYTES;
+import static ai.timefold.solver.service.definition.internal.rest.Headers.X_TENANT_ID_HEADER;
import java.io.IOException;
import java.io.InputStream;
diff --git a/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/error/MapServiceExceptionMapper.java b/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/error/MapServiceExceptionMapper.java
index 0960775f5fe..880a34a9cb4 100644
--- a/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/error/MapServiceExceptionMapper.java
+++ b/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/error/MapServiceExceptionMapper.java
@@ -2,7 +2,7 @@
import jakarta.ws.rs.core.Response;
-import ai.timefold.solver.service.definition.api.error.ErrorInfo;
+import ai.timefold.solver.service.definition.api.dto.error.ErrorInfo;
import ai.timefold.solver.service.definition.internal.error.ErrorCodes;
import ai.timefold.solver.service.definition.internal.error.TimefoldRuntimeException;
diff --git a/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/processors/SaveWaypointsPostProcessor.java b/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/processors/SaveWaypointsPostProcessor.java
index e9c4d03195b..983aa688153 100644
--- a/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/processors/SaveWaypointsPostProcessor.java
+++ b/service/maps/service-client/src/main/java/ai/timefold/solver/service/maps/service/client/impl/processors/SaveWaypointsPostProcessor.java
@@ -8,9 +8,9 @@
import jakarta.inject.Inject;
import jakarta.interceptor.Interceptor;
-import ai.timefold.solver.service.definition.api.ModelOutput;
-import ai.timefold.solver.service.definition.api.ModelPostProcessor;
import ai.timefold.solver.service.definition.api.SolverModel;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelOutput;
+import ai.timefold.solver.service.definition.internal.dataset.ModelPostProcessor;
import ai.timefold.solver.service.definition.internal.storage.AbstractStorageService;
import ai.timefold.solver.service.maps.api.model.Waypoints;
import ai.timefold.solver.service.maps.service.integration.impl.WaypointsService;
diff --git a/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/impl/WaypointsServiceImplTest.java b/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/impl/WaypointsServiceImplTest.java
index ffe917d719c..83e7c4f4b27 100644
--- a/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/impl/WaypointsServiceImplTest.java
+++ b/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/impl/WaypointsServiceImplTest.java
@@ -5,7 +5,7 @@
import jakarta.inject.Inject;
-import ai.timefold.solver.service.definition.api.domain.Metadata;
+import ai.timefold.solver.service.definition.api.dto.dataset.Metadata;
import ai.timefold.solver.service.definition.internal.events.BestSolutionEvent;
import ai.timefold.solver.service.definition.internal.events.FinalBestSolutionEvent;
import ai.timefold.solver.service.definition.internal.events.InitSolutionEvent;
diff --git a/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/DummyModelInput.java b/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/DummyModelInput.java
index 1c5580ae5b8..4af4202a86c 100644
--- a/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/DummyModelInput.java
+++ b/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/DummyModelInput.java
@@ -1,6 +1,6 @@
package ai.timefold.solver.service.maps.service.client.util;
-import ai.timefold.solver.service.definition.api.ModelInput;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelInput;
public class DummyModelInput implements ModelInput {
}
diff --git a/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/DummyModelOutput.java b/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/DummyModelOutput.java
index 476ef6aec7a..a02f73e823f 100644
--- a/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/DummyModelOutput.java
+++ b/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/DummyModelOutput.java
@@ -1,6 +1,6 @@
package ai.timefold.solver.service.maps.service.client.util;
-import ai.timefold.solver.service.definition.api.ModelOutput;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelOutput;
public class DummyModelOutput implements ModelOutput {
}
diff --git a/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/DummyStorageService.java b/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/DummyStorageService.java
index 38503fe844c..af8d954a1ad 100644
--- a/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/DummyStorageService.java
+++ b/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/DummyStorageService.java
@@ -1,9 +1,9 @@
package ai.timefold.solver.service.maps.service.client.util;
import ai.timefold.solver.core.api.score.SimpleScore;
-import ai.timefold.solver.service.definition.api.ModelConfigOverrides;
-import ai.timefold.solver.service.definition.api.ModelConstraintJustification;
-import ai.timefold.solver.service.definition.api.domain.Configuration;
+import ai.timefold.solver.service.definition.api.dto.dataset.Configuration;
+import ai.timefold.solver.service.definition.api.dto.dataset.ModelConfigOverrides;
+import ai.timefold.solver.service.definition.api.dto.scoreanalysis.ModelConstraintJustification;
import ai.timefold.solver.service.definition.api.metrics.ModelInputMetrics;
import ai.timefold.solver.service.definition.api.metrics.ModelOutputMetrics;
import ai.timefold.solver.service.definition.internal.storage.AbstractStorageService;
diff --git a/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/SampleModel.java b/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/SampleModel.java
index 78551e16bb4..c20cb5fc2d4 100644
--- a/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/SampleModel.java
+++ b/service/maps/service-client/src/test/java/ai/timefold/solver/service/maps/service/client/util/SampleModel.java
@@ -10,8 +10,6 @@
import ai.timefold.solver.core.api.domain.solution.ProblemFactCollectionProperty;
import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider;
import ai.timefold.solver.core.api.score.HardSoftScore;
-import ai.timefold.solver.service.definition.api.Status;
-import ai.timefold.solver.service.definition.api.UserModel;
import ai.timefold.solver.service.definition.api.metrics.InputMetricsAware;
import ai.timefold.solver.service.definition.api.metrics.ModelInputMetrics;
import ai.timefold.solver.service.definition.api.metrics.ModelOutputMetrics;
@@ -21,8 +19,7 @@
@PlanningSolution
public class SampleModel implements LocationsAwareSolverModel+ * The flat {@code ai.timefold.solver.service.definition.api} package and its {@code configuration}, {@code data}, + * {@code domain}, {@code error}, {@code log}, {@code termination} and {@code validation} subpackages + * were reorganized: + *
+ * The removed {@code ai.timefold.solver.service.definition.api.UserModel} has no replacement and is not migrated.
+ */
+public class ServiceDefinitionPackageMigrationRecipe extends AbstractRecipe {
+
+ private static final String API = "ai.timefold.solver.service.definition.api.";
+ private static final String NEW_PREVIEW_API = "ai.timefold.solver.service.definition.preview.api.";
+ private static final String INTERNAL = "ai.timefold.solver.service.definition.internal.";
+ private static final String ENTERPRISE_API = "ai.timefold.solver.enterprise.service.definition.api.";
+
+ @Override
+ public String getDisplayName() {
+ return "Migrate the service definition to its new package structure";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Migrate the types of the Timefold Solver service definition to their new packages.";
+ }
+
+ @Override
+ public List