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

io.repseq.gen.ConcatenatedLazySequence Maven / Gradle / Ivy

package io.repseq.gen;

import com.milaboratory.core.Range;
import com.milaboratory.core.sequence.Sequence;
import com.milaboratory.core.sequence.SequenceBuilder;
import com.milaboratory.core.sequence.provider.SequenceProvider;

public final class ConcatenatedLazySequence> implements SequenceProvider {
    private final SequenceProvider[] providers;
    private int size = -1;

    public ConcatenatedLazySequence(SequenceProvider[] providers) {
        this.providers = providers;
    }

    @Override
    public int size() {
        if (size == -1) {
            int totalLength = 0;
            for (SequenceProvider p : providers)
                totalLength += p.size();
            size = totalLength;
        }
        return size;
    }

    @Override
    public S getRegion(Range range) {
        if (range.getUpper() > size())
            throw new IllegalArgumentException("Can't get sequence outside defined region.");
        Range direct = range.isReverse() ? new Range(range.getLower(), range.getUpper()) : range;
        SequenceBuilder seq = null;
        for (SequenceProvider provider : providers) {
            if (provider.size() <= direct.getLower())
                direct = direct.move(-provider.size());
            else {
                Range targetRange;
                if (direct.getUpper() <= provider.size()) {
                    targetRange = direct;
                    direct = null;
                } else {
                    Range r = new Range(0, provider.size());
                    targetRange = direct.intersection(r);
                    assert targetRange != null;
                    direct = new Range(0, direct.getUpper() - provider.size());
                }
                S currentSeq = provider.getRegion(targetRange);
                if (seq == null)
                    seq = currentSeq.getBuilder().ensureCapacity(range.length()).append(currentSeq);
                else
                    seq.append(currentSeq);
                if (direct == null)
                    break;
            }
        }
        assert seq != null;
        S result = seq.createAndDestroy();
        return range.isReverse() ? result.getRange(result.size(), 0) : result;
    }
}