package eu.esdihumboldt.hale.io.schematron.validator;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URI;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import org.opengis.cite.validation.SchematronValidator;
import eu.esdihumboldt.hale.common.core.io.IOProviderConfigurationException;
import eu.esdihumboldt.hale.common.core.io.ProgressIndicator;
import eu.esdihumboldt.hale.common.core.io.Value;
import eu.esdihumboldt.hale.common.core.io.report.IOReport;
import eu.esdihumboldt.hale.common.core.io.report.IOReporter;
import eu.esdihumboldt.hale.common.core.io.report.impl.IOMessageImpl;
import eu.esdihumboldt.hale.common.core.io.supplier.DefaultInputSupplier;
import eu.esdihumboldt.hale.common.instance.io.impl.AbstractInstanceValidator;
import eu.esdihumboldt.hale.io.schematron.util.SchematronReportParser;
import eu.esdihumboldt.hale.io.validation.ConfigurableInstanceValidator;
import eu.esdihumboldt.hale.io.validation.ValidatorConfiguration;
/***
*
* Validator for ISO Schematron
*
* @author Florian Esser
*/
public class SchematronInstanceValidator extends AbstractInstanceValidator
implements ConfigurableInstanceValidator {
/**
* Name of the parameter specifying the schematron location.
*/
public static final String PARAM_SCHEMATRON_LOCATION = "schematron.location";
/**
* Set the location of the schematron rules definition to use for
* validation.
*
* @param location the schematron location
*/
public void setSchematronLocation(URI location) {
if (location == null) {
setParameter(PARAM_SCHEMATRON_LOCATION, Value.NULL);
}
else {
setParameter(PARAM_SCHEMATRON_LOCATION, Value.of(location.toString()));
}
}
/**
* @return the location of the schematron rules definition
*/
public URI getSchematronLocation() {
String paramString = getParameter(PARAM_SCHEMATRON_LOCATION).as(String.class);
if (paramString != null) {
return URI.create(paramString);
}
return null;
}
@Override
protected IOReport execute(ProgressIndicator progress, IOReporter reporter)
throws IOProviderConfigurationException, IOException {
URI schematronLoc = getSchematronLocation();
if (schematronLoc == null) {
throw new IOProviderConfigurationException("Providing a schematron file is required");
}
progress.begin("Performing Schematron validation", ProgressIndicator.UNKNOWN);
final InputStream sourceInput = this.getSource().getInput();
if (sourceInput == null) {
throw new RuntimeException("No input for Schematron validator");
}
final Source xmlSource = new StreamSource(sourceInput);
final DefaultInputSupplier schematronInputSupplier = new DefaultInputSupplier(
schematronLoc);
final InputStream schematronInput = schematronInputSupplier.getInput();
if (schematronInput == null) {
throw new RuntimeException("No rules input for Schematron validator");
}
final Source schematronSource = new StreamSource(schematronInput);
try {
final SchematronValidator validator = new SchematronValidator(schematronSource);
final Result result = validator.validate(xmlSource, /* svrlReport */true);
final StringWriter reportWriter = new StringWriter();
SchematronUtils.convertValidatorResult(result, reportWriter);
reporter.setSuccess(!validator.ruleViolationsDetected());
if (validator.ruleViolationsDetected()) {
SchematronReportParser parser = new SchematronReportParser(reportWriter.toString());
parser.reportFailedAssertions(reporter);
}
} catch (Exception e) {
reporter.error(new IOMessageImpl("Error running schematron validation", e));
reporter.setSuccess(false);
} finally {
schematronInput.close();
progress.end();
}
return reporter;
}
@Override
protected String getReportLabel() {
return "Schematron validation";
}
@Override
protected String getDefaultFailSummary() {
return "Validating the XML file against the schematron rules failed";
}
@Override
protected String getDefaultSuccessSummary() {
return "The XML file is valid according to the schematron rules";
}
@Override
protected String getDefaultTypeName() {
return "XML file";
}
@Override
public boolean isCancelable() {
return false;
}
/**
* Checks if the validator is properly configured. This method does not call
* <code>validate()</code> from {@link AbstractInstanceValidator}.
*
* @see eu.esdihumboldt.hale.common.instance.io.impl.AbstractInstanceValidator#validate()
*/
@Override
public void validate() throws IOProviderConfigurationException {
if (this.getSchematronLocation() == null) {
throw new IOProviderConfigurationException("No schematron rules file is configured");
}
}
/**
* @see eu.esdihumboldt.hale.io.validation.ConfigurableInstanceValidator#configure(eu.esdihumboldt.hale.io.validation.ValidatorConfiguration)
*/
@Override
public void configure(ValidatorConfiguration configuration) {
this.setSchematronLocation(configuration.getLocation());
}
}