package com.xenoage.zong.musicxml.types; import static com.xenoage.utils.NullUtils.notNull; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; import com.xenoage.utils.annotations.MaybeNull; import com.xenoage.utils.annotations.NonNull; import com.xenoage.utils.xml.XmlReader; import com.xenoage.utils.xml.XmlWriter; import com.xenoage.zong.musicxml.types.attributes.MxlPosition; import com.xenoage.zong.musicxml.types.choice.MxlNotationsContent; import com.xenoage.zong.musicxml.types.enums.MxlPlacement; import com.xenoage.zong.musicxml.types.enums.MxlStartStopContinue; import com.xenoage.zong.musicxml.types.util.MxlPlacementContent; import com.xenoage.zong.musicxml.types.util.MxlPositionContent; import com.xenoage.zong.musicxml.util.IncompleteMusicXML; /** * MusicXML slur or tied. * * @author Andreas Wenger */ @IncompleteMusicXML(missing = "line-type,orientation,color") @AllArgsConstructor @Getter @Setter public final class MxlSlurOrTied implements MxlNotationsContent, MxlPositionContent, MxlPlacementContent { public static final String elemNameSlur = "slur"; public static final String elemNameTied = "tied"; public enum MxlElementType { Slur, Tied; } @NonNull private MxlElementType elementType; @NonNull private MxlStartStopContinue type; /** May be null for tied elements, but never null for slurs. */ @MaybeNull private Integer number; private MxlPosition position; private MxlPlacement placement; @MaybeNull private MxlBezier bezier; private static final int defaultNumberForSlur = 1; @Override public MxlNotationsContentType getNotationsContentType() { return MxlNotationsContentType.SlurOrTied; } @MaybeNull public static MxlSlurOrTied read(XmlReader reader) { //element type MxlElementType elementType = null; String eName = reader.getElementName(); if (elemNameSlur.equals(eName)) elementType = MxlElementType.Slur; else if (elemNameTied.equals(eName)) elementType = MxlElementType.Tied; else throw reader.dataException("slur or tied expected"); //type MxlStartStopContinue type = MxlStartStopContinue.read(reader.getAttribute("type")); if (type == MxlStartStopContinue.Continue && elementType == MxlElementType.Tied) throw reader.dataException("tied can not be continued"); //other members Integer number = reader.getAttributeInt("number"); if (elementType == MxlElementType.Slur) number = notNull(number, defaultNumberForSlur); MxlPosition position = MxlPosition.read(reader); MxlPlacement placement = MxlPlacement.read(reader); MxlBezier bezier = MxlBezier.read(reader); return new MxlSlurOrTied(elementType, type, number, position, placement, bezier); } @Override public void write(XmlWriter writer) { writer.writeElementStart(elementType == MxlElementType.Slur ? elemNameSlur : elemNameTied); writer.writeAttribute("type", type.write()); writer.writeAttribute("number", number); position.write(writer); placement.write(writer); if (bezier != null) bezier.write(writer); writer.writeElementEnd(); } }