All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dmfs.rfc5545.iterable.instanceiterator.Composite Maven / Gradle / Ivy

/*
 * Copyright 2022 Marten Gajda 
 *
 *
 * 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.dmfs.rfc5545.iterable.instanceiterator;

import org.dmfs.jems2.comparator.By;
import org.dmfs.jems2.iterable.Mapped;
import org.dmfs.jems2.iterable.Seq;
import org.dmfs.jems2.iterable.Sieved;
import org.dmfs.jems2.single.Collected;
import org.dmfs.rfc5545.iterable.InstanceIterator;

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


/**
 * An {@link InstanceIterator} which iterates the elements of other {@link InstanceIterator} in chronological order.
 *
 * @deprecated in favour of {@link org.dmfs.rfc5545.instanceiterator.Merged}
 */
@Deprecated
public final class Composite implements InstanceIterator
{
    private List mHelpers;


    public Composite(InstanceIterator... delegates)
    {
        this(new Seq<>(delegates));
    }


    public Composite(Iterable delegates)
    {
        mHelpers = new Collected<>(
            ArrayList::new,
            new Mapped<>(
                Helper::new,
                new Sieved<>(
                    InstanceIterator::hasNext,
                    delegates))).value();
        Collections.sort(mHelpers, new By<>(helper -> helper.nextValue));

        // resolve duplicates
        for (int i = mHelpers.size(); i > 1; --i)
        {
            if (mHelpers.get(i - 1).nextValue == mHelpers.get(i - 2).nextValue)
            {
                if (mHelpers.get(i - 1).iterator.hasNext())
                {
                    bubbleUp(i - 1);
                }
                else
                {
                    mHelpers.remove(i - 1);
                }
            }
        }
    }


    @Override
    public boolean hasNext()
    {
        return mHelpers.size() > 0;
    }


    @Override
    public long next()
    {
        if (!hasNext())
        {
            throw new NoSuchElementException("No more elements to iterate");
        }
        long result = mHelpers.get(0).nextValue;
        advance();
        return result;
    }


    @Override
    public void fastForward(long until)
    {
        for (int i = mHelpers.size() - 1; i >= 0; --i)
        {
            Helper it = mHelpers.get(i);
            if (it.nextValue < until)
            {
                it.iterator.fastForward(until);
                if (it.iterator.hasNext())
                {
                    it.nextValue = it.iterator.next();
                }
                else
                {
                    mHelpers.remove(i);
                }
            }
        }
        Collections.sort(mHelpers, new By<>(helper -> helper.nextValue));
    }


    private void advance()
    {
        if (mHelpers.size() == 1)
        {
            Helper helper = mHelpers.get(0);
            if (helper.iterator.hasNext())
            {
                helper.nextValue = helper.iterator.next();
            }
            else
            {
                mHelpers.clear();
            }
        }
        else
        {
            Helper helper = mHelpers.get(0);
            if (helper.iterator.hasNext())
            {
                bubbleUp(0);
            }
            else
            {
                mHelpers.remove(0);
            }
        }
    }


    private void bubbleUp(int pos)
    {
        // pull the next element and let it bubble up to its position
        final List helpers = mHelpers;
        Helper first = helpers.get(pos);
        long next = first.iterator.next();
        while (pos < helpers.size() - 1 && next >= helpers.get(pos + 1).nextValue)
        {
            if (next == helpers.get(pos + 1).nextValue)
            {
                // value already present, skip this one
                if (first.iterator.hasNext())
                {
                    next = first.iterator.next();
                }
                else
                {
                    // this one has no more elements
                    helpers.remove(pos);
                    return;
                }
            }
            helpers.set(pos, helpers.get(pos + 1));
            pos++;
        }
        first.nextValue = next;
        helpers.set(pos, first);
    }


    private final static class Helper
    {
        private long nextValue;
        private final InstanceIterator iterator;


        private Helper(InstanceIterator iterator)
        {
            this(iterator.next(), iterator);
        }


        private Helper(long nextValue, InstanceIterator iterator)
        {
            this.nextValue = nextValue;
            this.iterator = iterator;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy