001/*
002 * Java Genetic Algorithm Library (jenetics-7.2.0).
003 * Copyright (c) 2007-2023 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019 */
020package io.jenetics.ext.internal.util;
021
022import static java.util.Objects.requireNonNull;
023
024import java.util.Spliterator;
025import java.util.function.Consumer;
026import java.util.function.Function;
027
028/**
029 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
030 * @version 4.1
031 * @since 4.1
032 */
033public class GeneratorSpliterator<T> implements Spliterator<T> {
034
035        private final Function<? super T, ? extends Spliterator<T>> _generator;
036
037        private Spliterator<T> _current;
038        private T _element;
039
040        public GeneratorSpliterator(
041                final Function<? super T, ? extends Spliterator<T>> generator
042        ) {
043                _generator = requireNonNull(generator);
044        }
045
046        @Override
047        public boolean tryAdvance(final Consumer<? super T> action) {
048                requireNonNull(action);
049
050                final boolean advance = spliterator().tryAdvance(element -> {
051                        action.accept(element);
052                        _element = element;
053                });
054
055                if (!advance) {
056                        _current = null;
057                }
058
059                return true;
060        }
061
062        @Override
063        public Spliterator<T> trySplit() {
064                return new GeneratorSpliterator<>(_generator);
065        }
066
067        @Override
068        public long estimateSize() {
069                return Long.MAX_VALUE;
070        }
071
072        @Override
073        public int characteristics() {
074                return Spliterator.ORDERED;
075        }
076
077        private Spliterator<T> spliterator() {
078                if (_current == null) {
079                        _current = _generator.apply(_element);
080                }
081
082                return _current;
083        }
084
085}