All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fryske_akademy.validation.FA_ValidationHelper Maven / Gradle / Ivy

Go to download

ValidationHelpers with to and from XML methods and JAXB classes for tei dictionaries

There is a newer version: 5.9
Show newest version
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");
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy