package com.xenoage.zong.musiclayout.notation;
import static com.xenoage.utils.collections.CollectionUtils.alist;
import static com.xenoage.utils.collections.CollectionUtils.map;
import java.util.HashMap;
import java.util.List;
import com.xenoage.zong.core.music.ColumnElement;
import com.xenoage.zong.core.music.MusicElement;
import com.xenoage.zong.core.music.beam.Beam;
import com.xenoage.zong.core.music.beam.BeamWaypoint;
import com.xenoage.zong.core.music.chord.Chord;
import lombok.Data;
/**
* Collection of already computed {@link Notation}s.
*
* A {@link Notation} is queried by the {@link MusicElement} it belongs
* to. Also a staff index may be given, because for {@link ColumnElement}s
* the same element is found on all staves but with different notations.
*
* When querying for an element, the staff index can also be provided. If
* nothing can be found at the given staff, the staff-less cache is used.
* But if an element is registered with a staff but searched for without
* a staff, it won't be found.
*
* @author Andreas Wenger
*/
public class Notations {
@Data private static class StaffElement {
final MusicElement element;
final int staff;
}
private HashMap<Object, Notation> notations;
public Notations() {
this.notations = map();
}
/**
* Adds the given {@link Notation}.
* If already there, it is replaced. Use this method only for elements which appear
* only on a single staff (like chords or clefs). If they may appear on multiple
* staves (like time signatures), use {@link #add(Notation, int)} instead.
*/
public void add(Notation notation) {
if (notation != null)
notations.put(notation.getElement(), notation);
}
/**
* Adds the given {@link Notation}, that belongs to the given and staff.
* If already there, it is replaced.
*/
public void add(Notation notation, int staff) {
if (notation != null)
notations.put(new StaffElement(notation.getElement(), staff), notation);
}
@Deprecated
public void merge(Notations cache) {
this.notations.putAll(cache.notations);
}
/**
* Gets the {@link Notation}, that belongs to the given {@link MusicElement},
* or null if unknown. It will also return null if the element was registered
* with a staff before. See {@link #add(Notation, MusicElement)}.
*/
public Notation get(MusicElement element) {
return notations.get(element);
}
/**
* Gets the {@link Notation}, that belongs to the given {@link MusicElement}
* and staff index. If it is not found there, the staff-less cache is searched.
* If still not found, null is returned.
*/
public Notation get(MusicElement element, int staff) {
Notation ret = notations.get(new StaffElement(element, staff));
if (ret == null)
ret = notations.get(element);
return ret;
}
/**
* Gets the {@link ChordNotation}, that belongs to the given {@link Chord}.
* If the notation does not exist yet, it is created.
*/
public ChordNotation getChord(Chord chord) {
ChordNotation ret = (ChordNotation) get(chord);
if (ret == null)
add(ret = new ChordNotation(chord));
return ret;
}
/**
* Gets the {@link ChordNotation}s of the given {@link Beam}.
*/
public List<ChordNotation> getBeamChords(Beam beam) {
List<ChordNotation> ret = alist(beam.size());
for (BeamWaypoint wp : beam.getWaypoints())
ret.add(getChord(wp.getChord()));
return ret;
}
public int size() {
return notations.size();
}
@Override public String toString() {
return "[" + getClass().getSimpleName() + " with " + notations.size() + " elements]";
}
}