diff --git a/optaplanner-core/src/main/java/org/optaplanner/core/impl/domain/solution/AbstractSolution.java b/optaplanner-core/src/main/java/org/optaplanner/core/impl/domain/solution/AbstractSolution.java index 0c90a4676b..7d931836f2 100644 --- a/optaplanner-core/src/main/java/org/optaplanner/core/impl/domain/solution/AbstractSolution.java +++ b/optaplanner-core/src/main/java/org/optaplanner/core/impl/domain/solution/AbstractSolution.java @@ -21,6 +21,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Map; import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty; @@ -50,21 +51,25 @@ public void setScore(S score) { } /** - * Convenience method for tests. - * - * @return All entities from anywhere in this class' hierarchy. + * @return a list with every problem fact that is in a field of this class + * (directly or indirectly as an element of a {@link Collection} or {@link Map} field) */ @ProblemFactCollectionProperty - protected Collection getProblemFacts() { - Class instanceClass = getClass(); - return getProblemFactsFromClass(instanceClass); + protected List getProblemFactList() { + List factList = new ArrayList(); + addProblemFactsFromClass(factList, getClass()); + return factList; } - private Collection getProblemFactsFromClass(Class instanceClass) { - Collection factList = new ArrayList<>(); + /** + * Adds to an existing to {@link List} to avoid copying the entire list with {@link List#addAll(Collection)}. + * @param factList never null + * @param instanceClass never null + */ + private void addProblemFactsFromClass(List factList, Class instanceClass) { if (instanceClass.equals(AbstractSolution.class)) { // The field score should not be included - return factList; + return; } for (Field field : instanceClass.getDeclaredFields()) { field.setAccessible(true); @@ -91,9 +96,8 @@ private Collection getProblemFactsFromClass(Class instanceClass) { } Class superclass = instanceClass.getSuperclass(); if (superclass != null) { - factList.addAll(getProblemFactsFromClass(superclass)); + addProblemFactsFromClass(factList, superclass); } - return factList; } private boolean isFieldAPlanningEntityPropertyOrPlanningEntityCollectionProperty(Field field, diff --git a/optaplanner-core/src/main/java/org/optaplanner/core/impl/domain/solution/mutation/MutationCounter.java b/optaplanner-core/src/main/java/org/optaplanner/core/impl/domain/solution/mutation/MutationCounter.java index 47b3c0c10b..383794b903 100644 --- a/optaplanner-core/src/main/java/org/optaplanner/core/impl/domain/solution/mutation/MutationCounter.java +++ b/optaplanner-core/src/main/java/org/optaplanner/core/impl/domain/solution/mutation/MutationCounter.java @@ -49,7 +49,7 @@ public int countMutations(Solution_ a, Solution_ b) { for (Iterator aIt = aEntities.iterator(), bIt = bEntities.iterator(); aIt.hasNext() && bIt.hasNext(); ) { Object aEntity = aIt.next(); Object bEntity = bIt.next(); - for (GenuineVariableDescriptor variableDescriptor : entityDescriptor.getGenuineVariableDescriptors()) { + for (GenuineVariableDescriptor variableDescriptor : entityDescriptor.getGenuineVariableDescriptors()) { // TODO broken if the value is an entity, because then it's never the same // But we don't want to depend on value/entity equals() => use surrogate entity id's to compare // https://issues.jboss.org/browse/PLANNER-170 @@ -70,4 +70,5 @@ public int countMutations(Solution_ a, Solution_ b) { public String toString() { return "MutationCounter(" + solutionDescriptor + ")"; } + } diff --git a/optaplanner-core/src/test/java/org/optaplanner/core/impl/domain/solution/AbstractSolutionTest.java b/optaplanner-core/src/test/java/org/optaplanner/core/impl/domain/solution/AbstractSolutionTest.java index 94640e2dad..0514dbf344 100644 --- a/optaplanner-core/src/test/java/org/optaplanner/core/impl/domain/solution/AbstractSolutionTest.java +++ b/optaplanner-core/src/test/java/org/optaplanner/core/impl/domain/solution/AbstractSolutionTest.java @@ -16,7 +16,6 @@ package org.optaplanner.core.impl.domain.solution; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -63,7 +62,7 @@ public void getProblemFacts() { solution.setSingleEntity(singleEntity); SimpleScore score = SimpleScore.valueOf(-10); solution.setScore(score); - assertCollectionContainsExactly((Collection) solution.getProblemFacts(), singleValue, v1, v2, v3); + assertCollectionContainsExactly(solution.getProblemFactList(), singleValue, v1, v2, v3); } @Test @@ -78,7 +77,7 @@ public void getProblemFactsWithNullField() { solution.setEntityList(null); solution.setSingleEntity(null); solution.setScore(null); - assertCollectionContainsExactly((Collection) solution.getProblemFacts(), v1, v2, v3); + assertCollectionContainsExactly(solution.getProblemFactList(), v1, v2, v3); } public static class TestdataAbstractSolutionBasedSolution extends AbstractSolution { diff --git a/optaplanner-core/src/test/java/org/optaplanner/core/impl/testdata/domain/extended/abstractsolution/TestdataExtendedAbstractSolution.java b/optaplanner-core/src/test/java/org/optaplanner/core/impl/testdata/domain/extended/abstractsolution/TestdataExtendedAbstractSolution.java index 7e0d2ccc18..591e25cc3a 100644 --- a/optaplanner-core/src/test/java/org/optaplanner/core/impl/testdata/domain/extended/abstractsolution/TestdataExtendedAbstractSolution.java +++ b/optaplanner-core/src/test/java/org/optaplanner/core/impl/testdata/domain/extended/abstractsolution/TestdataExtendedAbstractSolution.java @@ -19,11 +19,14 @@ import java.util.List; import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty; +import org.optaplanner.core.api.domain.solution.drools.ProblemFactCollectionProperty; import org.optaplanner.core.api.domain.solution.drools.ProblemFactProperty; import org.optaplanner.core.api.domain.solution.PlanningSolution; +import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider; import org.optaplanner.core.impl.domain.solution.AbstractSolution; import org.optaplanner.core.impl.domain.solution.descriptor.SolutionDescriptor; import org.optaplanner.core.impl.testdata.domain.TestdataEntity; +import org.optaplanner.core.impl.testdata.domain.TestdataValue; @PlanningSolution public class TestdataExtendedAbstractSolution extends AbstractSolution { @@ -32,6 +35,7 @@ public static SolutionDescriptor buildSolutionDescriptor() { return SolutionDescriptor.buildSolutionDescriptor(TestdataExtendedAbstractSolution.class, TestdataEntity.class); } + private List valueList; private Object extraObject; private List entityList; @@ -40,6 +44,16 @@ public TestdataExtendedAbstractSolution(String code) { super(); } + @ValueRangeProvider(id = "valueRange") + @ProblemFactCollectionProperty + public List getValueList() { + return valueList; + } + + public void setValueList(List valueList) { + this.valueList = valueList; + } + @ProblemFactProperty public Object getExtraObject() { return extraObject;