package com.compomics.util.pride.validation; import com.sun.msv.verifier.jarv.TheFactoryImpl; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.net.URL; import org.iso_relax.verifier.Schema; import org.iso_relax.verifier.Verifier; import org.iso_relax.verifier.VerifierConfigurationException; import org.iso_relax.verifier.VerifierFactory; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; /** * PRIDE XML schema validation. * * @author Phil Jones * @author Florian Reisinger * @author Harald Barsnes */ public class PrideXmlValidator { /** * The verifier factory. */ public static final VerifierFactory VERIFIER_FACTORY = new TheFactoryImpl(); /** * The schema. */ private static Schema SCHEMA = null; /** * The schema name. */ private static final String SCHEMA_NAME = "pride.xsd"; /** * The XML validation error handler. */ private XMLValidationErrorHandler xveh; /** * The maximum number of error messages to display in the message to the * user before referring to the error log. */ private int maxErrorMessagesToDisplay = 10; /** * Set up a PrideXmlValidator using the default schema. * * @throws IOException if an IOException occurs * @throws VerifierConfigurationException if a * VerifierConfigurationException occurs * @throws SAXException if a SAXException occurs */ public PrideXmlValidator() throws IOException, VerifierConfigurationException, SAXException { SCHEMA = VERIFIER_FACTORY.compileSchema(PrideXmlValidator.class.getClassLoader().getResourceAsStream(SCHEMA_NAME)); } /** * Set up a PrideXmlValidator using the provided schema. * * @param schemaUrl the URL to the schema * @throws IOException if an IOException occurs * @throws VerifierConfigurationException if a * VerifierConfigurationException occurs * @throws SAXException if a SAXException occurs */ public PrideXmlValidator(URL schemaUrl) throws IOException, VerifierConfigurationException, SAXException { SCHEMA = VERIFIER_FACTORY.compileSchema(schemaUrl.openStream()); } /** * Set the schema. * * @param schemaUrl the schema to set * @throws IOException if an IOException occurs * @throws VerifierConfigurationException if a * VerifierConfigurationException occurs * @throws SAXException if a SAXException occurs */ public void setSchema(URL schemaUrl) throws IOException, VerifierConfigurationException, SAXException { SCHEMA = VERIFIER_FACTORY.compileSchema(schemaUrl.openStream()); } /** * Validate the file in the reader according to the given schema. * * @param reader the reader containing the file to validate * @param schema the schema to validate against * @return an XMLValidationErrorHandler object with the error details, if * any * @throws IOException if an IOException occurs * @throws VerifierConfigurationException if a * VerifierConfigurationException occurs * @throws SAXException if a SAXException occurs */ private XMLValidationErrorHandler validate(Reader reader, Schema schema) throws IOException, VerifierConfigurationException, SAXException { XMLValidationErrorHandler xmlValidationErrorHandler = new XMLValidationErrorHandler(); Verifier schemaVerifier = schema.newVerifier(); schemaVerifier.setErrorHandler(xmlValidationErrorHandler); try { schemaVerifier.verify(new InputSource(reader)); } catch (SAXParseException e) { xmlValidationErrorHandler.error(e); } return xmlValidationErrorHandler; } /** * Validate the file in the reader according to the default PRIDE XML * schema. * * @param reader the reader containing the file to validate * @return an XMLValidationErrorHandler object with the error details, if * any * @throws IOException if an IOException occurs * @throws VerifierConfigurationException if a * VerifierConfigurationException occurs * @throws SAXException if a SAXException occurs */ private XMLValidationErrorHandler validate(Reader reader) throws IOException, VerifierConfigurationException, SAXException { if (SCHEMA == null) { SCHEMA = VERIFIER_FACTORY.compileSchema(PrideXmlValidator.class.getClassLoader().getResourceAsStream(SCHEMA_NAME)); } return validate(reader, SCHEMA); } /** * Returns true of the given PRIDE XML file is valid. * * @param prideXmlFile the PRIDE XML file to test * @return true of the given PRIDE XML file is valid * @throws FileNotFoundException if a FileNotFoundException occurs * @throws IOException if an IOException occurs * @throws VerifierConfigurationException if a * VerifierConfigurationException occurs * @throws SAXException if a SAXException occurs */ public boolean validate(File prideXmlFile) throws FileNotFoundException, IOException, VerifierConfigurationException, SAXException { PrideXmlValidator validator = new PrideXmlValidator(); BufferedReader br = new BufferedReader(new FileReader(prideXmlFile)); xveh = validator.validate(br); br.close(); return xveh.noErrors(); } /** * Returns the errors formatted as s single string. Returns null if the file * has not been validated. * * @return the errors formatted as s single string, null if the file has not * yet been validated */ public String getErrorsAsString() { if (xveh == null) { return "The file has not yet been validated!"; } if (xveh.getErrorsAsList().isEmpty()) { return "There are no errors."; } if (xveh.getErrorsAsList().size() > maxErrorMessagesToDisplay) { System.out.println(xveh.getErrorsFormattedAsPlainText()); return "The PRIDE XML file contains errors. See the tool's log file for details." + "\n\nPlease contact the developers."; } else { System.out.println(xveh.getErrorsFormattedAsPlainText()); return "The PRIDE XML file contains errors:" + xveh.getErrorsFormattedAsPlainText() + "\n\nPlease contact the developers."; } } /** * Returns the XML validation error object. Returns null if the file has not * been validated. * * @return the XML validation error object, null if the file has not yet * been validated */ public XMLValidationErrorHandler getErrors() { return xveh; } }