class SubListChangeMoveSelectorFactory<Solution_>
        extends AbstractMoveSelectorFactory<Solution_, SubListChangeMoveSelectorConfig> {

    public SubListChangeMoveSelectorFactory(SubListChangeMoveSelectorConfig moveSelectorConfig) {
        super(moveSelectorConfig);
    }

    @Override
    protected MoveSelector<Solution_> buildBaseMoveSelector(HeuristicConfigPolicy<Solution_> configPolicy,
            SelectionCacheType minimumCacheType, boolean randomSelection) {
        checkUnfolded("subListSelectorConfig", config.getSubListSelectorConfig());
        checkUnfolded("destinationSelectorConfig", config.getDestinationSelectorConfig());
        if (!randomSelection) {
            throw new IllegalArgumentException("The subListChangeMoveSelector (" + config
                    + ") only supports random selection order.");
        }

        SelectionOrder selectionOrder = SelectionOrder.fromRandomSelectionBoolean(randomSelection);

        EntitySelector<Solution_> entitySelector = EntitySelectorFactory
                .<Solution_> create(config.getDestinationSelectorConfig().getEntitySelectorConfig())
                .buildEntitySelector(configPolicy, minimumCacheType, selectionOrder);

        SubListSelector<Solution_> subListSelector = SubListSelectorFactory
                .<Solution_> create(config.getSubListSelectorConfig())
                .buildSubListSelector(configPolicy, entitySelector, minimumCacheType, selectionOrder);

        DestinationSelector<Solution_> destinationSelector = DestinationSelectorFactory
                .<Solution_> create(config.getDestinationSelectorConfig())
                .buildDestinationSelector(configPolicy, minimumCacheType, randomSelection);

        boolean selectReversingMoveToo = Objects.requireNonNullElse(config.getSelectReversingMoveToo(), true);

        return new RandomSubListChangeMoveSelector<>(subListSelector, destinationSelector, selectReversingMoveToo);
    }

    @Override
    protected MoveSelectorConfig<?> buildUnfoldedMoveSelectorConfig(HeuristicConfigPolicy<Solution_> configPolicy) {<FILL_FUNCTION_BODY>}

    private SubListChangeMoveSelectorConfig buildChildMoveSelectorConfig(ListVariableDescriptor<?> variableDescriptor) {
        SubListChangeMoveSelectorConfig subListChangeMoveSelectorConfig = config.copyConfig()
                .withSubListSelectorConfig(new SubListSelectorConfig(config.getSubListSelectorConfig())
                        .withValueSelectorConfig(Optional.ofNullable(config.getSubListSelectorConfig())
                                .map(SubListSelectorConfig::getValueSelectorConfig)
                                .map(ValueSelectorConfig::new) // use copy constructor if inherited not null
                                .orElseGet(ValueSelectorConfig::new)))
                .withDestinationSelectorConfig(new DestinationSelectorConfig(config.getDestinationSelectorConfig())
                        .withEntitySelectorConfig(
                                Optional.ofNullable(config.getDestinationSelectorConfig())
                                        .map(DestinationSelectorConfig::getEntitySelectorConfig)
                                        .map(EntitySelectorConfig::new) // use copy constructor if inherited not null
                                        .orElseGet(EntitySelectorConfig::new) // otherwise create new instance
                                        // override entity class (destination entity selector is never replaying)
                                        .withEntityClass(variableDescriptor.getEntityDescriptor().getEntityClass()))
                        .withValueSelectorConfig(
                                Optional.ofNullable(config.getDestinationSelectorConfig())
                                        .map(DestinationSelectorConfig::getValueSelectorConfig)
                                        .map(ValueSelectorConfig::new) // use copy constructor if inherited not null
                                        .orElseGet(ValueSelectorConfig::new) // otherwise create new instance
                                        // override variable name (destination value selector is never replaying)
                                        .withVariableName(variableDescriptor.getVariableName())));

        SubListSelectorConfig subListSelectorConfig = subListChangeMoveSelectorConfig.getSubListSelectorConfig();
        SubListConfigUtil.transferDeprecatedMinimumSubListSize(
                subListChangeMoveSelectorConfig,
                SubListChangeMoveSelectorConfig::getMinimumSubListSize,
                "subListSelector",
                subListSelectorConfig);
        SubListConfigUtil.transferDeprecatedMaximumSubListSize(
                subListChangeMoveSelectorConfig,
                SubListChangeMoveSelectorConfig::getMaximumSubListSize,
                "subListSelector",
                subListSelectorConfig);

        if (subListSelectorConfig.getMimicSelectorRef() == null) {
            subListSelectorConfig.getValueSelectorConfig().setVariableName(variableDescriptor.getVariableName());
        }

        return subListChangeMoveSelectorConfig;
    }
}

        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));
    
<methods>public void <init>(org.optaplanner.core.config.heuristic.selector.move.generic.list.SubListChangeMoveSelectorConfig) ,public MoveSelector<Solution_> buildMoveSelector(HeuristicConfigPolicy<Solution_>, org.optaplanner.core.config.heuristic.selector.common.SelectionCacheType, org.optaplanner.core.config.heuristic.selector.common.SelectionOrder) <variables>