package com.xenoage.zong.io.musicxml.in;
import static com.xenoage.utils.PlatformUtils.platformUtils;
import static com.xenoage.utils.log.Log.log;
import static com.xenoage.utils.log.Report.warning;
import java.io.IOException;
import com.xenoage.utils.annotations.MaybeNull;
import com.xenoage.utils.document.io.FileInput;
import com.xenoage.utils.exceptions.InvalidFormatException;
import com.xenoage.utils.io.InputStream;
import com.xenoage.utils.xml.XmlDataException;
import com.xenoage.utils.xml.XmlReader;
import com.xenoage.zong.core.Score;
import com.xenoage.zong.core.format.LayoutFormat;
import com.xenoage.zong.core.format.ScoreFormat;
import com.xenoage.zong.core.info.ScoreInfo;
import com.xenoage.zong.core.music.StavesList;
import com.xenoage.zong.io.musicxml.in.readers.LayoutFormatReader;
import com.xenoage.zong.io.musicxml.in.readers.ScoreFormatReader;
import com.xenoage.zong.io.musicxml.in.readers.ScoreInfoReader;
import com.xenoage.zong.io.musicxml.in.readers.ScoreReader;
import com.xenoage.zong.io.musicxml.in.readers.StavesListReader;
import com.xenoage.zong.io.musicxml.in.util.ErrorHandling;
import com.xenoage.zong.io.musicxml.in.util.ErrorHandling.Level;
import com.xenoage.zong.musicxml.MusicXMLDocument;
import com.xenoage.zong.musicxml.types.MxlDefaults;
import com.xenoage.zong.musicxml.types.MxlScorePartwise;
import com.xenoage.zong.musicxml.types.groups.MxlLayout;
import com.xenoage.zong.musicxml.types.groups.MxlScoreHeader;
/**
* This class reads a MusicXML 2.0 file
* into a instance of the {@link Score} class.
*
* It uses the Zong! MusicXML Library.
*
* @author Andreas Wenger
*/
public class MusicXmlScoreFileInput
implements FileInput<Score> {
/**
* Creates a new MusicXML 2.0 reader.
*/
public MusicXmlScoreFileInput() {
}
/**
* Creates a {@link Score} instance from the document
* behind the given {@link InputStream}.
* @param inputStream the input stream with the MusicXML document
* @param filePath file path if known, null otherwise
*/
@Override public Score read(InputStream stream, @MaybeNull String filePath)
throws InvalidFormatException, IOException {
//parse MusicXML file
MxlScorePartwise score;
try {
XmlReader xmlReader = platformUtils().createXmlReader(stream);
MusicXMLDocument doc = MusicXMLDocument.read(xmlReader);
score = doc.getScore();
} catch (XmlDataException ex) {
//no valid MusicXML
throw new InvalidFormatException(ex);
} catch (Exception ex) {
throw new IOException(ex);
}
return read(score, Level.LogErrors);
}
/**
* Builds a {@link Score} entity from a {@link MxlScorePartwise} document.
* @param doc the provided score-partwise document
* @param errorHandling how to deal with errors
*/
public Score read(MxlScorePartwise mxlScore, Level errorHandling)
throws InvalidFormatException {
try {
//create new score
Score score = new Score();
//read information about the score
ScoreInfo scoreInfo = new ScoreInfoReader(mxlScore.getScoreHeader()).read();
score.setInfo(scoreInfo);
//read score format
MxlScoreHeader mxlScoreHeader = mxlScore.getScoreHeader();
MxlDefaults mxlDefaults = mxlScoreHeader.getDefaults();
ScoreFormat scoreFormat = new ScoreFormatReader(mxlDefaults).read();
score.setFormat(scoreFormat);
//read layout format
MxlLayout mxlLayout = (mxlDefaults != null ? mxlDefaults.getLayout() : null);
LayoutFormat layoutFormat = new LayoutFormatReader(
mxlLayout, scoreFormat.getInterlineSpace() / 10).read();
score.setMetaData("layoutformat", layoutFormat); //TIDY
//create the list of staves
ErrorHandling mxlErrorHandling = new ErrorHandling(errorHandling);
StavesListReader stavesListReader = new StavesListReader(mxlScore, mxlErrorHandling);
StavesList stavesList = stavesListReader.read();
stavesList.setScore(score);
score.setStavesList(stavesList);
//read the musical contents
new ScoreReader(mxlScore).readToScore(score, mxlErrorHandling);
//remember the XML document for further application-dependend processing
score.setMetaData("mxldoc", mxlScore); //TIDY
//when errors were collected, log them and save them as metadata
if (mxlErrorHandling.getErrorMessages().size() > 0) {
log(warning("The file could be loaded, but the following error(s) were reported: " +
mxlErrorHandling.getErrorMessages()));
score.setMetaData("mxlerrors", mxlErrorHandling.getErrorMessages());
}
return score;
}
catch (RuntimeException ex) {
//catch runtime exceptions and rethrow them in the expected type
throw new InvalidFormatException(ex);
}
}
}