diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/autodiscover/AutoDiscoverMemberType.java b/core/src/main/java/ai/timefold/solver/core/api/domain/autodiscover/AutoDiscoverMemberType.java deleted file mode 100644 index 77659433a0d..00000000000 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/autodiscover/AutoDiscoverMemberType.java +++ /dev/null @@ -1,32 +0,0 @@ -package ai.timefold.solver.core.api.domain.autodiscover; - -import ai.timefold.solver.core.api.domain.solution.ConstraintWeightOverrides; -import ai.timefold.solver.core.api.domain.solution.PlanningEntityCollectionProperty; -import ai.timefold.solver.core.api.domain.solution.PlanningEntityProperty; -import ai.timefold.solver.core.api.domain.solution.PlanningScore; -import ai.timefold.solver.core.api.domain.solution.PlanningSolution; -import ai.timefold.solver.core.api.domain.solution.ProblemFactCollectionProperty; -import ai.timefold.solver.core.api.domain.solution.ProblemFactProperty; - -/** - * Determines if and how to automatically presume {@link ConstraintWeightOverrides}, - * {@link ProblemFactCollectionProperty}, {@link ProblemFactProperty}, {@link PlanningEntityCollectionProperty}, - * {@link PlanningEntityProperty} and {@link PlanningScore} annotations on {@link PlanningSolution} members - * based on the member type. - */ -public enum AutoDiscoverMemberType { - /** - * Do not reflect. - */ - NONE, - /** - * Reflect over the fields and automatically behave as the appropriate annotation is there - * based on the field type. - */ - FIELD, - /** - * Reflect over the getter methods and automatically behave as the appropriate annotation is there - * based on the return type. - */ - GETTER; -} diff --git a/core/src/main/java/ai/timefold/solver/core/api/domain/solution/PlanningSolution.java b/core/src/main/java/ai/timefold/solver/core/api/domain/solution/PlanningSolution.java index dedd9689bbc..560e197f4d3 100644 --- a/core/src/main/java/ai/timefold/solver/core/api/domain/solution/PlanningSolution.java +++ b/core/src/main/java/ai/timefold/solver/core/api/domain/solution/PlanningSolution.java @@ -6,12 +6,9 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType; import ai.timefold.solver.core.api.domain.solution.cloner.SolutionCloner; import ai.timefold.solver.core.api.score.stream.ConstraintProvider; -import org.jspecify.annotations.NonNull; - /** * Specifies that the class is a planning solution. * A solution represents a problem and a possible solution of that problem. @@ -42,21 +39,6 @@ @Target({ TYPE }) @Retention(RUNTIME) public @interface PlanningSolution { - - /** - * Enable reflection through the members of the class - * to automatically assume {@link PlanningScore}, {@link PlanningEntityCollectionProperty}, - * {@link PlanningEntityProperty}, {@link ProblemFactCollectionProperty}, {@link ProblemFactProperty} - * and {@link ConstraintWeightOverrides} annotations based on the member type. - * - *

- * This feature is not supported under Quarkus. - * When using Quarkus, - * setting this to anything other than {@link AutoDiscoverMemberType#NONE} will result in a build-time exception. - */ - @NonNull - AutoDiscoverMemberType autoDiscoverMemberType() default AutoDiscoverMemberType.NONE; - /** * Overrides the default {@link SolutionCloner} to implement a custom {@link PlanningSolution} cloning implementation. *

diff --git a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptor.java b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptor.java index 9ff642c5adf..f850e794e04 100644 --- a/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptor.java +++ b/core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptor.java @@ -10,7 +10,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -34,7 +33,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType; import ai.timefold.solver.core.api.domain.entity.PlanningEntity; import ai.timefold.solver.core.api.domain.solution.ConstraintWeightOverrides; import ai.timefold.solver.core.api.domain.solution.PlanningEntityCollectionProperty; @@ -139,7 +137,7 @@ public static SolutionDescriptor buildSolutionDescriptor( descriptorPolicy.setMemberAccessorFactory(solutionDescriptor.getMemberAccessorFactory()); solutionDescriptor.processUnannotatedFieldsAndMethods(descriptorPolicy); - solutionDescriptor.processAnnotations(descriptorPolicy, entityClassList); + solutionDescriptor.processAnnotations(descriptorPolicy); // Before iterating over the entity classes, we need to read the inheritance chain, // add all parent and child classes, and sort them. var updatedEntityClassList = new ArrayList<>(entityClassList); @@ -259,7 +257,6 @@ private static boolean hasAnyAnnotatedMembers(Class solutionClass) { private final MemberAccessorFactory memberAccessorFactory; private DomainAccessType domainAccessType; - private AutoDiscoverMemberType autoDiscoverMemberType; private LookUpStrategyResolver lookUpStrategyResolver; private final Map problemFactMemberAccessorMap = new LinkedHashMap<>(); @@ -337,7 +334,7 @@ private void processConstraintWeights(DescriptorPolicy descriptorPolicy) { } } - public void processAnnotations(DescriptorPolicy descriptorPolicy, List> entityClassList) { + public void processAnnotations(DescriptorPolicy descriptorPolicy) { domainAccessType = descriptorPolicy.getDomainAccessType(); processSolutionAnnotations(descriptorPolicy); var potentiallyOverwritingMethodList = new ArrayList(); @@ -356,7 +353,7 @@ public void processAnnotations(DescriptorPolicy descriptorPolicy, List> continue; } processValueRangeProviderAnnotation(descriptorPolicy, member); - processFactEntityOrScoreAnnotation(descriptorPolicy, member, entityClassList); + processFactEntityOrScoreAnnotation(descriptorPolicy, member); } potentiallyOverwritingMethodList.ensureCapacity(potentiallyOverwritingMethodList.size() + memberList.size()); memberList.stream().filter(Method.class::isInstance) @@ -382,7 +379,6 @@ Maybe add a getScore() method with a @%s annotation.""" private void processSolutionAnnotations(DescriptorPolicy descriptorPolicy) { var annotation = extractMostRelevantPlanningSolutionAnnotation(); - autoDiscoverMemberType = annotation.autoDiscoverMemberType(); var solutionClonerClass = annotation.solutionCloner(); if (solutionClonerClass != PlanningSolution.NullSolutionCloner.class) { solutionCloner = ConfigUtils.newInstance(this::toString, "solutionClonerClass", solutionClonerClass); @@ -422,9 +418,9 @@ private void processValueRangeProviderAnnotation(DescriptorPolicy descriptorPoli } private void processFactEntityOrScoreAnnotation(DescriptorPolicy descriptorPolicy, - Member member, List> entityClassList) { - var annotationClass = extractFactEntityOrScoreAnnotationClassOrAutoDiscover( - member, entityClassList); + Member member) { + var annotationClass = extractFactEntityOrScoreAnnotationClass( + member); if (annotationClass == null) { return; } @@ -444,63 +440,12 @@ private void processFactEntityOrScoreAnnotation(DescriptorPolicy descriptorPolic } } - private Class extractFactEntityOrScoreAnnotationClassOrAutoDiscover( - Member member, List> entityClassList) { - var annotationClass = ConfigUtils.extractAnnotationClass(member, + private static Class extractFactEntityOrScoreAnnotationClass(Member member) { + return ConfigUtils.extractAnnotationClass(member, ProblemFactProperty.class, ProblemFactCollectionProperty.class, PlanningEntityProperty.class, PlanningEntityCollectionProperty.class, PlanningScore.class); - if (annotationClass == null) { - Class type; - if (autoDiscoverMemberType == AutoDiscoverMemberType.FIELD - && member instanceof Field field) { - type = field.getType(); - } else if (autoDiscoverMemberType == AutoDiscoverMemberType.GETTER - && (member instanceof Method method) && ReflectionHelper.isGetterMethod(method)) { - type = method.getReturnType(); - } else { - type = null; - } - if (type != null) { - if (Score.class.isAssignableFrom(type)) { - annotationClass = PlanningScore.class; - } else if (Collection.class.isAssignableFrom(type) || type.isArray()) { - Class elementType; - if (Collection.class.isAssignableFrom(type)) { - var genericType = (member instanceof Field f) ? f.getGenericType() - : ((Method) member).getGenericReturnType(); - var memberName = member.getName(); - if (!(genericType instanceof ParameterizedType)) { - throw new IllegalArgumentException( - """ - The solutionClass (%s) has a auto discovered member (%s) with a member type (%s) that returns a %s which has no generic parameters. - Maybe the member (%s) should return a typed %s.""" - .formatted(solutionClass, memberName, type, Collection.class.getSimpleName(), - memberName, Collection.class.getSimpleName())); - } - elementType = ConfigUtils.extractGenericTypeParameter("solutionClass", solutionClass, type, genericType, - null, member.getName()).orElse(Object.class); - } else { - elementType = type.getComponentType(); - } - if (entityClassList.stream().anyMatch(entityClass -> entityClass.isAssignableFrom(elementType))) { - annotationClass = PlanningEntityCollectionProperty.class; - } else { - annotationClass = ProblemFactCollectionProperty.class; - } - } else if (Map.class.isAssignableFrom(type)) { - throw new IllegalStateException( - "The autoDiscoverMemberType (%s) does not yet support the member (%s) of type (%s) which is an implementation of %s." - .formatted(autoDiscoverMemberType, member, type, Map.class.getSimpleName())); - } else if (entityClassList.stream().anyMatch(entityClass -> entityClass.isAssignableFrom(type))) { - annotationClass = PlanningEntityProperty.class; - } else { - annotationClass = ProblemFactProperty.class; - } - } - } - return annotationClass; } private void processProblemFactPropertyAnnotation(DescriptorPolicy descriptorPolicy, Member member, diff --git a/core/src/test/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptorTest.java b/core/src/test/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptorTest.java index 01db6ec9d1a..f0c9f48f28b 100644 --- a/core/src/test/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptorTest.java +++ b/core/src/test/java/ai/timefold/solver/core/impl/domain/solution/descriptor/SolutionDescriptorTest.java @@ -1,6 +1,5 @@ package ai.timefold.solver.core.impl.domain.solution.descriptor; -import static ai.timefold.solver.core.testutil.PlannerAssert.assertAllCodesOfCollection; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; @@ -10,19 +9,15 @@ import java.util.Arrays; import java.util.List; -import ai.timefold.solver.core.api.score.SimpleScore; import ai.timefold.solver.core.impl.domain.entity.descriptor.EntityDescriptor; import ai.timefold.solver.core.impl.domain.valuerange.descriptor.AbstractValueRangeDescriptor; import ai.timefold.solver.core.impl.domain.variable.descriptor.BasicVariableDescriptor; -import ai.timefold.solver.core.impl.score.definition.SimpleScoreDefinition; import ai.timefold.solver.core.testdomain.TestdataEntity; -import ai.timefold.solver.core.testdomain.TestdataObject; import ai.timefold.solver.core.testdomain.TestdataValue; import ai.timefold.solver.core.testdomain.collection.TestdataArrayBasedSolution; import ai.timefold.solver.core.testdomain.collection.TestdataSetBasedSolution; import ai.timefold.solver.core.testdomain.immutable.enumeration.TestdataEnumSolution; import ai.timefold.solver.core.testdomain.immutable.record.TestdataRecordSolution; -import ai.timefold.solver.core.testdomain.inheritance.solution.baseannotated.childnot.TestdataOnlyBaseAnnotatedChildEntity; import ai.timefold.solver.core.testdomain.inheritance.solution.baseannotated.childtoo.TestdataBothAnnotatedExtendedSolution; import ai.timefold.solver.core.testdomain.invalid.badfactcollection.TestdataBadFactCollectionSolution; import ai.timefold.solver.core.testdomain.invalid.constraintweightoverrides.TestdataInvalidConstraintWeightOverridesSolution; @@ -38,21 +33,13 @@ import ai.timefold.solver.core.testdomain.solutionproperties.TestdataProblemFactPropertySolution; import ai.timefold.solver.core.testdomain.solutionproperties.TestdataReadMethodProblemFactCollectionPropertySolution; import ai.timefold.solver.core.testdomain.solutionproperties.TestdataWildcardSolution; -import ai.timefold.solver.core.testdomain.solutionproperties.autodiscover.TestdataAutoDiscoverFieldOverrideSolution; -import ai.timefold.solver.core.testdomain.solutionproperties.autodiscover.TestdataAutoDiscoverFieldSolution; -import ai.timefold.solver.core.testdomain.solutionproperties.autodiscover.TestdataAutoDiscoverGetterOverrideSolution; -import ai.timefold.solver.core.testdomain.solutionproperties.autodiscover.TestdataAutoDiscoverGetterSolution; -import ai.timefold.solver.core.testdomain.solutionproperties.autodiscover.TestdataAutoDiscoverUnannotatedEntitySolution; -import ai.timefold.solver.core.testdomain.solutionproperties.autodiscover.TestdataExtendedAutoDiscoverGetterSolution; import ai.timefold.solver.core.testdomain.solutionproperties.invalid.TestdataDuplicatePlanningEntityCollectionPropertySolution; import ai.timefold.solver.core.testdomain.solutionproperties.invalid.TestdataDuplicatePlanningScorePropertySolution; import ai.timefold.solver.core.testdomain.solutionproperties.invalid.TestdataDuplicateProblemFactCollectionPropertySolution; import ai.timefold.solver.core.testdomain.solutionproperties.invalid.TestdataMissingScorePropertySolution; import ai.timefold.solver.core.testdomain.solutionproperties.invalid.TestdataProblemFactCollectionPropertyWithArgumentSolution; import ai.timefold.solver.core.testdomain.solutionproperties.invalid.TestdataProblemFactIsPlanningEntityCollectionPropertySolution; -import ai.timefold.solver.core.testdomain.solutionproperties.invalid.TestdataUnknownFactTypeSolution; import ai.timefold.solver.core.testdomain.solutionproperties.invalid.TestdataUnsupportedWildcardSolution; -import ai.timefold.solver.core.testutil.CodeAssertableArrayList; import ai.timefold.solver.core.testutil.PlannerTestUtils; import org.junit.jupiter.api.Test; @@ -203,137 +190,6 @@ void generic() { .containsOnlyKeys("value", "subTypeValue", "complexGenericValue"); } - // ************************************************************************ - // Autodiscovery - // ************************************************************************ - - @Test - void autoDiscoverProblemFactCollectionPropertyElementTypeUnknown() { - assertThatIllegalArgumentException().isThrownBy(TestdataUnknownFactTypeSolution::buildSolutionDescriptor); - } - - @Test - void autoDiscoverFields() { - var solutionDescriptor = TestdataAutoDiscoverFieldSolution.buildSolutionDescriptor(); - assertThat(solutionDescriptor.getScoreDefinition()).isInstanceOf(SimpleScoreDefinition.class); - assertThat(solutionDescriptor.getScoreDefinition().getScoreClass()).isEqualTo(SimpleScore.class); - assertThat(solutionDescriptor.getProblemFactMemberAccessorMap()).containsOnlyKeys("singleProblemFact"); - assertThat(solutionDescriptor.getProblemFactCollectionMemberAccessorMap()).containsOnlyKeys("problemFactList"); - assertThat(solutionDescriptor.getEntityMemberAccessorMap()).containsOnlyKeys("otherEntity"); - assertThat(solutionDescriptor.getEntityCollectionMemberAccessorMap()).containsOnlyKeys("entityList"); - - var singleProblemFact = new TestdataObject("p1"); - var valueList = Arrays.asList(new TestdataValue("v1"), new TestdataValue("v2")); - var entityList = Arrays.asList(new TestdataEntity("e1"), new TestdataEntity("e2")); - var otherEntity = new TestdataEntity("otherE1"); - var solution = new TestdataAutoDiscoverFieldSolution("s1", singleProblemFact, valueList, entityList, otherEntity); - - assertAllCodesOfCollection(solutionDescriptor.getAllEntitiesAndProblemFacts(solution), "otherE1", "p1", "e1", "e2", - "v1", "v2"); - } - - @Test - void autoDiscoverGetters() { - var solutionDescriptor = TestdataAutoDiscoverGetterSolution.buildSolutionDescriptor(); - assertThat(solutionDescriptor.getProblemFactMemberAccessorMap()).containsOnlyKeys("singleProblemFact"); - assertThat(solutionDescriptor.getProblemFactCollectionMemberAccessorMap()).containsOnlyKeys("problemFactList"); - assertThat(solutionDescriptor.getEntityMemberAccessorMap()).containsOnlyKeys("otherEntity"); - assertThat(solutionDescriptor.getEntityCollectionMemberAccessorMap()).containsOnlyKeys("entityList"); - - var singleProblemFact = new TestdataObject("p1"); - var valueList = Arrays.asList(new TestdataValue("v1"), new TestdataValue("v2")); - var entityList = Arrays.asList(new TestdataEntity("e1"), new TestdataEntity("e2")); - var otherEntity = new TestdataEntity("otherE1"); - var solution = new TestdataAutoDiscoverGetterSolution("s1", singleProblemFact, valueList, entityList, otherEntity); - - assertAllCodesOfCollection(solutionDescriptor.getAllEntitiesAndProblemFacts(solution), "otherE1", "p1", "e1", "e2", - "v1", "v2"); - } - - @Test - void autoDiscoverFieldsFactCollectionOverriddenToSingleProperty() { - var solutionDescriptor = TestdataAutoDiscoverFieldOverrideSolution.buildSolutionDescriptor(); - assertThat(solutionDescriptor.getProblemFactMemberAccessorMap()).containsOnlyKeys("singleProblemFact", - "listProblemFact"); - assertThat(solutionDescriptor.getProblemFactCollectionMemberAccessorMap()).containsOnlyKeys("problemFactList"); - assertThat(solutionDescriptor.getEntityMemberAccessorMap()).containsOnlyKeys("otherEntity"); - assertThat(solutionDescriptor.getEntityCollectionMemberAccessorMap()).containsOnlyKeys("entityList"); - - var singleProblemFact = new TestdataObject("p1"); - var valueList = Arrays.asList(new TestdataValue("v1"), new TestdataValue("v2")); - var entityList = Arrays.asList(new TestdataEntity("e1"), new TestdataEntity("e2")); - var otherEntity = new TestdataEntity("otherE1"); - var listFact = new CodeAssertableArrayList<>("list1", Arrays.asList("x", "y")); - var solution = new TestdataAutoDiscoverFieldOverrideSolution("s1", singleProblemFact, valueList, entityList, - otherEntity, listFact); - - assertAllCodesOfCollection(solutionDescriptor.getAllEntitiesAndProblemFacts(solution), - "otherE1", "list1", "p1", "e1", "e2", "v1", "v2"); - } - - @Test - void autoDiscoverGettersFactCollectionOverriddenToSingleProperty() { - var solutionDescriptor = TestdataAutoDiscoverGetterOverrideSolution.buildSolutionDescriptor(); - assertThat(solutionDescriptor.getProblemFactMemberAccessorMap()).containsOnlyKeys("singleProblemFact", - "listProblemFact"); - assertThat(solutionDescriptor.getProblemFactCollectionMemberAccessorMap()).containsOnlyKeys("problemFactList"); - assertThat(solutionDescriptor.getEntityMemberAccessorMap()).containsOnlyKeys("otherEntity"); - assertThat(solutionDescriptor.getEntityCollectionMemberAccessorMap()).containsOnlyKeys("entityList"); - - var singleProblemFact = new TestdataObject("p1"); - var valueList = Arrays.asList(new TestdataValue("v1"), new TestdataValue("v2")); - var entityList = Arrays.asList(new TestdataEntity("e1"), new TestdataEntity("e2")); - var otherEntity = new TestdataEntity("otherE1"); - var listFact = new CodeAssertableArrayList<>("list1", Arrays.asList("x", "y")); - var solution = new TestdataAutoDiscoverGetterOverrideSolution("s1", singleProblemFact, valueList, entityList, - otherEntity, listFact); - - assertAllCodesOfCollection(solutionDescriptor.getAllEntitiesAndProblemFacts(solution), - "otherE1", "list1", "p1", "e1", "e2", "v1", "v2"); - } - - @Test - void autoDiscoverUnannotatedEntitySubclass() { - var solutionDescriptor = TestdataAutoDiscoverUnannotatedEntitySolution.buildSolutionDescriptor(); - assertThat(solutionDescriptor.getProblemFactMemberAccessorMap()).containsOnlyKeys("singleProblemFact"); - assertThat(solutionDescriptor.getProblemFactCollectionMemberAccessorMap()).containsOnlyKeys("problemFactList"); - assertThat(solutionDescriptor.getEntityMemberAccessorMap()).containsOnlyKeys("otherEntity"); - assertThat(solutionDescriptor.getEntityCollectionMemberAccessorMap()).containsOnlyKeys("entityList"); - - var singleProblemFact = new TestdataObject("p1"); - var valueList = Arrays.asList(new TestdataValue("v1"), new TestdataValue("v2")); - var entityList = Arrays.asList( - new TestdataOnlyBaseAnnotatedChildEntity("u1"), - new TestdataOnlyBaseAnnotatedChildEntity("u2")); - var otherEntity = new TestdataOnlyBaseAnnotatedChildEntity("otherU1"); - var solution = - new TestdataAutoDiscoverUnannotatedEntitySolution("s1", singleProblemFact, valueList, entityList, otherEntity); - - assertAllCodesOfCollection(solutionDescriptor.getAllEntitiesAndProblemFacts(solution), "otherU1", "p1", "u1", "u2", - "v1", "v2"); - } - - @Test - void autoDiscoverGettersOverriddenInSubclass() { - var solutionDescriptor = TestdataExtendedAutoDiscoverGetterSolution.buildSubclassSolutionDescriptor(); - assertThat(solutionDescriptor.getProblemFactMemberAccessorMap()).containsOnlyKeys("singleProblemFact", - "problemFactList"); - assertThat(solutionDescriptor.getProblemFactCollectionMemberAccessorMap()).isEmpty(); - assertThat(solutionDescriptor.getEntityMemberAccessorMap()).containsOnlyKeys("otherEntity"); - assertThat(solutionDescriptor.getEntityCollectionMemberAccessorMap()).containsOnlyKeys("entityList"); - - var singleProblemFact = new TestdataObject("p1"); - var listAsSingleProblemFact = - new CodeAssertableArrayList<>("f1", Arrays.asList(new TestdataValue("v1"), new TestdataValue("v2"))); - var entityList = Arrays.asList(new TestdataEntity("e1"), new TestdataEntity("e2")); - var otherEntity = new TestdataEntity("otherE1"); - var solution = new TestdataExtendedAutoDiscoverGetterSolution("s1", singleProblemFact, listAsSingleProblemFact, - entityList, otherEntity); - - assertAllCodesOfCollection(solutionDescriptor.getAllEntitiesAndProblemFacts(solution), "otherE1", "f1", "p1", "e1", - "e2"); - } - @Test void testImmutableClass() { assertThatCode(TestdataRecordSolution::buildSolutionDescriptor) diff --git a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverFieldOverrideSolution.java b/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverFieldOverrideSolution.java deleted file mode 100644 index 232e2cbddf6..00000000000 --- a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverFieldOverrideSolution.java +++ /dev/null @@ -1,99 +0,0 @@ -package ai.timefold.solver.core.testdomain.solutionproperties.autodiscover; - -import java.util.List; - -import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType; -import ai.timefold.solver.core.api.domain.solution.PlanningSolution; -import ai.timefold.solver.core.api.domain.solution.ProblemFactProperty; -import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider; -import ai.timefold.solver.core.api.score.SimpleScore; -import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; -import ai.timefold.solver.core.testdomain.TestdataEntity; -import ai.timefold.solver.core.testdomain.TestdataObject; -import ai.timefold.solver.core.testdomain.TestdataValue; - -@PlanningSolution(autoDiscoverMemberType = AutoDiscoverMemberType.FIELD) -public class TestdataAutoDiscoverFieldOverrideSolution extends TestdataObject { - - public static SolutionDescriptor buildSolutionDescriptor() { - return SolutionDescriptor.buildSolutionDescriptor(TestdataAutoDiscoverFieldOverrideSolution.class, - TestdataEntity.class); - } - - private TestdataObject singleProblemFact; - @ValueRangeProvider(id = "valueRange") - private List problemFactList; - @ProblemFactProperty // would have been autodiscovered as @ProblemFactCollectionProperty - private List listProblemFact; - - private List entityList; - private TestdataEntity otherEntity; - - private SimpleScore score; - - public TestdataAutoDiscoverFieldOverrideSolution() { - } - - public TestdataAutoDiscoverFieldOverrideSolution(String code) { - super(code); - } - - public TestdataAutoDiscoverFieldOverrideSolution(String code, TestdataObject singleProblemFact, - List problemFactList, List entityList, - TestdataEntity otherEntity, List listFact) { - super(code); - this.singleProblemFact = singleProblemFact; - this.problemFactList = problemFactList; - this.entityList = entityList; - this.otherEntity = otherEntity; - this.listProblemFact = listFact; - } - - public SimpleScore getScore() { - return score; - } - - public void setScore(SimpleScore score) { - this.score = score; - } - - public TestdataObject getSingleProblemFact() { - return singleProblemFact; - } - - public void setSingleProblemFact(TestdataObject singleProblemFact) { - this.singleProblemFact = singleProblemFact; - } - - public List getProblemFactList() { - return problemFactList; - } - - public void setProblemFactList(List problemFactList) { - this.problemFactList = problemFactList; - } - - public List getListProblemFact() { - return listProblemFact; - } - - public void setListProblemFact(List listProblemFact) { - this.listProblemFact = listProblemFact; - } - - public List getEntityList() { - return entityList; - } - - public void setEntityList(List entityList) { - this.entityList = entityList; - } - - public TestdataEntity getOtherEntity() { - return otherEntity; - } - - public void setOtherEntity(TestdataEntity otherEntity) { - this.otherEntity = otherEntity; - } -} diff --git a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverFieldSolution.java b/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverFieldSolution.java deleted file mode 100644 index 18ed54fb70b..00000000000 --- a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverFieldSolution.java +++ /dev/null @@ -1,86 +0,0 @@ -package ai.timefold.solver.core.testdomain.solutionproperties.autodiscover; - -import java.util.List; - -import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType; -import ai.timefold.solver.core.api.domain.solution.PlanningSolution; -import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider; -import ai.timefold.solver.core.api.score.SimpleScore; -import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; -import ai.timefold.solver.core.testdomain.TestdataEntity; -import ai.timefold.solver.core.testdomain.TestdataObject; -import ai.timefold.solver.core.testdomain.TestdataValue; - -@PlanningSolution(autoDiscoverMemberType = AutoDiscoverMemberType.FIELD) -public class TestdataAutoDiscoverFieldSolution extends TestdataObject { - - public static SolutionDescriptor buildSolutionDescriptor() { - return SolutionDescriptor.buildSolutionDescriptor(TestdataAutoDiscoverFieldSolution.class, TestdataEntity.class); - } - - private TestdataObject singleProblemFact; - @ValueRangeProvider(id = "valueRange") - private List problemFactList; - - private List entityList; - private TestdataEntity otherEntity; - - private SimpleScore score; - - public TestdataAutoDiscoverFieldSolution() { - } - - public TestdataAutoDiscoverFieldSolution(String code) { - super(code); - } - - public TestdataAutoDiscoverFieldSolution(String code, TestdataObject singleProblemFact, - List problemFactList, List entityList, - TestdataEntity otherEntity) { - super(code); - this.singleProblemFact = singleProblemFact; - this.problemFactList = problemFactList; - this.entityList = entityList; - this.otherEntity = otherEntity; - } - - public SimpleScore getScore() { - return score; - } - - public void setScore(SimpleScore score) { - this.score = score; - } - - public TestdataObject getSingleProblemFact() { - return singleProblemFact; - } - - public void setSingleProblemFact(TestdataObject singleProblemFact) { - this.singleProblemFact = singleProblemFact; - } - - public List getProblemFactList() { - return problemFactList; - } - - public void setProblemFactList(List problemFactList) { - this.problemFactList = problemFactList; - } - - public List getEntityList() { - return entityList; - } - - public void setEntityList(List entityList) { - this.entityList = entityList; - } - - public TestdataEntity getOtherEntity() { - return otherEntity; - } - - public void setOtherEntity(TestdataEntity otherEntity) { - this.otherEntity = otherEntity; - } -} diff --git a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverGetterOverrideSolution.java b/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverGetterOverrideSolution.java deleted file mode 100644 index 24ae215d156..00000000000 --- a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverGetterOverrideSolution.java +++ /dev/null @@ -1,80 +0,0 @@ -package ai.timefold.solver.core.testdomain.solutionproperties.autodiscover; - -import java.util.List; - -import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType; -import ai.timefold.solver.core.api.domain.solution.PlanningSolution; -import ai.timefold.solver.core.api.domain.solution.ProblemFactProperty; -import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider; -import ai.timefold.solver.core.api.score.SimpleScore; -import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; -import ai.timefold.solver.core.testdomain.TestdataEntity; -import ai.timefold.solver.core.testdomain.TestdataObject; -import ai.timefold.solver.core.testdomain.TestdataValue; - -@PlanningSolution(autoDiscoverMemberType = AutoDiscoverMemberType.GETTER) -public class TestdataAutoDiscoverGetterOverrideSolution extends TestdataObject { - - public static SolutionDescriptor buildSolutionDescriptor() { - return SolutionDescriptor.buildSolutionDescriptor( - TestdataAutoDiscoverGetterOverrideSolution.class, TestdataEntity.class); - } - - private TestdataObject singleProblemFactField; - private List problemFactListField; - private List listProblemFactField; - - private List entityListField; - private TestdataEntity otherEntityField; - - private SimpleScore score; - - public TestdataAutoDiscoverGetterOverrideSolution() { - } - - public TestdataAutoDiscoverGetterOverrideSolution(String code) { - super(code); - } - - public TestdataAutoDiscoverGetterOverrideSolution(String code, TestdataObject singleProblemFact, - List problemFactList, List entityList, - TestdataEntity otherEntity, List listFact) { - super(code); - this.singleProblemFactField = singleProblemFact; - this.problemFactListField = problemFactList; - this.entityListField = entityList; - this.otherEntityField = otherEntity; - this.listProblemFactField = listFact; - } - - public TestdataObject getSingleProblemFact() { - return singleProblemFactField; - } - - @ValueRangeProvider(id = "valueRange") - public List getProblemFactList() { - return problemFactListField; - } - - @ProblemFactProperty // would have been autodiscovered as @ProblemFactCollectionProperty - public List getListProblemFact() { - return listProblemFactField; - } - - public List getEntityList() { - return entityListField; - } - - public TestdataEntity getOtherEntity() { - return otherEntityField; - } - - public SimpleScore getScore() { - return score; - } - - public void setScore(SimpleScore score) { - this.score = score; - } - -} diff --git a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverGetterSolution.java b/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverGetterSolution.java deleted file mode 100644 index 89c9123da6f..00000000000 --- a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverGetterSolution.java +++ /dev/null @@ -1,71 +0,0 @@ -package ai.timefold.solver.core.testdomain.solutionproperties.autodiscover; - -import java.util.List; - -import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType; -import ai.timefold.solver.core.api.domain.solution.PlanningSolution; -import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider; -import ai.timefold.solver.core.api.score.SimpleScore; -import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; -import ai.timefold.solver.core.testdomain.TestdataEntity; -import ai.timefold.solver.core.testdomain.TestdataObject; -import ai.timefold.solver.core.testdomain.TestdataValue; - -@PlanningSolution(autoDiscoverMemberType = AutoDiscoverMemberType.GETTER) -public class TestdataAutoDiscoverGetterSolution extends TestdataObject { - - public static SolutionDescriptor buildSolutionDescriptor() { - return SolutionDescriptor.buildSolutionDescriptor(TestdataAutoDiscoverGetterSolution.class, TestdataEntity.class); - } - - private TestdataObject singleProblemFactField; - private List problemFactListField; - - private List entityListField; - private TestdataEntity otherEntityField; - - private SimpleScore score; - - public TestdataAutoDiscoverGetterSolution() { - } - - public TestdataAutoDiscoverGetterSolution(String code) { - super(code); - } - - public TestdataAutoDiscoverGetterSolution(String code, TestdataObject singleProblemFact, - List problemFactList, List entityList, - TestdataEntity otherEntity) { - super(code); - this.singleProblemFactField = singleProblemFact; - this.problemFactListField = problemFactList; - this.entityListField = entityList; - this.otherEntityField = otherEntity; - } - - public TestdataObject getSingleProblemFact() { - return singleProblemFactField; - } - - @ValueRangeProvider(id = "valueRange") - public List getProblemFactList() { - return problemFactListField; - } - - public List getEntityList() { - return entityListField; - } - - public TestdataEntity getOtherEntity() { - return otherEntityField; - } - - public SimpleScore getScore() { - return score; - } - - public void setScore(SimpleScore score) { - this.score = score; - } - -} diff --git a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverUnannotatedEntitySolution.java b/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverUnannotatedEntitySolution.java deleted file mode 100644 index 8e7429a3870..00000000000 --- a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataAutoDiscoverUnannotatedEntitySolution.java +++ /dev/null @@ -1,74 +0,0 @@ -package ai.timefold.solver.core.testdomain.solutionproperties.autodiscover; - -import java.util.List; - -import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType; -import ai.timefold.solver.core.api.domain.solution.PlanningSolution; -import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider; -import ai.timefold.solver.core.api.score.SimpleScore; -import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; -import ai.timefold.solver.core.testdomain.TestdataObject; -import ai.timefold.solver.core.testdomain.TestdataValue; -import ai.timefold.solver.core.testdomain.inheritance.solution.baseannotated.childnot.TestdataOnlyBaseAnnotatedChildEntity; - -@PlanningSolution(autoDiscoverMemberType = AutoDiscoverMemberType.GETTER) -public class TestdataAutoDiscoverUnannotatedEntitySolution extends TestdataObject { - - public static SolutionDescriptor buildSolutionDescriptor() { - return SolutionDescriptor.buildSolutionDescriptor( - TestdataAutoDiscoverUnannotatedEntitySolution.class, TestdataOnlyBaseAnnotatedChildEntity.class); - } - - private TestdataObject singleProblemFactField; - private List problemFactListField; - - private List entityListField; - private TestdataOnlyBaseAnnotatedChildEntity otherEntityField; - - private SimpleScore score; - - public TestdataAutoDiscoverUnannotatedEntitySolution() { - } - - public TestdataAutoDiscoverUnannotatedEntitySolution(String code) { - super(code); - } - - public TestdataAutoDiscoverUnannotatedEntitySolution(String code, TestdataObject singleProblemFact, - List problemFactList, List entityList, - TestdataOnlyBaseAnnotatedChildEntity otherEntity) { - super(code); - this.singleProblemFactField = singleProblemFact; - this.problemFactListField = problemFactList; - this.entityListField = entityList; - this.otherEntityField = otherEntity; - } - - public TestdataObject getSingleProblemFact() { - return singleProblemFactField; - } - - @ValueRangeProvider(id = "valueRange") - public List getProblemFactList() { - return problemFactListField; - } - - // should be auto discovered as an entity collection - public List getEntityList() { - return entityListField; - } - - // should be auto discovered as a single entity property - public TestdataOnlyBaseAnnotatedChildEntity getOtherEntity() { - return otherEntityField; - } - - public SimpleScore getScore() { - return score; - } - - public void setScore(SimpleScore score) { - this.score = score; - } - -} diff --git a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataExtendedAutoDiscoverGetterSolution.java b/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataExtendedAutoDiscoverGetterSolution.java deleted file mode 100644 index b755b250b64..00000000000 --- a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/autodiscover/TestdataExtendedAutoDiscoverGetterSolution.java +++ /dev/null @@ -1,67 +0,0 @@ -package ai.timefold.solver.core.testdomain.solutionproperties.autodiscover; - -import java.util.List; - -import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType; -import ai.timefold.solver.core.api.domain.solution.PlanningSolution; -import ai.timefold.solver.core.api.domain.solution.ProblemFactProperty; -import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider; -import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; -import ai.timefold.solver.core.testdomain.TestdataEntity; -import ai.timefold.solver.core.testdomain.TestdataObject; -import ai.timefold.solver.core.testdomain.TestdataValue; - -@PlanningSolution(autoDiscoverMemberType = AutoDiscoverMemberType.GETTER) -public class TestdataExtendedAutoDiscoverGetterSolution extends TestdataAutoDiscoverGetterSolution { - - public static SolutionDescriptor buildSubclassSolutionDescriptor() { - return SolutionDescriptor.buildSolutionDescriptor(TestdataExtendedAutoDiscoverGetterSolution.class, - TestdataEntity.class); - } - - private TestdataObject singleProblemFactFieldOverride; - private List problemFactListFieldOverride; - - private List entityListFieldOverride; - private TestdataEntity otherEntityFieldOverride; - - public TestdataExtendedAutoDiscoverGetterSolution() { - } - - public TestdataExtendedAutoDiscoverGetterSolution(String code) { - super(code); - } - - public TestdataExtendedAutoDiscoverGetterSolution(String code, TestdataObject singleProblemFact, - List problemFactList, List entityList, - TestdataEntity otherEntity) { - super(code); - this.singleProblemFactFieldOverride = singleProblemFact; - this.problemFactListFieldOverride = problemFactList; - this.entityListFieldOverride = entityList; - this.otherEntityFieldOverride = otherEntity; - } - - @Override - public TestdataObject getSingleProblemFact() { - return singleProblemFactFieldOverride; - } - - @ProblemFactProperty // Override from a fact collection to a single fact - @ValueRangeProvider(id = "valueRange") - @Override - public List getProblemFactList() { - return problemFactListFieldOverride; - } - - @Override - public List getEntityList() { - return entityListFieldOverride; - } - - @Override - public TestdataEntity getOtherEntity() { - return otherEntityFieldOverride; - } - -} diff --git a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/invalid/TestdataUnknownFactTypeSolution.java b/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/invalid/TestdataUnknownFactTypeSolution.java deleted file mode 100644 index 7c6fc9e1db0..00000000000 --- a/core/src/test/java/ai/timefold/solver/core/testdomain/solutionproperties/invalid/TestdataUnknownFactTypeSolution.java +++ /dev/null @@ -1,48 +0,0 @@ -package ai.timefold.solver.core.testdomain.solutionproperties.invalid; - -import java.util.Collection; -import java.util.List; - -import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType; -import ai.timefold.solver.core.api.domain.solution.PlanningSolution; -import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider; -import ai.timefold.solver.core.api.score.SimpleScore; -import ai.timefold.solver.core.impl.domain.solution.descriptor.SolutionDescriptor; -import ai.timefold.solver.core.testdomain.TestdataEntity; -import ai.timefold.solver.core.testdomain.TestdataObject; -import ai.timefold.solver.core.testdomain.TestdataValue; - -@PlanningSolution(autoDiscoverMemberType = AutoDiscoverMemberType.FIELD) -public class TestdataUnknownFactTypeSolution extends TestdataObject { - - public static SolutionDescriptor buildSolutionDescriptor() { - return SolutionDescriptor.buildSolutionDescriptor(TestdataUnknownFactTypeSolution.class, - TestdataEntity.class); - } - - private List valueList; - private List entityList; - private SimpleScore score; - // this can't work with autodiscovery because it's difficult/impossible to resolve the type of collection elements - private MyStringCollection facts; - - public TestdataUnknownFactTypeSolution() { - } - - public TestdataUnknownFactTypeSolution(String code) { - super(code); - } - - @ValueRangeProvider(id = "valueRange") - public List getValueList() { - return valueList; - } - - public MyStringCollection getFacts() { - return facts; - } - - public static interface MyStringCollection extends Collection { - - } -} diff --git a/docs/TODO.md b/docs/TODO.md index df692a1d046..e020ae1ccaf 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -31,5 +31,6 @@ - [ ] domain.lookup package is gone, so is lookup from PlanningSolution. - [ ] lookups no longer accept null values. - [ ] `DomainAccessType` is gone, code uses GIZMO when possible +- [ ] `AutoDiscoverMemberType` is gone Remove this file when done. \ No newline at end of file diff --git a/docs/src/modules/ROOT/pages/using-timefold-solver/modeling-planning-problems.adoc b/docs/src/modules/ROOT/pages/using-timefold-solver/modeling-planning-problems.adoc index f59888b241b..15213918e1f 100644 --- a/docs/src/modules/ROOT/pages/using-timefold-solver/modeling-planning-problems.adoc +++ b/docs/src/modules/ROOT/pages/using-timefold-solver/modeling-planning-problems.adoc @@ -2426,7 +2426,6 @@ In rare cases, a planning entity might be a singleton: use `@PlanningEntityPrope Both annotations need to be on a member in a class with a `@PlanningSolution` annotation, and are ignored on parent classes or subclasses without that annotation. -They can also be <> if enabled. IMPORTANT: A planning solution must not contain duplicate entities, as defined by the `equals()` method of the entity class. @@ -2474,8 +2473,6 @@ public class Timetable { Some use cases use xref:constraints-and-score/overview.adoc#scoreType[other score types]. -This annotation can also be <> if enabled. - [#problemFacts] === Problem facts of a solution (`@ProblemFactCollectionProperty`) @@ -2531,8 +2528,6 @@ It is ignored on parent classes or subclasses without that annotation. In rare cases, a problem fact might be a singleton: use `@ProblemFactProperty` on its method (or field) instead. -Both annotations can also be <> if enabled. - [#cachedProblemFact] ==== Cached problem fact @@ -2580,41 +2575,6 @@ Where a score constraint needs to check that no two exams with a topic that shar the `TopicConflict` instance can be used as a problem fact, rather than having to combine every two `Student` instances. -[#autoDiscoverSolutionProperties] -=== Auto discover solution properties - -Instead of configuring each property (or field) annotation explicitly, -some can also be deduced automatically by Timefold Solver: - -[source,java,options="nowrap"] ----- -@PlanningSolution(autoDiscoverMemberType = AutoDiscoverMemberType.FIELD) -public class VehicleRoutePlan { - - ... - -} ----- - -The `AutoDiscoverMemberType` can be: - -* `NONE`: No auto discovery. -* `FIELD`: Auto discover all fields on the `@PlanningSolution` class -* `GETTER`: Auto discover all getters on the `@PlanningSolution` class - -The automatic annotation is based on the field type (or getter return type): - -* `@ProblemFactProperty`: when it isn't a `Collection`, an array, a `@PlanningEntity` class or a `Score` -* `@ProblemFactCollectionProperty`: when it's a `Collection` (or array) of a type that isn't a `@PlanningEntity` class -* `@PlanningEntityProperty`: when it is a configured `@PlanningEntity` class or subclass -* `@PlanningEntityCollectionProperty`: when it's a `Collection` (or array) of a type that is a configured `@PlanningEntity` class or subclass -* `@PlanningScore`: when it is a `Score` or subclass - -These automatic annotations can still be overwritten per field (or getter). -Specifically, a xref:constraints-and-score/overview.adoc#bendableScore[BendableScore] always needs to override -with an explicit `@PlanningScore` annotation to define the number of hard and soft levels. - - [#cloningASolution] === Cloning a solution 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 400cbb72284..4827bf74250 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 @@ -24,12 +24,8 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Singleton; -import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType; import ai.timefold.solver.core.api.domain.entity.PlanningEntity; -import ai.timefold.solver.core.api.domain.solution.PlanningEntityCollectionProperty; -import ai.timefold.solver.core.api.domain.solution.PlanningScore; import ai.timefold.solver.core.api.domain.solution.PlanningSolution; -import ai.timefold.solver.core.api.domain.solution.ProblemFactCollectionProperty; import ai.timefold.solver.core.api.domain.variable.ShadowSources; import ai.timefold.solver.core.api.domain.variable.ShadowVariable; import ai.timefold.solver.core.api.score.calculator.EasyScoreCalculator; @@ -65,7 +61,6 @@ import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.FieldInfo; @@ -1001,28 +996,6 @@ private GeneratedGizmoClasses generateDomainAccessors(Map PlanningSolution.class.getSimpleName())); } - planningSolutionAnnotationInstanceCollection.forEach(planningSolutionAnnotationInstance -> { - var autoDiscoverMemberType = planningSolutionAnnotationInstance.values().stream() - .filter(v -> v.name().equals("autoDiscoverMemberType")) - .findFirst() - .map(AnnotationValue::asEnum) - .map(AutoDiscoverMemberType::valueOf) - .orElse(AutoDiscoverMemberType.NONE); - - if (autoDiscoverMemberType != AutoDiscoverMemberType.NONE) { - throw new UnsupportedOperationException(""" - Auto-discovery of members using %s is not supported under Quarkus. - Remove the autoDiscoverMemberType property from the @%s annotation - and explicitly annotate the fields or getters with annotations such as @%s, @%s or @%s.""" - .strip() - .formatted( - AutoDiscoverMemberType.class.getSimpleName(), - PlanningSolution.class.getSimpleName(), - PlanningScore.class.getSimpleName(), - PlanningEntityCollectionProperty.class.getSimpleName(), - ProblemFactCollectionProperty.class.getSimpleName())); - } - }); var solutionClassInstance = planningSolutionAnnotationInstanceCollection.iterator().next(); var solutionClassInfo = solutionClassInstance.target().asClass(); var visited = new HashSet(); diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/TimefoldProcessorGizmoKitchenSinkAutoDiscoverFieldTest.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/TimefoldProcessorGizmoKitchenSinkAutoDiscoverFieldTest.java deleted file mode 100644 index cb9d134afe6..00000000000 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/TimefoldProcessorGizmoKitchenSinkAutoDiscoverFieldTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package ai.timefold.solver.quarkus; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; - -import ai.timefold.solver.quarkus.testdomain.gizmo.DummyConstraintProvider; -import ai.timefold.solver.quarkus.testdomain.gizmo.TestDataKitchenSinkAutoDiscoverFieldSolution; -import ai.timefold.solver.quarkus.testdomain.gizmo.TestDataKitchenSinkEntity; - -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.spec.JavaArchive; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -class TimefoldProcessorGizmoKitchenSinkAutoDiscoverFieldTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) - .addClasses(TestDataKitchenSinkAutoDiscoverFieldSolution.class, - TestDataKitchenSinkEntity.class, - DummyConstraintProvider.class)) - .assertException(t -> assertThat(t) - .isInstanceOf(UnsupportedOperationException.class) - .hasMessageContaining("autoDiscoverMemberType")); - - @Test - void solve() { - fail("The build should fail"); - } - -} diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/TimefoldProcessorGizmoKitchenSinkAutoDiscoverMethodTest.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/TimefoldProcessorGizmoKitchenSinkAutoDiscoverMethodTest.java deleted file mode 100644 index cfa7791d7e9..00000000000 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/TimefoldProcessorGizmoKitchenSinkAutoDiscoverMethodTest.java +++ /dev/null @@ -1,64 +0,0 @@ -package ai.timefold.solver.quarkus; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertSame; - -import jakarta.inject.Inject; - -import ai.timefold.solver.core.api.score.SimpleScore; -import ai.timefold.solver.core.api.solver.SolutionManager; -import ai.timefold.solver.core.api.solver.SolverFactory; -import ai.timefold.solver.core.api.solver.SolverManager; -import ai.timefold.solver.core.impl.solver.DefaultSolutionManager; -import ai.timefold.solver.core.impl.solver.DefaultSolverFactory; -import ai.timefold.solver.core.impl.solver.DefaultSolverManager; -import ai.timefold.solver.quarkus.testdomain.gizmo.DummyConstraintProvider; -import ai.timefold.solver.quarkus.testdomain.gizmo.TestDataKitchenSinkAutoDiscoverMethodSolution; -import ai.timefold.solver.quarkus.testdomain.gizmo.TestDataKitchenSinkEntity; - -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.spec.JavaArchive; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; - -class TimefoldProcessorGizmoKitchenSinkAutoDiscoverMethodTest { - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .overrideConfigKey("quarkus.timefold.solver.termination.best-score-limit", "0hard/0soft") - .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class) - .addClasses(TestDataKitchenSinkAutoDiscoverMethodSolution.class, - TestDataKitchenSinkEntity.class, - DummyConstraintProvider.class)) - .assertException(t -> assertThat(t) - .isInstanceOf(UnsupportedOperationException.class) - .hasMessageContaining("autoDiscoverMemberType")); - - @Inject - SolverFactory solverFactory; - @Inject - SolverManager solverManager; - @Inject - SolutionManager solutionManager; - - @Test - void singletonSolverFactory() { - assertNotNull(solverFactory); - // There is only one ScoreDirectorFactory instance - assertSame(((DefaultSolverFactory) solverFactory).getScoreDirectorFactory(), - ((DefaultSolutionManager) solutionManager).getScoreDirectorFactory()); - assertNotNull(solverManager); - // There is only one SolverFactory instance - assertSame(solverFactory, - ((DefaultSolverManager) solverManager).getSolverFactory()); - } - - @Test - void solve() { // The method exists only so that the class is considered a test. - throw new IllegalStateException("The test is expected to fail before it even gets here."); - } - -} diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdomain/gizmo/TestDataKitchenSinkAutoDiscoverFieldSolution.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdomain/gizmo/TestDataKitchenSinkAutoDiscoverFieldSolution.java deleted file mode 100644 index bc783031c6a..00000000000 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdomain/gizmo/TestDataKitchenSinkAutoDiscoverFieldSolution.java +++ /dev/null @@ -1,39 +0,0 @@ -package ai.timefold.solver.quarkus.testdomain.gizmo; - -import java.util.List; - -import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType; -import ai.timefold.solver.core.api.domain.solution.PlanningSolution; -import ai.timefold.solver.core.api.score.HardSoftScore; - -@PlanningSolution(autoDiscoverMemberType = AutoDiscoverMemberType.FIELD) -public class TestDataKitchenSinkAutoDiscoverFieldSolution { - - private TestDataKitchenSinkEntity planningEntityProperty; - private List planningEntityListProperty; - private String problemFactProperty; - private List problemFactListProperty; - private HardSoftScore score; - - public TestDataKitchenSinkAutoDiscoverFieldSolution() { - - } - - public TestDataKitchenSinkAutoDiscoverFieldSolution(TestDataKitchenSinkEntity planningEntityProperty, - List planningEntityListProperty, String problemFactProperty, - List problemFactListProperty, HardSoftScore score) { - this.planningEntityProperty = planningEntityProperty; - this.planningEntityListProperty = planningEntityListProperty; - this.problemFactProperty = problemFactProperty; - this.problemFactListProperty = problemFactListProperty; - this.score = score; - } - - public TestDataKitchenSinkEntity getPlanningEntityProperty() { - return planningEntityProperty; - } - - public HardSoftScore getScore() { - return score; - } -} diff --git a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdomain/gizmo/TestDataKitchenSinkAutoDiscoverMethodSolution.java b/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdomain/gizmo/TestDataKitchenSinkAutoDiscoverMethodSolution.java deleted file mode 100644 index aeb1d4f6deb..00000000000 --- a/quarkus-integration/quarkus/deployment/src/test/java/ai/timefold/solver/quarkus/testdomain/gizmo/TestDataKitchenSinkAutoDiscoverMethodSolution.java +++ /dev/null @@ -1,71 +0,0 @@ -package ai.timefold.solver.quarkus.testdomain.gizmo; - -import java.util.List; - -import ai.timefold.solver.core.api.domain.autodiscover.AutoDiscoverMemberType; -import ai.timefold.solver.core.api.domain.solution.PlanningSolution; -import ai.timefold.solver.core.api.score.HardSoftScore; - -@PlanningSolution(autoDiscoverMemberType = AutoDiscoverMemberType.GETTER) -public class TestDataKitchenSinkAutoDiscoverMethodSolution { - - private TestDataKitchenSinkEntity planningEntityProperty; - private List planningEntityListProperty; - private String problemFactProperty; - private List problemFactListProperty; - private HardSoftScore score; - - public TestDataKitchenSinkAutoDiscoverMethodSolution() { - - } - - public TestDataKitchenSinkAutoDiscoverMethodSolution(TestDataKitchenSinkEntity planningEntityProperty, - List planningEntityListProperty, String problemFactProperty, - List problemFactListProperty, HardSoftScore score) { - this.planningEntityProperty = planningEntityProperty; - this.planningEntityListProperty = planningEntityListProperty; - this.problemFactProperty = problemFactProperty; - this.problemFactListProperty = problemFactListProperty; - this.score = score; - } - - public TestDataKitchenSinkEntity getPlanningEntityProperty() { - return planningEntityProperty; - } - - public void setPlanningEntityProperty(TestDataKitchenSinkEntity planningEntityProperty) { - this.planningEntityProperty = planningEntityProperty; - } - - public List getPlanningEntityListProperty() { - return planningEntityListProperty; - } - - public void setPlanningEntityListProperty(List planningEntityListProperty) { - this.planningEntityListProperty = planningEntityListProperty; - } - - public String getProblemFactProperty() { - return problemFactProperty; - } - - public void setProblemFactProperty(String problemFactProperty) { - this.problemFactProperty = problemFactProperty; - } - - public List getProblemFactListProperty() { - return problemFactListProperty; - } - - public void setProblemFactListProperty(List problemFactListProperty) { - this.problemFactListProperty = problemFactListProperty; - } - - public HardSoftScore getScore() { - return score; - } - - public void setScore(HardSoftScore score) { - this.score = score; - } -}