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

com.xmlcalabash.library.ValidateJing Maven / Gradle / Ivy

The newest version!
package com.xmlcalabash.library;

/*
 * ValidateWithRNG.java
 *
 * Copyright 2008 Mark Logic Corporation.
 * All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */

import com.xmlcalabash.config.JingConfigurer;
import com.xmlcalabash.core.XMLCalabash;
import com.xmlcalabash.util.Base64;
import com.xmlcalabash.util.TreeWriter;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XdmNode;
import com.xmlcalabash.io.ReadablePipe;
import com.xmlcalabash.io.WritablePipe;
import com.xmlcalabash.core.XProcRuntime;
import com.xmlcalabash.core.XProcException;
import com.xmlcalabash.core.XProcConstants;
import com.xmlcalabash.runtime.XAtomicStep;
import com.xmlcalabash.util.S9apiUtils;
import com.thaiopensource.validate.SchemaReader;
import com.thaiopensource.validate.ValidateProperty;
import com.thaiopensource.validate.ValidationDriver;
import com.thaiopensource.validate.prop.rng.RngProperty;
import com.thaiopensource.validate.auto.AutoSchemaReader;
import com.thaiopensource.validate.rng.CompactSchemaReader;
import com.thaiopensource.xml.sax.ErrorHandlerImpl;
import com.thaiopensource.util.PropertyMapBuilder;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import java.io.IOException;
import java.io.StringReader;
import java.net.URI;

/**
 * Created by IntelliJ IDEA.
 * User: ndw
 * Date: Apr 28, 2009
 * Time: 8:02:33 AM
 * To change this template use File | Settings | File Templates.
 */

@XMLCalabash(
        name = "p:validate-with-relax-ng",
        type = "{http://www.w3.org/ns/xproc}validate-with-relax-ng")

public class ValidateJing extends DefaultStep {
    private static final QName _assert_valid = new QName("", "assert-valid");
    private static final QName _dtd_attribute_values = new QName("", "dtd-attribute-values");
    private static final QName _dtd_id_idref_warnings = new QName("", "dtd-id-idref-warnings");
    private static final QName _encoding = new QName("encoding");
    private static final QName _line = new QName("line");
    private static final QName _column = new QName("column");

    private ReadablePipe source = null;
    private ReadablePipe schemaSource = null;
    private WritablePipe result = null;
    private URI docBaseURI = null;

    /* Creates a new instance of Delete */
    public ValidateJing(XProcRuntime runtime, XAtomicStep step) {
        super(runtime,step);
    }

    public void setInput(String port, ReadablePipe pipe) {
        if ("source".equals(port)) {
            source = pipe;
        } else if ("schema".equals(port)) {
            schemaSource = pipe;
        }
    }

    public void setOutput(String port, WritablePipe pipe) {
        result = pipe;
    }

    public void reset() {
        source.resetReader();
        result.resetWriter();
    }

    public void run() throws SaxonApiException {
        super.run();

        boolean assertValid = getOption(_assert_valid,true);
        boolean checkIdRefs = getOption(_dtd_id_idref_warnings,false);
        boolean dtdAugment  = getOption(_dtd_attribute_values,false);

        RNGErrorHandler eh = new RNGErrorHandler();
        PropertyMapBuilder properties = new PropertyMapBuilder();
        properties.put(ValidateProperty.ERROR_HANDLER, eh);
        properties.put(ValidateProperty.URI_RESOLVER, runtime.getResolver());
        properties.put(ValidateProperty.ENTITY_RESOLVER, runtime.getResolver());


        if (checkIdRefs) {
            RngProperty.CHECK_ID_IDREF.add(properties);
        }
        
        XdmNode doc = source.read();
        XdmNode schema = schemaSource.read();
        XdmNode root = S9apiUtils.getDocumentElement(schema);

        docBaseURI = doc.getBaseURI();

        SchemaReader sr = null;

        boolean compact = XProcConstants.c_data.equals(root.getNodeName());

        String contentType = root.getAttributeValue(XProcConstants.c_content_type);
        if (contentType != null) {
            compact |= contentType.startsWith("text/") || contentType.equals("application/relax-ng-compact-syntax");
        }

        InputSource schemaInputSource = null;
        JingConfigurer configurer = runtime.getConfigurer().getJingConfigurer();

        if (compact) {
            // Compact syntax
            configurer.configRNC(properties);
            sr = CompactSchemaReader.getInstance();

            // Grotesque hack!
            StringReader srdr = new StringReader(compactSchema(root));
            schemaInputSource = new InputSource(srdr);
            schemaInputSource.setSystemId(root.getBaseURI().toASCIIString());
        } else {
            // XML syntax
            configurer.configRNG(properties);
            sr = new AutoSchemaReader();
            schemaInputSource = S9apiUtils.xdmToInputSource(runtime, schema);
        }

        ValidationDriver driver = new ValidationDriver(properties.toPropertyMap(), sr);
        try {
            if (driver.loadSchema(schemaInputSource)) {
                InputSource din = S9apiUtils.xdmToInputSource(runtime, doc);
                if (!driver.validate(din)) {
                    if (assertValid) {
                        throw XProcException.stepError(53, step, eh.getErr());
                    }
                }
            } else {
                throw new XProcException(step, "Error loading schema");
            }
        } catch (SAXParseException e) {
            if (assertValid) {
                throw XProcException.stepError(53, step, e);
            }
        } catch (SAXException e) {
            throw new XProcException(new RuntimeException("SAX Exception", e));
        } catch (IOException e) {
            throw new XProcException(new RuntimeException("IO Exception", e));
        }

        result.write(doc); // At the moment, we don't get any augmentation
    }

    private String compactSchema(XdmNode doc) {
        if ("base64".equals(doc.getAttributeValue(_encoding))) {
            byte[] decoded = Base64.decode(doc.getStringValue());
            String s = new String(decoded);
            return s;
        } else {
            return doc.getStringValue();
        }
    }

    class RNGErrorHandler implements ErrorHandler {
        SAXParseException err = null;

        public SAXParseException getErr() {
            return err;
        }

        public void fatalError(SAXParseException e) throws SAXException {
            error(e);
        }

        public void error(SAXParseException e) throws SAXException {
            if (runtime.getShowMessages()) {
                System.err.println(e.getMessage());
            }

            TreeWriter treeWriter = new TreeWriter(runtime);
            treeWriter.startDocument(docBaseURI);
            treeWriter.addStartElement(XProcConstants.c_error);

            if (e.getLineNumber()!=-1) {
                treeWriter.addAttribute(_line, ""+e.getLineNumber());
            }

            if (e.getColumnNumber()!=-1) {
                treeWriter.addAttribute(_column, ""+e.getColumnNumber());
            }

            treeWriter.startContent();

            treeWriter.addText(e.toString());

            treeWriter.addEndElement();
            treeWriter.endDocument();

            step.reportError(treeWriter.getResult());
            if (err == null) {
                err = e;
            }
        }

        public void warning(SAXParseException e) {
            if (runtime.getShowMessages()) {
                System.err.println(e.getMessage());
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy