package com.compomics.util.experiment.quantification.reporterion;
import com.compomics.util.experiment.biology.ions.ElementaryIon;
import com.compomics.util.experiment.biology.ions.ReporterIon;
import com.compomics.util.experiment.personalization.ExperimentObject;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
/**
* This factory imports reporter methods details from an XMl file.
*
* @author Marc Vaudel
* @author Harald Barsnes
*/
public class ReporterMethodFactory extends ExperimentObject {
/**
* The reporter methods names.
*/
private ArrayList<String> methodsNames;
/**
* The reporter methods.
*/
private HashMap<String, ReporterMethod> methods;
/**
* The reporter factory.
*/
private static ReporterMethodFactory instance = null;
/**
* Constructor.
*/
private ReporterMethodFactory() {
}
/**
* Constructor for the factory.
*
* @return the reporter method factory
*/
public static ReporterMethodFactory getInstance() {
if (instance == null) {
instance = new ReporterMethodFactory();
}
return instance;
}
/**
* Returns the methods implemented in the factory.
*
* @return the methods implemented in the factory
*/
public HashMap<String, ReporterMethod> getMethods() {
return methods;
}
/**
* Returns the name of the methods present in the factory.
*
* @return the name of the methods present in the factory
*/
public ArrayList<String> getMethodsNames() {
return methodsNames;
}
/**
* Returns the methods names as array.
*
* @return the methods names
*/
public String[] getMethodsNamesAsArray() {
String[] array = methodsNames.toArray(new String[methodsNames.size()]);
return array;
}
/**
* Returns the reporter methods corresponding to the given name.
*
* @param methodName the name of the method
*
* @return the reporter methods
*/
public ReporterMethod getReporterMethod(String methodName) {
return methods.get(methodName);
}
/**
* Save to file.
*
* @param aFile the file to save to
*
* @throws IOException thrown whenever a problem occurred while writing the
* file
*/
public void saveFile(File aFile) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter(aFile));
try {
String indent = "\t";
writer.write("<xml>");
writer.newLine();
for (String reporterMethodName : methodsNames) {
ReporterMethod reporterMethod = methods.get(reporterMethodName);
writer.write(indent + "<reporterMethod>");
writer.newLine();
writer.write(indent + indent + "<name>" + reporterMethod.getName() + "</name>");
writer.newLine();
writer.write(indent + indent + "<reagentList>");
writer.newLine();
ArrayList<String> reagentNames = new ArrayList<String>(reporterMethod.getReagentsSortedByMass());
for (String reagentName : reagentNames) {
Reagent reagent = reporterMethod.getReagent(reagentName);
writer.write(indent + indent + indent + "<reagent>");
writer.newLine();
writer.write(indent + indent + indent + indent + "<name>" + reagent.getName() + "</name>");
writer.newLine();
writer.write(indent + indent + indent + indent + "<monoisotopicMz>" + (reagent.getReporterIon().getTheoreticMz(1)) + "</monoisotopicMz>");
writer.newLine();
writer.write(indent + indent + indent + indent + "<minus2>" + reagent.getMinus2() + "</minus2>");
writer.newLine();
writer.write(indent + indent + indent + indent + "<minus1>" + reagent.getMinus1() + "</minus1>");
writer.newLine();
writer.write(indent + indent + indent + indent + "<ref>" + reagent.getRef() + "</ref>");
writer.newLine();
writer.write(indent + indent + indent + indent + "<plus1>" + reagent.getPlus1() + "</plus1>");
writer.newLine();
writer.write(indent + indent + indent + indent + "<plus2>" + reagent.getPlus2() + "</plus2>");
writer.newLine();
writer.write(indent + indent + indent + "</reagent>");
writer.newLine();
}
writer.write(indent + indent + "</reagentList>");
writer.newLine();
writer.write(indent + "</reporterMethod>");
writer.newLine();
}
writer.write("</xml>");
writer.newLine();
} finally {
writer.close();
}
}
/**
* Imports the methods from an XML file.
*
* @param aFile the XML file
* @throws IOException exception thrown whenever an error occurred while
* reading the file
* @throws XmlPullParserException exception thrown whenever an error
* occurred while parsing the XML file
*/
public void importMethods(File aFile) throws IOException, XmlPullParserException {
methodsNames = new ArrayList<String>();
methods = new HashMap<String, ReporterMethod>();
// create the pull parser
XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
factory.setNamespaceAware(true);
XmlPullParser parser = factory.newPullParser();
// create a reader for the input file
BufferedReader br = new BufferedReader(new FileReader(aFile));
try {
// set the XML Pull Parser to read from this reader
parser.setInput(br);
// start the parsing
int type = parser.next();
// go through the whole document
while (type != XmlPullParser.END_DOCUMENT) {
// if we find a 'reporterMethod' start tag, we should parse the mod
if (type == XmlPullParser.START_TAG && parser.getName().equals("reporterMethod")) {
ReporterMethod reporterMethod = parseMethod(parser);
String methodName = reporterMethod.getName();
methodsNames.add(methodName);
methods.put(methodName, reporterMethod);
}
type = parser.next();
}
} finally {
br.close();
}
}
/**
* Parses a bloc describing a reporter method.
*
* @param parser the XML parser
* @throws IOException exception thrown whenever an error occurred while
* reading the file
* @throws XmlPullParserException exception thrown whenever an error
* occurred while parsing the XML file
*/
private ReporterMethod parseMethod(XmlPullParser parser) throws XmlPullParserException, IOException {
int type = parser.next();
while (type != XmlPullParser.START_TAG || !parser.getName().equals("name")) {
type = parser.next();
}
type = parser.next();
String name = parser.getText().trim();
// list of reagents
ArrayList<Reagent> reagents = new ArrayList<Reagent>();
// iterate the reagents
while (type != XmlPullParser.END_TAG || !parser.getName().equals("reagentList")) {
// create the empry reagent
Reagent reagent = new Reagent();
// reagent name
while (type != XmlPullParser.START_TAG || !parser.getName().equals("name")) {
type = parser.next();
if (type == XmlPullParser.END_TAG && parser.getName().equals("reagentList")) {
throw new IllegalArgumentException("Unexpected end of reagent list when parsing method " + name + ".");
}
}
type = parser.next();
String reagentName = parser.getText().trim();
reagent.setName(reagentName);
ReporterIon reporterIon = ReporterIon.getReporterIon(reagentName);
// monoisotopic m/z or minus 2
while (type != XmlPullParser.START_TAG || (!parser.getName().equals("monoisotopicMz") && !parser.getName().equals("minus2"))) {
type = parser.next();
if (type == XmlPullParser.END_TAG && parser.getName().equals("reagent")) {
throw new IllegalArgumentException("Unexpected end of reagent details when parsing reagent " + reagentName + " in method " + name + ".");
}
}
if (parser.getName().equals("monoisotopicMz")) {
type = parser.next();
Double monoisotopicMass = new Double(parser.getText().trim());
reporterIon = new ReporterIon(reagentName, monoisotopicMass - ElementaryIon.proton.getTheoreticMass());
// minus 2
while (type != XmlPullParser.START_TAG || !parser.getName().equals("minus2")) {
type = parser.next();
if (type == XmlPullParser.END_TAG && parser.getName().equals("reagent")) {
throw new IllegalArgumentException("Unexpected end of reagent details when parsing reagent " + reagentName + " in method " + name + ".");
}
}
} else if (!parser.getName().equals("minus2")) {
throw new IllegalArgumentException("Found " + parser.getName() + " start tag where minus2 was expected.");
}
if (reporterIon == null) {
throw new IllegalArgumentException("No mass found for reporter ion " + reagentName + ".");
}
reagent.setReporterIon(reporterIon);
type = parser.next();
Double correctionFactor = new Double(parser.getText().trim());
reagent.setMinus2(correctionFactor);
// minus 1
while (type != XmlPullParser.START_TAG || !parser.getName().equals("minus1")) {
type = parser.next();
if (type == XmlPullParser.END_TAG && parser.getName().equals("reagent")) {
throw new IllegalArgumentException("Unexpected end of reagent details when parsing reagent " + reagentName + " in method " + name + ".");
}
}
type = parser.next();
correctionFactor = new Double(parser.getText().trim());
reagent.setMinus1(correctionFactor);
// ref
while (type != XmlPullParser.START_TAG || !parser.getName().equals("ref")) {
type = parser.next();
if (type == XmlPullParser.END_TAG && parser.getName().equals("reagent")) {
throw new IllegalArgumentException("Unexpected end of reagent details when parsing reagent " + reagentName + " in method " + name + ".");
}
}
type = parser.next();
correctionFactor = new Double(parser.getText().trim());
reagent.setRef(correctionFactor);
// plus 1
while (type != XmlPullParser.START_TAG || !parser.getName().equals("plus1")) {
type = parser.next();
if (type == XmlPullParser.END_TAG && parser.getName().equals("reagent")) {
throw new IllegalArgumentException("Unexpected end of reagent details when parsing reagent " + reagentName + " in method " + name + ".");
}
}
type = parser.next();
correctionFactor = new Double(parser.getText().trim());
reagent.setPlus1(correctionFactor);
// plus 2
while (type != XmlPullParser.START_TAG || !parser.getName().equals("plus2")) {
type = parser.next();
if (type == XmlPullParser.END_TAG && parser.getName().equals("reagent")) {
throw new IllegalArgumentException("Unexpected end of reagent details when parsing reagent " + reagentName + " in method " + name + ".");
}
}
type = parser.next();
correctionFactor = new Double(parser.getText().trim());
reagent.setPlus2(correctionFactor);
// add the reagent to the list
reagents.add(reagent);
// move to the next reagent
while (type != XmlPullParser.END_TAG || !parser.getName().equals("reagent")) {
type = parser.next();
}
type = parser.next();
while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_TAG) {
type = parser.next();
}
}
return new ReporterMethod(name, reagents);
}
}