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

org.yamcs.xtce.xml.AbstractStaxReader Maven / Gradle / Ivy

The newest version!
package org.yamcs.xtce.xml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

/**
 * Abstract class for XML readers
 */
public class AbstractStaxReader implements AutoCloseable {

    protected final XMLEventReader xmlEventReader;
    protected final String fileName;
    final InputStream in;
    protected XMLEvent xmlEvent = null;
    
    protected AbstractStaxReader(String fileName) throws IOException, XMLStreamException {
        this.fileName = fileName;
        in = new FileInputStream(new File(fileName));
        xmlEventReader = initEventReader(in);
    }

    private XMLEventReader initEventReader(InputStream in) throws XMLStreamException {
        XMLInputFactory factory = XMLInputFactory.newInstance();
        // Merge multiple character data blocks into a single event (e.g. algorithm text)
        factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);

        // Sonarqube suggestion to protect Java XML Parsers from XXE attack
        // see https://rules.sonarsource.com/java/RSPEC-2755
        factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
        factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");

        return factory.createXMLEventReader(in);
    }

    /**
     * Examines element for presence of attributes
     * 
     * @param element
     *            Element to be examined, should not be null
     * @return True, if the element contains attributes, otherwise false
     */
    protected boolean hasAttributes(StartElement element) {
        if (element == null) {
            return false;
        }
        return element.getAttributes().hasNext();
    }

    /**
     * Check if xml element is a start element with particular name
     * 
     * @param localName
     *            Name of the element
     * @return True if element is start element with the given name, otherwise false
     */
    protected boolean isStartElementWithName(String localName) {
        return (xmlEvent.getEventType() == XMLStreamConstants.START_ELEMENT && xmlEvent
                .asStartElement().getName().getLocalPart().equals(localName));
    }

    protected String readStringBetweenTags(String tagName) throws XMLStreamException {
        checkStartElementPreconditions();

        StringBuilder longDescr = new StringBuilder();
        while (true) {
            xmlEvent = xmlEventReader.nextEvent();
            if (isEndElementWithName(tagName)) {
                break;
            }
            if (!xmlEvent.isCharacters()) {
                throw new IllegalStateException(
                        tagName + " characters or end element expected but instead got " + xmlEvent);
            }
            longDescr.append(xmlEvent.asCharacters().getData());
        }

        return longDescr.toString();
    }

    /**
     * Checks preconditions before the dedicated code for section reading will run
     * 
     * @return
     * 
     * @throws IllegalStateException
     *             If the conditions are not met
     */
    protected StartElement checkStartElementPreconditions() throws IllegalStateException {
        if (xmlEvent == null) {
            throw new IllegalStateException("xmlEvent is null");
        }
        if (xmlEvent.getEventType() != XMLStreamConstants.START_ELEMENT) {
            throw new IllegalStateException("xmlEvent type is not start element");
        }
        return xmlEvent.asStartElement();
    }

    protected boolean hasAttribute(String attName, StartElement element) throws XMLStreamException {
        Attribute attribute = element.getAttributeByName(new QName(attName));
        return (attribute != null);

    }

    /**
     * Get attribute values as string
     * 
     * @param attName
     *            Name of the attribute
     * @param element
     *            Start element which the attribute is read from
     * @return Attribute's value as string
     * @throws XMLStreamException
     *             - if the attribute does not exist
     */
    protected String readMandatoryAttribute(String attName, StartElement element) throws XMLStreamException {
        Attribute attribute = element.getAttributeByName(new QName(attName));
        if (attribute != null) {
            return attribute.getValue();
        } else {
            throw new XMLStreamException("Mandatory attribute '" + attName + "' not defined", element.getLocation());
        }
    }

    protected String readAttribute(String attName, StartElement element, String defaultValue) {
        Attribute attribute = element.getAttributeByName(new QName(attName));
        if (attribute != null) {
            return attribute.getValue();
        }
        return defaultValue;
    }

    protected int readIntAttribute(String attName, StartElement element, int defaultValue) throws XMLStreamException {
        String v = readAttribute(attName, element, null);
        if (v == null) {
            return defaultValue;
        } else {
            try {
                return Integer.parseInt(v);
            } catch (IllegalArgumentException e) {
                throw new XMLStreamException("Cannot parse '" + v + "' to integer");
            }
        }
    }

    protected int readIntAttribute(String attName, StartElement element) throws XMLStreamException {
        String v = readAttribute(attName, element, null);
        if (v == null) {
            throw new XMLStreamException("Mandatory attribute '" + attName + "' not defined");
        } else {
            try {
                return Integer.parseInt(v);
            } catch (IllegalArgumentException e) {
                throw new XMLStreamException("Cannot parse '" + v + "' to integer");
            }
        }
    }

    protected long readLongAttribute(String attName, StartElement element) throws XMLStreamException {
        String v = readAttribute(attName, element, null);
        if (v == null) {
            throw new XMLStreamException("Mandatory attribute '" + attName + "' not defined");
        } else {
            try {
                return Long.parseLong(v);
            } catch (IllegalArgumentException e) {
                throw new XMLStreamException("Cannot parse '" + v + "' to integer");
            }
        }
    }

    protected long readLongAttribute(String attName, StartElement element, long defaultValue)
            throws XMLStreamException {
        String v = readAttribute(attName, element, null);
        if (v == null) {
            return defaultValue;
        } else {
            try {
                return Long.parseLong(v);
            } catch (IllegalArgumentException e) {
                throw new XMLStreamException("Cannot parse '" + v + "' to integer");
            }
        }
    }

    protected double readDoubleAttribute(String attName, StartElement element) throws XMLStreamException {
        String v = readAttribute(attName, element, null);
        if (v == null) {
            throw new XMLStreamException("Mandatory attribute '" + attName + "' not defined");
        } else {
            try {
                return Double.parseDouble(v);
            } catch (IllegalArgumentException e) {
                throw new XMLStreamException("Cannot parse '" + v + "' to double float number");
            }
        }

    }

    protected double readDoubleAttribute(String attName, StartElement element, double defaultValue)
            throws XMLStreamException {
        String v = readAttribute(attName, element, null);
        if (v == null) {
            return defaultValue;
        } else {
            try {
                return Double.parseDouble(v);
            } catch (IllegalArgumentException e) {
                throw new XMLStreamException("Cannot parse '" + v + "' to double floating point number");
            }
        }

    }

    protected boolean readBooleanAttribute(String attName, StartElement element, boolean defaultValue)
            throws XMLStreamException {
        String v = readAttribute(attName, element, null);
        if (v == null) {
            return defaultValue;
        } else {
            if ("true".equalsIgnoreCase(v) || "1".equals(v)) {
                return true;
            } else if ("false".equalsIgnoreCase(v) || "0".equals(v)) {
                return false;
            } else {
                throw new XMLStreamException("Cannot parse '" + v + "' to boolean");
            }
        }
    }

    /**
     * Test if the xmlEvent is of type END_ELEMENT and has particular local name. This test is used to identify the end
     * of section.
     * 
     * @param localName
     *            Local name of the element (we neglect namespace for now)
     * @return True if current xmlEvent is of type END_ELEMENT and has particular local name, otherwise false
     */
    protected boolean isEndElementWithName(String localName) {
        return (xmlEvent.getEventType() == XMLStreamConstants.END_ELEMENT && xmlEvent
                .asEndElement().getName().getLocalPart().equals(localName));
    }

    @Override
    public void close() throws XMLStreamException, IOException {
        xmlEventReader.close();
        in.close();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy