in core/optaplanner-core-impl/src/main/java/org/optaplanner/core/impl/heuristic/selector/move/generic/list/SubListChangeMoveSelectorFactory.java [89:160]
protected MoveSelectorConfig<?> buildUnfoldedMoveSelectorConfig(HeuristicConfigPolicy<Solution_> configPolicy) {
Collection<EntityDescriptor<Solution_>> entityDescriptors;
EntityDescriptor<Solution_> onlyEntityDescriptor = config.getDestinationSelectorConfig() == null ? null
: config.getDestinationSelectorConfig().getEntitySelectorConfig() == null ? null
: EntitySelectorFactory
.<Solution_> create(config.getDestinationSelectorConfig().getEntitySelectorConfig())
.extractEntityDescriptor(configPolicy);
if (onlyEntityDescriptor != null) {
entityDescriptors = Collections.singletonList(onlyEntityDescriptor);
} else {
entityDescriptors = configPolicy.getSolutionDescriptor().getGenuineEntityDescriptors();
}
if (entityDescriptors.size() > 1) {
throw new IllegalArgumentException("The subListChangeMoveSelector (" + config
+ ") cannot unfold when there are multiple entities (" + entityDescriptors + ")."
+ " Please use one subListChangeMoveSelector per each planning list variable.");
}
EntityDescriptor<Solution_> entityDescriptor = entityDescriptors.iterator().next();
List<ListVariableDescriptor<Solution_>> variableDescriptorList = new ArrayList<>();
GenuineVariableDescriptor<Solution_> onlySubListVariableDescriptor =
config.getSubListSelectorConfig() == null ? null
: config.getSubListSelectorConfig().getValueSelectorConfig() == null ? null
: ValueSelectorFactory
.<Solution_> create(config.getSubListSelectorConfig().getValueSelectorConfig())
.extractVariableDescriptor(configPolicy, entityDescriptor);
GenuineVariableDescriptor<Solution_> onlyDestinationVariableDescriptor =
config.getDestinationSelectorConfig() == null ? null
: config.getDestinationSelectorConfig().getValueSelectorConfig() == null ? null
: ValueSelectorFactory
.<Solution_> create(config.getDestinationSelectorConfig().getValueSelectorConfig())
.extractVariableDescriptor(configPolicy, entityDescriptor);
if (onlySubListVariableDescriptor != null && onlyDestinationVariableDescriptor != null) {
if (!onlySubListVariableDescriptor.isListVariable()) {
throw new IllegalArgumentException("The subListChangeMoveSelector (" + config
+ ") is configured to use a planning variable (" + onlySubListVariableDescriptor
+ "), which is not a planning list variable.");
}
if (!onlyDestinationVariableDescriptor.isListVariable()) {
throw new IllegalArgumentException("The subListChangeMoveSelector (" + config
+ ") is configured to use a planning variable (" + onlyDestinationVariableDescriptor
+ "), which is not a planning list variable.");
}
if (onlySubListVariableDescriptor != onlyDestinationVariableDescriptor) {
throw new IllegalArgumentException("The subListSelector's valueSelector ("
+ config.getSubListSelectorConfig().getValueSelectorConfig()
+ ") and destinationSelector's valueSelector ("
+ config.getDestinationSelectorConfig().getValueSelectorConfig()
+ ") must be configured for the same planning variable.");
}
if (onlyEntityDescriptor != null) {
// No need for unfolding or deducing
return null;
}
variableDescriptorList.add((ListVariableDescriptor<Solution_>) onlySubListVariableDescriptor);
} else {
variableDescriptorList.addAll(
entityDescriptor.getGenuineVariableDescriptorList().stream()
.filter(GenuineVariableDescriptor::isListVariable)
.map(variableDescriptor -> ((ListVariableDescriptor<Solution_>) variableDescriptor))
.collect(Collectors.toList()));
}
if (variableDescriptorList.isEmpty()) {
throw new IllegalArgumentException("The subListChangeMoveSelector (" + config
+ ") cannot unfold because there are no planning list variables.");
}
if (variableDescriptorList.size() > 1) {
throw new IllegalArgumentException("The subListChangeMoveSelector (" + config
+ ") cannot unfold because there are multiple planning list variables.");
}
return buildChildMoveSelectorConfig(variableDescriptorList.get(0));
}