private void processValueRangeAnnotation() {
   Method propertyGetter = variablePropertyAccessor.getReadMethod();
   ValueRange valueRangeAnnotation = propertyGetter.getAnnotation(ValueRange.class);
   ValueRanges valueRangesAnnotation = propertyGetter.getAnnotation(ValueRanges.class);
   if (valueRangeAnnotation != null) {
     if (valueRangesAnnotation != null) {
       throw new IllegalArgumentException(
           "The planningEntityClass ("
               + planningEntityDescriptor.getPlanningEntityClass()
               + ") has a PlanningVariable annotated property ("
               + variablePropertyAccessor.getName()
               + ") that has a @ValueRange and @ValueRanges annotation: fold them into 1 @ValueRanges.");
     }
     valueRangeDescriptor = buildValueRangeDescriptor(valueRangeAnnotation);
   } else {
     if (valueRangesAnnotation == null) {
       throw new IllegalArgumentException(
           "The planningEntityClass ("
               + planningEntityDescriptor.getPlanningEntityClass()
               + ") has a PlanningVariable annotated property ("
               + variablePropertyAccessor.getName()
               + ") that has no @ValueRange or @ValueRanges annotation.");
     }
     List<PlanningValueRangeDescriptor> valueRangeDescriptorList =
         new ArrayList<PlanningValueRangeDescriptor>(valueRangesAnnotation.value().length);
     for (ValueRange partialValueRangeAnnotation : valueRangesAnnotation.value()) {
       valueRangeDescriptorList.add(buildValueRangeDescriptor(partialValueRangeAnnotation));
     }
     valueRangeDescriptor =
         new CompositePlanningValueRangeDescriptor(this, valueRangeDescriptorList);
   }
 }
 private void processChained(PlanningVariable planningVariableAnnotation) {
   chained = planningVariableAnnotation.chained();
   if (chained
       && !variablePropertyAccessor
           .getPropertyType()
           .isAssignableFrom(planningEntityDescriptor.getPlanningEntityClass())) {
     throw new IllegalArgumentException(
         "The planningEntityClass ("
             + planningEntityDescriptor.getPlanningEntityClass()
             + ") has a PlanningVariable annotated property ("
             + variablePropertyAccessor.getName()
             + ") with chained ("
             + chained
             + ") and propertyType ("
             + variablePropertyAccessor.getPropertyType()
             + ") which is not a superclass/interface of or the same as the planningEntityClass ("
             + planningEntityDescriptor.getPlanningEntityClass()
             + ").");
   }
   if (chained && nullable) {
     throw new IllegalArgumentException(
         "The planningEntityClass ("
             + planningEntityDescriptor.getPlanningEntityClass()
             + ") has a PlanningVariable annotated property ("
             + variablePropertyAccessor.getName()
             + ") with chained ("
             + chained
             + "), which is not compatible with nullable ("
             + nullable
             + ").");
   }
 }
 private void processNullable(PlanningVariable planningVariableAnnotation) {
   nullable = planningVariableAnnotation.nullable();
   if (nullable && variablePropertyAccessor.getPropertyType().isPrimitive()) {
     throw new IllegalArgumentException(
         "The planningEntityClass ("
             + planningEntityDescriptor.getPlanningEntityClass()
             + ") has a PlanningVariable annotated property ("
             + variablePropertyAccessor.getName()
             + ") with nullable ("
             + nullable
             + "), which is not compatible with the primitive propertyType ("
             + variablePropertyAccessor.getPropertyType()
             + ").");
   }
   Class<? extends SelectionFilter> reinitializeVariableEntityFilterClass =
       planningVariableAnnotation.reinitializeVariableEntityFilter();
   if (reinitializeVariableEntityFilterClass
       == PlanningVariable.NullReinitializeVariableEntityFilter.class) {
     reinitializeVariableEntityFilterClass = null;
   }
   if (reinitializeVariableEntityFilterClass != null) {
     reinitializeVariableEntityFilter =
         ConfigUtils.newInstance(
             this, "reinitializeVariableEntityFilterClass", reinitializeVariableEntityFilterClass);
   } else {
     reinitializeVariableEntityFilter = new NullValueReinitializeVariableEntityFilter(this);
   }
 }
 private void processStrength(PlanningVariable planningVariableAnnotation) {
   Class<? extends Comparator> strengthComparatorClass =
       planningVariableAnnotation.strengthComparatorClass();
   if (strengthComparatorClass == PlanningVariable.NullStrengthComparator.class) {
     strengthComparatorClass = null;
   }
   Class<? extends SelectionSorterWeightFactory> strengthWeightFactoryClass =
       planningVariableAnnotation.strengthWeightFactoryClass();
   if (strengthWeightFactoryClass == PlanningVariable.NullStrengthWeightFactory.class) {
     strengthWeightFactoryClass = null;
   }
   if (strengthComparatorClass != null && strengthWeightFactoryClass != null) {
     throw new IllegalStateException(
         "The planningEntityClass ("
             + planningEntityDescriptor.getPlanningEntityClass()
             + ") property ("
             + variablePropertyAccessor.getName()
             + ") cannot have a strengthComparatorClass ("
             + strengthComparatorClass.getName()
             + ") and a strengthWeightFactoryClass ("
             + strengthWeightFactoryClass.getName()
             + ") at the same time.");
   }
   if (strengthComparatorClass != null) {
     Comparator<Object> strengthComparator =
         ConfigUtils.newInstance(this, "strengthComparatorClass", strengthComparatorClass);
     valueSorter.setStrengthComparator(strengthComparator);
   }
   if (strengthWeightFactoryClass != null) {
     SelectionSorterWeightFactory strengthWeightFactory =
         ConfigUtils.newInstance(this, "strengthWeightFactoryClass", strengthWeightFactoryClass);
     valueSorter.setStrengthWeightFactory(strengthWeightFactory);
   }
 }
 @Override
 public String toString() {
   return getClass().getSimpleName()
       + "("
       + variablePropertyAccessor.getName()
       + " of "
       + planningEntityDescriptor.getPlanningEntityClass().getName()
       + ")";
 }
 public String getVariableName() {
   return variablePropertyAccessor.getName();
 }