protected MoveSelectorConfig buildUnfoldedMoveSelectorConfig()

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));
    }