in core/optaplanner-core-impl/src/main/java/org/optaplanner/core/impl/heuristic/selector/move/generic/list/ListChangeMoveSelectorFactory.java [93:169]
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 listChangeMoveSelector (" + config
+ ") cannot unfold when there are multiple entities (" + entityDescriptors + ")."
+ " Please use one listChangeMoveSelector per each planning list variable.");
}
EntityDescriptor<Solution_> entityDescriptor = entityDescriptors.iterator().next();
List<ListVariableDescriptor<Solution_>> variableDescriptorList = new ArrayList<>();
GenuineVariableDescriptor<Solution_> onlyVariableDescriptor = config.getValueSelectorConfig() == null ? null
: ValueSelectorFactory.<Solution_> create(config.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 (onlyVariableDescriptor != null && onlyDestinationVariableDescriptor != null) {
if (!onlyVariableDescriptor.isListVariable()) {
throw new IllegalArgumentException("The listChangeMoveSelector (" + config
+ ") is configured to use a planning variable (" + onlyVariableDescriptor
+ "), which is not a planning list variable."
+ " Either fix your annotations and use a @" + PlanningListVariable.class.getSimpleName()
+ " on the variable to make it work with listChangeMoveSelector"
+ " or use a changeMoveSelector instead.");
}
if (!onlyDestinationVariableDescriptor.isListVariable()) {
throw new IllegalArgumentException("The destinationSelector (" + config.getDestinationSelectorConfig()
+ ") is configured to use a planning variable (" + onlyDestinationVariableDescriptor
+ "), which is not a planning list variable.");
}
if (onlyVariableDescriptor != onlyDestinationVariableDescriptor) {
throw new IllegalArgumentException("The listChangeMoveSelector's valueSelector ("
+ config.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_>) onlyVariableDescriptor);
} else {
variableDescriptorList.addAll(
entityDescriptor.getGenuineVariableDescriptorList().stream()
.filter(GenuineVariableDescriptor::isListVariable)
.map(variableDescriptor -> ((ListVariableDescriptor<Solution_>) variableDescriptor))
.collect(Collectors.toList()));
}
if (variableDescriptorList.isEmpty()) {
throw new IllegalArgumentException("The listChangeMoveSelector (" + config
+ ") cannot unfold because there are no planning list variables.");
}
if (variableDescriptorList.size() > 1) {
throw new IllegalArgumentException("The listChangeMoveSelector (" + config
+ ") cannot unfold because there are multiple planning list variables.");
}
ListChangeMoveSelectorConfig listChangeMoveSelectorConfig = buildChildMoveSelectorConfig(
variableDescriptorList.get(0),
config.getValueSelectorConfig(),
config.getDestinationSelectorConfig());
listChangeMoveSelectorConfig.inheritFolded(config);
return listChangeMoveSelectorConfig;
}