Package xml

Source Code of xml.XmlPartReaderImpl$XmlPartEventFilter

package xml;

import javax.xml.stream.EventFilter;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.Iterator;

/**
* A stream reader for xml parts.<br/>
* Uses StaX to read input stream.Reads from stream until end of tag is found.
* Then reads again when getNextXmlPart is called.
*/
public class XmlPartReaderImpl implements XmlPartReader {

    private final String tag;
    private final InputStream inputStream;
    private long startPosition;
    private XMLEventReader eventReader;
    private XmlPartEventFilter eventFilter;

    private boolean initialized = false;
    private boolean isNamespaceAware = false;

    public boolean isNamespaceAware() {
        return isNamespaceAware;
    }

    public void setNamespaceAware(boolean namespaceAware) {
        isNamespaceAware = namespaceAware;
    }

    private XmlPartReaderImpl(String tag, InputStream inputStream, long startPosition) throws IOException {
        this.tag = tag;
        this.inputStream = inputStream;
        this.startPosition = startPosition;
    }

    @Override
    public Iterator<String> iterator() {
        return new XmlPartIterator(this);
    }

    public static XmlPartReaderImpl readerFor(String tag, InputStream inputStream, long startPosition) throws IOException {
        return new XmlPartReaderImpl(tag, inputStream, startPosition);
    }

    /**
     * Closes reader. Reads after calling close will cause an IOException.
     * @throws IOException
     */
    public void close() throws IOException {
        withEventReader(FUNC_CLOSE_READER);
        eventReader = null;
        inputStream.close();
    }

    private <A> A withEventReader(EventReaderFunction<A> f) throws IOException {
        if(eventReader != null) {
            return f.apply(eventReader);
        } else
            throw new IOException("Reader not yet initialized or already closed.");
    }

    private interface EventReaderFunction<A> {
        public A apply(XMLEventReader reader) throws IOException;
    }

    private final EventReaderFunction<Void> FUNC_CLOSE_READER = new EventReaderFunction<Void>() {
        @Override
        public Void apply(XMLEventReader reader) throws IOException {
            try {
                reader.close();
                return null;
            } catch (XMLStreamException e) {
                throw new IOException(e);
            }
        }
    };

    public String getNextXmlPart() throws IOException {
        if(hasNext()) {
            return withEventReader(FUNC_READ_PART);
        } else
            return null;
    }

    private final EventReaderFunction<String> FUNC_READ_PART = new EventReaderFunction<String>() {
        @Override
        public String apply(XMLEventReader reader) throws IOException {
            return readXmlPart(reader, eventFilter);
        }
    };

    private String readXmlPart(XMLEventReader xmlEventReader, XmlPartEventFilter filter) throws IOException {
        try {
            return readPart(xmlEventReader, filter);
        } catch (XMLStreamException e) {
            throw new IOException(e);
        }
    }

    private String readPart(XMLEventReader xmlEventReader, XmlPartEventFilter filter) throws XMLStreamException {
        StringWriter writer = new StringWriter();
        while (filter.isStartFound()) {
            XMLEvent event = xmlEventReader.nextEvent();
            event.writeAsEncodedUnicode(writer);
        }
        writer.flush();
        return writer.toString();
    }

    public boolean hasNext() throws IOException {
        initialize();
        return withEventReader(FUNC_HAS_NEXT);

    }

    private void initialize() throws IOException {
        if(!initialized) {
            eventFilter = new XmlPartEventFilter(tag);

            XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
            xmlInputFactory.setProperty("javax.xml.stream.isNamespaceAware", isNamespaceAware);
            try {
                XMLEventReader xmlEventReader = xmlInputFactory.createXMLEventReader(inputStream);

                if(startPosition > 0) {
                    readUntilPastStartPosition(xmlEventReader);
                }

                eventReader = xmlInputFactory.createFilteredReader(xmlEventReader, eventFilter);
                initialized = true;
            } catch (XMLStreamException e) {
                throw new IOException(e);
            }
        }
    }

    private void readUntilPastStartPosition(XMLEventReader xmlEventReader) throws XMLStreamException {
        XMLEvent xmlEvent = xmlEventReader.peek();
        while(xmlEvent.getLocation().getCharacterOffset() < startPosition) {
            xmlEvent = xmlEventReader.nextEvent();
        }
    }

    private final EventReaderFunction<Boolean> FUNC_HAS_NEXT = new EventReaderFunction<Boolean>() {
        @Override
        public Boolean apply(XMLEventReader reader) throws IOException {
            return reader.hasNext();
        }
    };

    private static class XmlPartEventFilter implements EventFilter {

        boolean startFound = false;
        private String tag;

        public XmlPartEventFilter(String tag) {
            this.tag = tag;
        }
        public boolean isStartFound() {
            return startFound;
        }
        private boolean isTag(StartElement element) {
            return tag.equals(element.getName().getLocalPart());
        }

        private boolean isTag(EndElement element) {
            return tag.equals(element.getName().getLocalPart());
        }

        @Override
        public boolean accept(XMLEvent xmlEvent) {
            if (!startFound && xmlEvent.isStartElement() && isTag(xmlEvent.asStartElement())) {
                startFound = true;
            }
            // accept everything after start is found
            // also accept closing tag
            boolean accept = startFound;

            // reset when end tag found
            if (startFound && xmlEvent.isEndElement() && isTag(xmlEvent.asEndElement())) {
                startFound = false;
            }

            return accept;
        }
    }
}
TOP

Related Classes of xml.XmlPartReaderImpl$XmlPartEventFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.