<commit_before>/*
 * Copyright 2012 JBoss Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.optaplanner.core.impl.heuristic.selector.move.composite;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import org.apache.commons.collections.IteratorUtils;
import org.optaplanner.core.impl.heuristic.selector.common.iterator.UpcomingSelectionIterator;
import org.optaplanner.core.impl.heuristic.selector.move.MoveSelector;
import org.optaplanner.core.impl.move.CompositeMove;
import org.optaplanner.core.impl.move.Move;

/**
 * A {@link CompositeMoveSelector} that cartesian products 2 or more {@link MoveSelector}s.
 * <p/>
 * For example: a cartesian product of {A, B, C} and {X, Y} will result in {AX, AY, BX, BY, CX, CY}.
 * <p/>
 * Warning: there is no duplicated {@link Move} check, so union of {A, B} and {B} will result in {AB, BB}.
 * @see CompositeMoveSelector
 */
public class CartesianProductMoveSelector extends CompositeMoveSelector {

    public CartesianProductMoveSelector(List<MoveSelector> childMoveSelectorList, boolean randomSelection) {
        super(childMoveSelectorList, randomSelection);
    }

    // ************************************************************************
    // Worker methods
    // ************************************************************************

    public boolean isNeverEnding() {
        if (randomSelection) {
            return true;
        } else {
            // Only the last childMoveSelector can be neverEnding
            return !childMoveSelectorList.isEmpty()
                    && childMoveSelectorList.get(childMoveSelectorList.size() - 1).isNeverEnding();
        }
    }

    public long getSize() {
        long size = 1L;
        for (MoveSelector moveSelector : childMoveSelectorList) {
            size *= moveSelector.getSize();
        }
        return size;
    }

    public Iterator<Move> iterator() {
        if (!randomSelection) {
            return new OriginalCartesianProductMoveIterator();
        } else {
            return new RandomCartesianProductMoveIterator();
        }
    }

    public class OriginalCartesianProductMoveIterator extends UpcomingSelectionIterator<Move> {

        private List<Iterator<Move>> moveIteratorList;

        private List<Move> subSelections;

        public OriginalCartesianProductMoveIterator() {
            moveIteratorList = new ArrayList<Iterator<Move>>(childMoveSelectorList.size());
            subSelections = new ArrayList<Move>(childMoveSelectorList.size());
            for (int i = 0; i < childMoveSelectorList.size(); i++) {
                if (i == 0) {
                    moveIteratorList.add(childMoveSelectorList.get(i).iterator());
                } else {
                    moveIteratorList.add(IteratorUtils.emptyListIterator());
                }
                subSelections.add(null);
            }
        }

        @Override
        protected void createUpcomingSelection() {
            List<Move> moveList = new ArrayList<Move>(subSelections); // Clone to avoid CompositeMove corruption
            for (int i = moveIteratorList.size() - 1; i >= 0; i--) {
                Iterator<Move> moveIterator =  moveIteratorList.get(i);
                if (moveIterator.hasNext()) {
                    moveList.set(i, moveIterator.next());
                    break;
                }
                if (i == 0) {
                    upcomingSelection = null;
                    return;
                }
                moveIterator = childMoveSelectorList.get(i).iterator();
                moveIteratorList.set(i, moveIterator);
                if (!moveIterator.hasNext()) { // in case a moveIterator is empty
                    upcomingSelection = null;
                    return;
                }
                moveList.set(i, moveIterator.next());
            }
            // No need to clone to avoid CompositeMove corruption because subSelections's elements never change
            subSelections = moveList;
            upcomingSelection = new CompositeMove(moveList);
        }

    }

    public class RandomCartesianProductMoveIterator implements Iterator<Move> {

        private List<Iterator<Move>> moveIteratorList;
        private boolean empty;

        public RandomCartesianProductMoveIterator() {
            moveIteratorList = new ArrayList<Iterator<Move>>(childMoveSelectorList.size());
            empty = false;
            for (MoveSelector moveSelector : childMoveSelectorList) {
                Iterator<Move> moveIterator = moveSelector.iterator();
                if (!moveIterator.hasNext()) {
                    empty = true;
                }
                moveIteratorList.add(moveIterator);
            }
        }

        public boolean hasNext() {
            return !empty;
        }
<commit_msg>All selector Iterators must not do hasNext() in their constructor: CartesianProductMoveSelector<commit_after>/*
 * Copyright 2012 JBoss Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.optaplanner.core.impl.heuristic.selector.move.composite;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import org.apache.commons.collections.IteratorUtils;
import org.optaplanner.core.impl.heuristic.selector.common.iterator.UpcomingSelectionIterator;
import org.optaplanner.core.impl.heuristic.selector.move.MoveSelector;
import org.optaplanner.core.impl.move.CompositeMove;
import org.optaplanner.core.impl.move.Move;

/**
 * A {@link CompositeMoveSelector} that cartesian products 2 or more {@link MoveSelector}s.
 * <p/>
 * For example: a cartesian product of {A, B, C} and {X, Y} will result in {AX, AY, BX, BY, CX, CY}.
 * <p/>
 * Warning: there is no duplicated {@link Move} check, so union of {A, B} and {B} will result in {AB, BB}.
 * @see CompositeMoveSelector
 */
public class CartesianProductMoveSelector extends CompositeMoveSelector {

    public CartesianProductMoveSelector(List<MoveSelector> childMoveSelectorList, boolean randomSelection) {
        super(childMoveSelectorList, randomSelection);
    }

    // ************************************************************************
    // Worker methods
    // ************************************************************************

    public boolean isNeverEnding() {
        if (randomSelection) {
            return true;
        } else {
            // Only the last childMoveSelector can be neverEnding
            return !childMoveSelectorList.isEmpty()
                    && childMoveSelectorList.get(childMoveSelectorList.size() - 1).isNeverEnding();
        }
    }

    public long getSize() {
        long size = 1L;
        for (MoveSelector moveSelector : childMoveSelectorList) {
            size *= moveSelector.getSize();
        }
        return size;
    }

    public Iterator<Move> iterator() {
        if (!randomSelection) {
            return new OriginalCartesianProductMoveIterator();
        } else {
            return new RandomCartesianProductMoveIterator();
        }
    }

    public class OriginalCartesianProductMoveIterator extends UpcomingSelectionIterator<Move> {

        private List<Iterator<Move>> moveIteratorList;

        private List<Move> subSelections;

        public OriginalCartesianProductMoveIterator() {
            moveIteratorList = new ArrayList<Iterator<Move>>(childMoveSelectorList.size());
            subSelections = new ArrayList<Move>(childMoveSelectorList.size());
            for (int i = 0; i < childMoveSelectorList.size(); i++) {
                if (i == 0) {
                    moveIteratorList.add(childMoveSelectorList.get(i).iterator());
                } else {
                    moveIteratorList.add(IteratorUtils.emptyListIterator());
                }
                subSelections.add(null);
            }
        }

        @Override
        protected void createUpcomingSelection() {
            List<Move> moveList = new ArrayList<Move>(subSelections); // Clone to avoid CompositeMove corruption
            for (int i = moveIteratorList.size() - 1; i >= 0; i--) {
                Iterator<Move> moveIterator =  moveIteratorList.get(i);
                if (moveIterator.hasNext()) {
                    moveList.set(i, moveIterator.next());
                    break;
                }
                if (i == 0) {
                    upcomingSelection = null;
                    return;
                }
                moveIterator = childMoveSelectorList.get(i).iterator();
                moveIteratorList.set(i, moveIterator);
                if (!moveIterator.hasNext()) { // in case a moveIterator is empty
                    upcomingSelection = null;
                    return;
                }
                moveList.set(i, moveIterator.next());
            }
            // No need to clone to avoid CompositeMove corruption because subSelections's elements never change
            subSelections = moveList;
            upcomingSelection = new CompositeMove(moveList);
        }

    }

    public class RandomCartesianProductMoveIterator implements Iterator<Move> {

        private List<Iterator<Move>> moveIteratorList;
        private Boolean empty;

        public RandomCartesianProductMoveIterator() {
            moveIteratorList = new ArrayList<Iterator<Move>>(childMoveSelectorList.size());
            empty = null;
            for (MoveSelector moveSelector : childMoveSelectorList) {
                moveIteratorList.add(moveSelector.iterator());
            }
        }

        public boolean hasNext() {
            if (empty == null) {
                empty = false;
                for (Iterator<Move> moveIterator : moveIteratorList) {
                    if (!moveIterator.hasNext()) {
                        empty = true;
                        break;
                    }
                }
            }
            return !empty;
        }

{'fraction_non_alphanumeric': 0.11433493517091305, 'fraction_numerical': 0.0029014416538217427, 'mean_word_length': 2.3123123123123124, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2504142', 'n_tokens_mistral': 2798, 'n_tokens_neox': 2641, 'n_words': 729}