package com.xenoage.zong.io.midi.out.repetitions; import com.xenoage.utils.annotations.Const; import com.xenoage.utils.collections.CList; import com.xenoage.utils.collections.IList; import com.xenoage.utils.kernel.Countable; import com.xenoage.zong.core.position.MP; import com.xenoage.zong.core.position.Time; import lombok.EqualsAndHashCode; import lombok.ToString; import lombok.val; import java.util.Iterator; import java.util.List; import static com.xenoage.utils.collections.CList.clist; /** * This class stores the repetitions in a score by * remembering the sequential repetitions which have end be played, * defined by start and end {@link MP}s. * * Consecutive {@link Repetition}s are merged, e.g. * "measure 1 to measure 3" and "measure 3 to measure 4" * are merged to "measure 1 to measure 4". * * @author Andreas Wenger */ @Const @EqualsAndHashCode @ToString public final class Repetitions implements Iterable<Repetition>, Countable { /** The list of repetitions in chronological order. */ private final IList<Repetition> repetitions; public Repetitions(List<Repetition> repetitions) { this.repetitions = mergeRepetitions(repetitions); } public Repetition get(int index) { return repetitions.get(index); } @Override public int getCount() { return repetitions.size(); } static IList<Repetition> mergeRepetitions(List<Repetition> repetitions) { CList<Repetition> merged = clist(); //merge consecutive repetitions Time start = null; Time end = null; for (val repetition : repetitions) { if (start == null) { //first repetition start = repetition.start; end = repetition.end; } else if (repetition.start.equals(end)) { //this repetition begins at the ending of the last one; continue it end = repetition.end; } else { //new repetition found. remember old one and start new one merged.add(new Repetition(start, end)); start = repetition.start; end = repetition.end; } } if (start != null) { //close last repetition merged.add(new Repetition(start, end)); } return merged.close(); } @Override public Iterator<Repetition> iterator() { return repetitions.iterator(); } }