Innovimax-SARL/QuiXDM

View on GitHub
src/main/java/innovimax/quixproc/datamodel/in/xml/XMLQuiXEventStreamReader.java

Summary

Maintainability
C
1 day
Test Coverage
/*
 * QuiXProc: efficient evaluation of XProc Pipelines.
 * Copyright (C) 2011-2018 Innovimax
 * All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  You may obtain a copy of the License at
 *        http://www.apache.org/licenses/LICENSE-2.0*/
package innovimax.quixproc.datamodel.in.xml;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;

import innovimax.quixproc.datamodel.QuiXCharStream;
import innovimax.quixproc.datamodel.QuiXException;
import innovimax.quixproc.datamodel.event.AQuiXEvent;
import innovimax.quixproc.datamodel.in.AQuiXEventBufferStreamReader;
import innovimax.quixproc.datamodel.in.AStreamSource;
import innovimax.quixproc.datamodel.in.AStreamSource.XMLStreamSource;
import innovimax.quixproc.datamodel.in.QuiXEventStreamReader.State;

public class XMLQuiXEventStreamReader extends AQuiXEventBufferStreamReader {

    private final XMLInputFactory ifactory;
    private XMLStreamReader sreader;
    private QuiXCharStream baseURI;

    public XMLQuiXEventStreamReader() {
        this.ifactory = XMLInputFactory.newFactory();
        this.ifactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE);
        this.ifactory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE);
    }

    private AQuiXEvent load(final Source current) {
        try {
            this.sreader = this.ifactory.createXMLStreamReader(current);
        } catch (final XMLStreamException e) {
            throw new QuiXException(e);
        }
        this.baseURI = QuiXCharStream.fromSequence(current.getSystemId());
        return AQuiXEvent.getStartDocument(this.baseURI);
    }

    private QuiXCharStream charBuffer = QuiXCharStream.EMPTY;

    @Override
    public AQuiXEvent process(final CallBack callback) {
        try {
            if (!this.buffer.isEmpty()) {
                return this.buffer.poll();
            }
            AQuiXEvent event;
            if (!this.sreader.hasNext() && callback.getState() == State.START_SOURCE) {
                // special case if the buffer is empty but the document has not
                // been closed
                event = AQuiXEvent.getEndDocument(this.baseURI);
                callback.setState(State.END_SOURCE);
                return event;
            }
            if (callback.getState() == State.END_SOURCE) {
                return callback.processEndSource();
            }
            while (true) {
                final int code = this.sreader.next();
                switch (code) {
                case XMLStreamConstants.START_DOCUMENT:
                    // System.out.println("START_DOCUMENT");
                    // do nothing already opened so get next event
                    break;
                case XMLStreamConstants.START_ELEMENT:
                    // System.out.println("START_ELEMENT");
                    event = AQuiXEvent.getStartElement(QuiXCharStream.fromSequence(this.sreader.getLocalName()),
                            QuiXCharStream.fromSequence(this.sreader.getNamespaceURI()),
                            QuiXCharStream.fromSequence(this.sreader.getPrefix()));
                    event = updateText(event);
                    for (int i = 0; i < this.sreader.getNamespaceCount(); i++) {
                        this.buffer.add(
                                AQuiXEvent.getNamespace(QuiXCharStream.fromSequence(this.sreader.getNamespacePrefix(i)),
                                        QuiXCharStream.fromSequence(this.sreader.getNamespaceURI(i))));
                    }
                    for (int i = 0; i < this.sreader.getAttributeCount(); i++) {
                        this.buffer.add(AQuiXEvent.getAttribute(
                                QuiXCharStream.fromSequence(this.sreader.getAttributeLocalName(i)),
                                QuiXCharStream.fromSequence(this.sreader.getAttributeNamespace(i)),
                                QuiXCharStream.fromSequence(this.sreader.getAttributePrefix(i)),
                                QuiXCharStream.fromSequence(this.sreader.getAttributeValue(i))));
                    }
                    return event;
                case XMLStreamConstants.END_DOCUMENT:
                    // System.out.println("END_DOCUMENT");
                    event = AQuiXEvent.getEndDocument(this.baseURI);
                    event = updateText(event);
                    callback.setState(State.END_SOURCE);
                    return event;
                case XMLStreamConstants.END_ELEMENT:
                    // System.out.println("END_ELEMENT");
                    event = AQuiXEvent.getEndElement(QuiXCharStream.fromSequence(this.sreader.getLocalName()),
                            QuiXCharStream.fromSequence(this.sreader.getNamespaceURI()),
                            QuiXCharStream.fromSequence(this.sreader.getPrefix()));
                    event = updateText(event);
                    return event;
                case XMLStreamConstants.ATTRIBUTE:
                    // System.out.println("ATTRIBUTE");
                    for (int i = 0; i < this.sreader.getAttributeCount(); i++) {
                        this.buffer.add(AQuiXEvent.getAttribute(
                                QuiXCharStream.fromSequence(this.sreader.getAttributeLocalName(i)),
                                QuiXCharStream.fromSequence(this.sreader.getAttributeNamespace(i)),
                                QuiXCharStream.fromSequence(this.sreader.getAttributePrefix(i)),
                                QuiXCharStream.fromSequence(this.sreader.getAttributeValue(i))));
                    }
                    return this.buffer.poll();
                case XMLStreamConstants.CDATA:
                    // System.out.println("CDATA");
                    this.charBuffer = this.charBuffer.append(this.sreader.getText());
                    // do loop
                    break;
                case XMLStreamConstants.CHARACTERS:
                    // System.out.println("CHARACTERS");
                    this.charBuffer = this.charBuffer.append(this.sreader.getText());
                    // do loop
                    break;
                case XMLStreamConstants.SPACE:
                    // System.out.println("SPACE");
                    this.charBuffer.append(this.sreader.getText());
                    // do loop
                    break;
                case XMLStreamConstants.COMMENT:
                    // System.out.println("COMMENT");
                    event = AQuiXEvent.getComment(QuiXCharStream.fromSequence(this.sreader.getText()));
                    event = updateText(event);
                    return event;
                case XMLStreamConstants.PROCESSING_INSTRUCTION:
                    // System.out.println("PI");
                    event = AQuiXEvent.getPI(QuiXCharStream.fromSequence(this.sreader.getPITarget()),
                            QuiXCharStream.fromSequence(this.sreader.getPIData()));
                    event = updateText(event);
                    return event;
                // case XMLStreamConstants.NAMESPACE:
                // System.out.println("NAMESPACE");
                default:
                    // do loop
                    break;
                }
            }
        } catch (final XMLStreamException e) {
            throw new QuiXException(e);
        }
    }

    /**
     * This function take a QuiXEvent as parameter If there is character event
     * waiting, it creates it, empties the charbuffer and push the current event
     * in the stack. If not it return the parameter
     * 
     * @param event
     * @return
     */
    private AQuiXEvent updateText(final AQuiXEvent event) {
        if (!this.charBuffer.isEmpty()) {
            final AQuiXEvent text = AQuiXEvent.getText(this.charBuffer);
            this.charBuffer = QuiXCharStream.EMPTY;
            this.buffer.add(event);
            return text;
        }
        return event;
    }

    @Override
    public void close() {
        try {
            this.sreader.close();
        } catch (final XMLStreamException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected AQuiXEvent load(final AStreamSource current) {
        return load(((XMLStreamSource) current).asSource());
    }
}