org.fryske_akademy.validation.FA_ValidationHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of teidictionaries Show documentation
Show all versions of teidictionaries Show documentation
ValidationHelpers with to and from XML methods and JAXB classes for tei dictionaries
package org.fryske_akademy.validation;
/*-
* #%L
* TeiLinguisticsFa
* %%
* Copyright (C) 2018 Fryske Akademy
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import name.dmaus.schxslt.Result;
import name.dmaus.schxslt.SchematronException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.nio.file.Files;
/**
* Can validate xml against xsd generated from fryske akademy tei dictionaries customization
*/
public class FA_ValidationHelper {
/**
* Can be used in schemaLocation attribute to import xsd groups to define complex types using
* <xs:group ref="...."/>
*/
public static final String CLASSPATH_URI_DICTIONARY_XSD = "classpath:/xsd/tei_dictionaries.xsd";
public enum XSD {
DCR_XSD("/xsd/dcr.xsd"),
XML_XSD("/xsd/xml.xsd"),
DICTIONARIES_XSD("/xsd/tei_dictionaries.xsd");
private final String xsd;
private String content;
private XSD(String xsd) {
this.xsd = xsd;
}
public String getPathInJar() {
return xsd;
}
public String getContent() throws IOException {
if (content == null) {
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
InputStream in = FA_ValidationHelper.class.getResourceAsStream(xsd);
int i = -1;
while ((i = in.read()) != -1) {
out.write(i);
}
content = out.toString();
}
return content;
}
}
private static final Schema schema;
private final static javax.xml.bind.JAXBContext JAXBCONTEXT;
static {
try {
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
schema = sf.newSchema(new Source[]{
new SAXSource(new InputSource(FA_ValidationHelper.class.getResourceAsStream(XSD.XML_XSD.getPathInJar()))),
new SAXSource(new InputSource(FA_ValidationHelper.class.getResourceAsStream(XSD.DCR_XSD.getPathInJar()))),
new SAXSource(new InputSource(FA_ValidationHelper.class.getResourceAsStream(XSD.DICTIONARIES_XSD.getPathInJar())))
});
JAXBCONTEXT = JAXBContext.newInstance("org.fryske_akademy.teidictionaries.jaxb");
} catch (SAXException | JAXBException ex) {
throw new IllegalStateException(ex);
}
}
public static T fromXML(Reader xml, Class clazz) throws JAXBException {
return fromXML(xml,clazz,true);
}
public static T fromXML(Reader xml, Class clazz, boolean validate) throws JAXBException {
Unmarshaller um = JAXBCONTEXT.createUnmarshaller();
if (validate) um.setSchema(schema);
java.lang.Object o = um.unmarshal(xml);
if (o instanceof JAXBElement) {
return ((JAXBElement)o).getValue();
} else {
return clazz.cast(o);
}
}
public static String toXML(java.lang.Object teiObject) throws JAXBException {
return toXML(teiObject,true);
}
public static String toXML(java.lang.Object teiObject, boolean validate) throws JAXBException {
Writer w = new StringWriter();
toXML(teiObject, w, validate);
return w.toString();
}
public static void toXML(java.lang.Object teiObject, Writer w, boolean validate) throws JAXBException {
Marshaller m = JAXBCONTEXT.createMarshaller();
if (validate) m.setSchema(schema);
Class c = teiObject.getClass();
if (c.isAnnotationPresent(XmlRootElement.class)) {
m.marshal(teiObject, w);
} else {
JAXBElement jb = new JAXBElement(new QName(TEINS, c.getSimpleName()), c, teiObject);
m.marshal(jb, w);
}
}
public static final String TEINS = "http://www.tei-c.org/ns/1.0";
public static JAXBContext getJAXBCONTEXT() {
return JAXBCONTEXT;
}
public static Schema getSchema() {
return schema;
}
public static void validateXml(InputStream xml) throws SAXException, IOException {
schema.newValidator().validate(new SAXSource(new InputSource(xml)));
}
public static void validateXml(Reader xml) throws SAXException, IOException {
schema.newValidator().validate(new SAXSource(new InputSource(xml)));
}
/**
* preferably use {@link FA_SchematronHelper#validate(URL)}
* @param xml
* @throws SAXException
* @throws IOException
*/
public static void validateXml(URL xml) throws SAXException, IOException {
validateXml(xml.openStream());
}
/**
* perform xsd validation and validation based on schematron.
* @param xml a url (file, classpath, network...) to the xml to be validated
*/
public static void validateXsdSchematron(URL xml) throws IOException, SchematronException, SAXException {
validateXml(xml);
validateSchematron(xml);
}
/**
* validates using schematron only
* @param xml
* @throws ValidationException when validation fails
*/
public static void validateSchematron(URL xml) throws IOException, SchematronException {
Result result = FA_SchematronHelper.validate(xml);
if (!result.isValid()) {
throw new ValidationException(result.getValidationMessages().toString());
}
}
/**
* perform sxd validation and validation based on schematron.
* @param xml the xml as a string
* @throws SAXException when validation fails, exception holds useful information
* @throws Exception if anything goes wrong
*/
public static void validateXsdSchematron(String xml) throws Exception {
validateXml(xml);
validateSchematron(xml);
}
/**
* validates using schematron only
* @param xml
* @throws ValidationException when validation fails
*/
public static void validateSchematron(String xml) throws SchematronException {
Result result = FA_SchematronHelper.validate(xml);
if (!result.isValid()) {
throw new ValidationException(result.getValidationMessages().toString());
}
}
public static void validateXml(String xml) throws SAXException, IOException {
validateXml(new StringReader(xml));
}
/**
* validate all files in first file or directory argument (no exceptions => ok)
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException, SAXException {
if (args != null && args.length > 0) {
File f = new File(args[0]);
if (f.isFile())
validateXml(f.toURI().toURL());
else if (f.isDirectory())
Files.walk(f.toPath()).filter(p -> p.toFile().isFile()).forEach(
p -> {
try {
validateXml(p.toFile().toURI().toURL());
} catch (SAXException | IOException e) {
System.err.println(p.toFile().getPath() + " invalid");
throw new RuntimeException(e);
}
}
);
else throw new IllegalArgumentException("not valid: " + args[0]);
} else throw new IllegalArgumentException("provide file or directory argument");
}
}