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

org.n52.svalbard.read.XmlReader Maven / Gradle / Ivy

/*
 * Copyright 2016-2017 52°North Initiative for Geospatial Open Source
 * Software GmbH
 *
 * 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.
 */
package org.n52.svalbard.read;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.n52.svalbard.decode.exception.DecodingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Optional;
import com.google.common.collect.Iterables;

public abstract class XmlReader {
    private static final Logger LOG = LoggerFactory.getLogger(XmlReader.class);
    private final XMLInputFactory inputFactory = XMLInputFactory.newInstance();
    private XMLStreamReader reader;
    private QName root;
    private int rootCount;

    public T read(InputStream in)
            throws XMLStreamException, DecodingException {
        return XmlReader.this.read(this.inputFactory.createXMLStreamReader(in));
    }

    private T read(XmlReader reader)
            throws XMLStreamException, DecodingException {
        return read(reader.reader);
    }

    private T read(XMLStreamReader reader)
            throws XMLStreamException, DecodingException {
        this.reader = reader;
        this.root = toNextBeginTag();
        String cName = this.getClass().getSimpleName();
        this.rootCount = 0;
        if (root != null && !isEndTag()) {
            LOG.trace("{}: root: <{}:{}>", cName, root.getPrefix(),
                      root.getLocalPart());

            begin();

            //begin may proceed to the end of the element...
            if (isEndTag() && tagName().equals(root)) {
                return finish();
            }

            QName current;
            while ((current = toNextTag()) != null) {
                if (isStartTag()) {
                    LOG.trace("{}: begin: <{}:{}>", cName,
                              current.getPrefix(), current.getLocalPart());
                    if (current.equals(root)) {
                        ++rootCount;
                    }
                    read(current);
                } else if (isEndTag()) {
                    LOG.trace("{}: end: <{}:{}>", cName, current.getPrefix(),
                              current.getLocalPart());
                    if (current.equals(root)) {
                        if (rootCount == 0) {
                            break;
                        } else {
                            --rootCount;
                        }
                    }
                }
            }
        }
        return finish();
    }

    protected void read(QName name)
            throws XMLStreamException, DecodingException {
        ignore();
    }

    @SuppressWarnings("hiding")
    protected  T delegate(XmlReader reader)
            throws XMLStreamException, DecodingException {
        return reader.read(this);
    }

    private boolean isStartTag() {
        return this.reader.isStartElement();
    }

    private boolean isEndTag() {
        return this.reader.isEndElement();
    }

    private boolean hasNext()
            throws XMLStreamException {
        return this.reader.hasNext();
    }

    private void next()
            throws XMLStreamException {
        this.reader.next();
    }

    private QName toNextTag()
            throws XMLStreamException {
        if (hasNext()) {
            next();
            return toTag();
        } else {
            return null;
        }
    }

    private QName toNextBeginTag()
            throws XMLStreamException {
        while (!isStartTag() && hasNext()) {
            toNextTag();
        }
        return isStartTag() ? tagName() : null;
    }

    private QName toTag()
            throws XMLStreamException {
        while (!isStartTag() && !isEndTag() && hasNext()) {
            next();
        }
        return isStartTag() || isEndTag() ? tagName() : null;
    }

    protected Map attr() {
        int l = this.reader.getAttributeCount();
        Map attr = new HashMap<>(l);
        for (int i = 0; i < l; ++i) {
            if (this.reader.isAttributeSpecified(i)) {
                attr.put(this.reader.getAttributeName(i),
                         this.reader.getAttributeValue(i));
            }
        }
        return attr;
    }

    protected Iterable> attr(Iterable names) {
        return Iterables.transform(names, XmlReader.this::attr);
    }

    protected Optional attr(QName qn) {
        return Optional.fromNullable(attr().get(qn));
    }

    protected Optional attr(String name) {
        return attr(new QName(name));
    }

    protected QName tagName() {
        return this.reader.getName();
    }

    protected String chars()
            throws XMLStreamException {
        return this.reader.getElementText();
    }

    protected void begin()
            throws XMLStreamException, DecodingException {
        /* no op */
    }

    protected abstract T finish()
            throws DecodingException;

    protected void ignore() {
        QName name = this.reader.getName();
        String cName = getClass().getSimpleName();
        LOG.warn("{}: ignoring element {}:{}", cName,
                 name.getPrefix(), name.getLocalPart());
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy