1010import java .lang .reflect .Field ;
1111import java .lang .reflect .Member ;
1212import java .lang .reflect .Method ;
13- import java .lang .reflect .ParameterizedType ;
1413import java .util .ArrayList ;
1514import java .util .Arrays ;
1615import java .util .Collection ;
3433import java .util .stream .Collectors ;
3534import java .util .stream .Stream ;
3635
37- import ai .timefold .solver .core .api .domain .autodiscover .AutoDiscoverMemberType ;
3836import ai .timefold .solver .core .api .domain .entity .PlanningEntity ;
3937import ai .timefold .solver .core .api .domain .solution .ConstraintWeightOverrides ;
4038import ai .timefold .solver .core .api .domain .solution .PlanningEntityCollectionProperty ;
@@ -139,7 +137,7 @@ public static <Solution_> SolutionDescriptor<Solution_> buildSolutionDescriptor(
139137 descriptorPolicy .setMemberAccessorFactory (solutionDescriptor .getMemberAccessorFactory ());
140138
141139 solutionDescriptor .processUnannotatedFieldsAndMethods (descriptorPolicy );
142- solutionDescriptor .processAnnotations (descriptorPolicy , entityClassList );
140+ solutionDescriptor .processAnnotations (descriptorPolicy );
143141 // Before iterating over the entity classes, we need to read the inheritance chain,
144142 // add all parent and child classes, and sort them.
145143 var updatedEntityClassList = new ArrayList <>(entityClassList );
@@ -259,7 +257,6 @@ private static boolean hasAnyAnnotatedMembers(Class<?> solutionClass) {
259257 private final MemberAccessorFactory memberAccessorFactory ;
260258
261259 private DomainAccessType domainAccessType ;
262- private AutoDiscoverMemberType autoDiscoverMemberType ;
263260 private LookUpStrategyResolver lookUpStrategyResolver ;
264261
265262 private final Map <String , MemberAccessor > problemFactMemberAccessorMap = new LinkedHashMap <>();
@@ -337,7 +334,7 @@ private void processConstraintWeights(DescriptorPolicy descriptorPolicy) {
337334 }
338335 }
339336
340- public void processAnnotations (DescriptorPolicy descriptorPolicy , List < Class <?>> entityClassList ) {
337+ public void processAnnotations (DescriptorPolicy descriptorPolicy ) {
341338 domainAccessType = descriptorPolicy .getDomainAccessType ();
342339 processSolutionAnnotations (descriptorPolicy );
343340 var potentiallyOverwritingMethodList = new ArrayList <Method >();
@@ -356,7 +353,7 @@ public void processAnnotations(DescriptorPolicy descriptorPolicy, List<Class<?>>
356353 continue ;
357354 }
358355 processValueRangeProviderAnnotation (descriptorPolicy , member );
359- processFactEntityOrScoreAnnotation (descriptorPolicy , member , entityClassList );
356+ processFactEntityOrScoreAnnotation (descriptorPolicy , member );
360357 }
361358 potentiallyOverwritingMethodList .ensureCapacity (potentiallyOverwritingMethodList .size () + memberList .size ());
362359 memberList .stream ().filter (Method .class ::isInstance )
@@ -382,7 +379,6 @@ Maybe add a getScore() method with a @%s annotation."""
382379
383380 private void processSolutionAnnotations (DescriptorPolicy descriptorPolicy ) {
384381 var annotation = extractMostRelevantPlanningSolutionAnnotation ();
385- autoDiscoverMemberType = annotation .autoDiscoverMemberType ();
386382 var solutionClonerClass = annotation .solutionCloner ();
387383 if (solutionClonerClass != PlanningSolution .NullSolutionCloner .class ) {
388384 solutionCloner = ConfigUtils .newInstance (this ::toString , "solutionClonerClass" , solutionClonerClass );
@@ -422,9 +418,9 @@ private void processValueRangeProviderAnnotation(DescriptorPolicy descriptorPoli
422418 }
423419
424420 private void processFactEntityOrScoreAnnotation (DescriptorPolicy descriptorPolicy ,
425- Member member , List < Class <?>> entityClassList ) {
426- var annotationClass = extractFactEntityOrScoreAnnotationClassOrAutoDiscover (
427- member , entityClassList );
421+ Member member ) {
422+ var annotationClass = extractFactEntityOrScoreAnnotationClass (
423+ member );
428424 if (annotationClass == null ) {
429425 return ;
430426 }
@@ -444,63 +440,12 @@ private void processFactEntityOrScoreAnnotation(DescriptorPolicy descriptorPolic
444440 }
445441 }
446442
447- private Class <? extends Annotation > extractFactEntityOrScoreAnnotationClassOrAutoDiscover (
448- Member member , List <Class <?>> entityClassList ) {
449- var annotationClass = ConfigUtils .extractAnnotationClass (member ,
443+ private static Class <? extends Annotation > extractFactEntityOrScoreAnnotationClass (Member member ) {
444+ return ConfigUtils .extractAnnotationClass (member ,
450445 ProblemFactProperty .class ,
451446 ProblemFactCollectionProperty .class ,
452447 PlanningEntityProperty .class , PlanningEntityCollectionProperty .class ,
453448 PlanningScore .class );
454- if (annotationClass == null ) {
455- Class <?> type ;
456- if (autoDiscoverMemberType == AutoDiscoverMemberType .FIELD
457- && member instanceof Field field ) {
458- type = field .getType ();
459- } else if (autoDiscoverMemberType == AutoDiscoverMemberType .GETTER
460- && (member instanceof Method method ) && ReflectionHelper .isGetterMethod (method )) {
461- type = method .getReturnType ();
462- } else {
463- type = null ;
464- }
465- if (type != null ) {
466- if (Score .class .isAssignableFrom (type )) {
467- annotationClass = PlanningScore .class ;
468- } else if (Collection .class .isAssignableFrom (type ) || type .isArray ()) {
469- Class <?> elementType ;
470- if (Collection .class .isAssignableFrom (type )) {
471- var genericType = (member instanceof Field f ) ? f .getGenericType ()
472- : ((Method ) member ).getGenericReturnType ();
473- var memberName = member .getName ();
474- if (!(genericType instanceof ParameterizedType )) {
475- throw new IllegalArgumentException (
476- """
477- The solutionClass (%s) has a auto discovered member (%s) with a member type (%s) that returns a %s which has no generic parameters.
478- Maybe the member (%s) should return a typed %s."""
479- .formatted (solutionClass , memberName , type , Collection .class .getSimpleName (),
480- memberName , Collection .class .getSimpleName ()));
481- }
482- elementType = ConfigUtils .extractGenericTypeParameter ("solutionClass" , solutionClass , type , genericType ,
483- null , member .getName ()).orElse (Object .class );
484- } else {
485- elementType = type .getComponentType ();
486- }
487- if (entityClassList .stream ().anyMatch (entityClass -> entityClass .isAssignableFrom (elementType ))) {
488- annotationClass = PlanningEntityCollectionProperty .class ;
489- } else {
490- annotationClass = ProblemFactCollectionProperty .class ;
491- }
492- } else if (Map .class .isAssignableFrom (type )) {
493- throw new IllegalStateException (
494- "The autoDiscoverMemberType (%s) does not yet support the member (%s) of type (%s) which is an implementation of %s."
495- .formatted (autoDiscoverMemberType , member , type , Map .class .getSimpleName ()));
496- } else if (entityClassList .stream ().anyMatch (entityClass -> entityClass .isAssignableFrom (type ))) {
497- annotationClass = PlanningEntityProperty .class ;
498- } else {
499- annotationClass = ProblemFactProperty .class ;
500- }
501- }
502- }
503- return annotationClass ;
504449 }
505450
506451 private void processProblemFactPropertyAnnotation (DescriptorPolicy descriptorPolicy , Member member ,
0 commit comments