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

gov.nasa.worldwind.util.xml.BasicXMLEventParserContext Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */

package gov.nasa.worldwind.util.xml;

import gov.nasa.worldwind.avlist.AVListImpl;
import gov.nasa.worldwind.util.Logging;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.stream.*;
import javax.xml.stream.events.XMLEvent;
import java.beans.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;

/**
 * Provides an implementation of {@link gov.nasa.worldwind.util.xml.XMLEventParserContext}. This class is meant to be
 * the base class for schema-specific parsers.
 *
 * @author tag
 * @version $Id: BasicXMLEventParserContext.java 1981 2014-05-08 03:59:04Z tgaskins $
 */
public class BasicXMLEventParserContext extends AVListImpl implements XMLEventParserContext
{
    /** The parser name of the default double parser. */
    public static QName DOUBLE = new QName("Double");
    /** The parser name of the default integer parser. */
    public static QName INTEGER = new QName("Integer");
    /** The parser name of the default string parser. */
    public static QName STRING = new QName("String");
    /** The parser name of the default boolean parser. */
    public static QName BOOLEAN = new QName("Boolean");
    /** The parser name of the default boolean integer parser. */
    public static QName BOOLEAN_INTEGER = new QName("BooleanInteger");
    /** The parser name of the unrecognized-element parser. */
    public static QName UNRECOGNIZED = new QName(UNRECOGNIZED_ELEMENT_PARSER);

    protected XMLEventReader reader;
    protected StringXMLEventParser stringParser;
    protected DoubleXMLEventParser doubleParser;
    protected IntegerXMLEventParser integerParser;
    protected BooleanXMLEventParser booleanParser;
    protected BooleanIntegerXMLEventParser booleanIntegerParser;
    protected String defaultNamespaceURI = XMLConstants.NULL_NS_URI;
    protected XMLParserNotificationListener notificationListener;
    protected ConcurrentHashMap idTable = new ConcurrentHashMap();

    protected ConcurrentHashMap parsers = new ConcurrentHashMap();

    /** Construct an instance. Invokes {@link #initializeParsers()} and {@link #initialize()}. */
    public BasicXMLEventParserContext()
    {
        this.initializeParsers();
        this.initialize();
    }

    /**
     * Construct an instance for a specified event reader. Invokes {@link #initializeParsers()} and {@link
     * #initialize()}.
     *
     * @param eventReader the event reader to use for XML parsing.
     */
    public BasicXMLEventParserContext(XMLEventReader eventReader)
    {
        this.reader = eventReader;

        this.initializeParsers();
        this.initialize();
    }

    /**
     * Construct an instance for a specified event reader and default namespace. Invokes {@link #initializeParsers()}
     * and {@link #initialize()}.
     *
     * @param eventReader      the event reader to use for XML parsing.
     * @param defaultNamespace the namespace URI of the default namespace.
     */
    public BasicXMLEventParserContext(XMLEventReader eventReader, String defaultNamespace)
    {
        this.reader = eventReader;
        this.setDefaultNamespaceURI(defaultNamespace);

        this.initializeParsers();
        this.initialize();
    }

    public BasicXMLEventParserContext(BasicXMLEventParserContext ctx)
    {
        this.parsers = ctx.parsers;
        this.setDefaultNamespaceURI(ctx.getDefaultNamespaceURI());
        this.initialize();
    }

    protected void initialize()
    {
        this.initializeDefaultNotificationListener();
    }

    protected void initializeDefaultNotificationListener()
    {
        this.addPropertyChangeListener(new PropertyChangeListener()
        {
            public void propertyChange(PropertyChangeEvent propEvent)
            {
                XMLParserNotification notification = (XMLParserNotification) propEvent;

                if (notificationListener != null)
                {
                    notificationListener.notify(notification);
                    return;
                }

                String msg;
                if (notification.getEvent() != null)
                {
                    msg = Logging.getMessage(notification.getMessage(), notification.getEvent().toString(),
                        notification.getEvent().getLocation().getLineNumber(),
                        notification.getEvent().getLocation().getColumnNumber(),
                        notification.getEvent().getLocation().getCharacterOffset());
                }
                else
                {
                    msg = Logging.getMessage(notification.getMessage(), "", "");
                }

                if (notification.getPropertyName().equals(XMLParserNotification.EXCEPTION))
                    Logging.logger().log(Level.WARNING, msg);
                else if (notification.getPropertyName().equals(XMLParserNotification.UNRECOGNIZED))
                    Logging.logger().log(Level.WARNING, msg);
            }
        });
    }

    /**
     * Initializes the parser table with the default parsers for the strings, integers, etc., qualified for the default
     * namespace.
     */
    protected void initializeParsers()
    {
        this.parsers.put(STRING, new StringXMLEventParser());
        this.parsers.put(DOUBLE, new DoubleXMLEventParser());
        this.parsers.put(INTEGER, new IntegerXMLEventParser());
        this.parsers.put(BOOLEAN, new BooleanXMLEventParser());
        this.parsers.put(BOOLEAN_INTEGER, new BooleanIntegerXMLEventParser());
        this.parsers.put(UNRECOGNIZED, new UnrecognizedXMLEventParser(null));
    }

    @Override
    public void addStringParsers(String namespace, String[] stringFields)
    {
        StringXMLEventParser stringParser = this.getStringParser();
        for (String s : stringFields)
        {
            this.parsers.put(new QName(namespace, s), stringParser);
        }
    }

    @Override
    public void addDoubleParsers(String namespace, String[] doubleFields)
    {
        DoubleXMLEventParser doubleParser = this.getDoubleParser();
        for (String s : doubleFields)
        {
            this.parsers.put(new QName(namespace, s), doubleParser);
        }
    }

    @Override
    public void addIntegerParsers(String namespace, String[] integerFields)
    {
        IntegerXMLEventParser integerParser = this.getIntegerParser();
        for (String s : integerFields)
        {
            this.parsers.put(new QName(namespace, s), integerParser);
        }
    }

    @Override
    public void addBooleanParsers(String namespace, String[] booleanFields)
    {
        BooleanXMLEventParser booleanParser = this.getBooleanParser();
        for (String s : booleanFields)
        {
            this.parsers.put(new QName(namespace, s), booleanParser);
        }
    }

    @Override
    public void addBooleanIntegerParsers(String namespace, String[] booleanIntegerFields)
    {
        BooleanIntegerXMLEventParser booleanIntegerParser = this.getBooleanIntegerParser();
        for (String s : booleanIntegerFields)
        {
            this.parsers.put(new QName(namespace, s), booleanIntegerParser);
        }
    }

    /**
     * Returns the event reader used by this instance.
     *
     * @return the instance's event reader.
     */
    public XMLEventReader getEventReader()
    {
        return this.reader;
    }

    /**
     * Specify the event reader for the parser context to use to parse XML.
     *
     * @param reader the event reader to use.
     */
    public void setEventReader(XMLEventReader reader)
    {
        if (reader == null)
        {
            String message = Logging.getMessage("nullValue.EventIsNull"); // TODO
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.reader = reader;
    }

    public String getDefaultNamespaceURI()
    {
        return defaultNamespaceURI;
    }

    public void setDefaultNamespaceURI(String defaultNamespaceURI)
    {
        this.defaultNamespaceURI = defaultNamespaceURI;
    }

    public void setNotificationListener(XMLParserNotificationListener listener)
    {
        this.notificationListener = listener;
    }

    public Map getIdTable()
    {
        return this.idTable;
    }

    public void addId(String id, Object o)
    {
        if (id != null)
            this.getIdTable().put(id, o);
    }

    public boolean hasNext()
    {
        return this.getEventReader().hasNext();
    }

    public XMLEvent nextEvent() throws XMLStreamException
    {
        while (this.hasNext())
        {
            XMLEvent event = this.getEventReader().nextEvent();

            if (event.isCharacters() && event.asCharacters().isWhiteSpace())
                continue;

            return event;
        }

        return null;
    }

    public XMLEventParser allocate(XMLEvent event, XMLEventParser defaultParser)
    {
        return this.getParser(event, defaultParser);
    }

    public XMLEventParser allocate(XMLEvent event)
    {
        return this.getParser(event, null);
    }

    public XMLEventParser getParser(XMLEvent event)
    {
        return this.getParser(event, null);
    }

    protected XMLEventParser getParser(XMLEvent event, XMLEventParser defaultParser)
    {
        if (event == null)
        {
            String message = Logging.getMessage("nullValue.EventIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        QName elementName = event.asStartElement().getName();
        if (elementName == null)
            return null;

        XMLEventParser parser = this.getParser(elementName);

        return parser != null ? parser : defaultParser;
    }

    public StringXMLEventParser getStringParser()
    {
        if (this.stringParser == null)
            this.stringParser = (StringXMLEventParser) this.getParser(STRING);

        return this.stringParser;
    }

    public DoubleXMLEventParser getDoubleParser()
    {
        if (this.doubleParser == null)
            this.doubleParser = (DoubleXMLEventParser) this.getParser(DOUBLE);

        return this.doubleParser;
    }

    public IntegerXMLEventParser getIntegerParser()
    {
        if (this.integerParser == null)
            this.integerParser = (IntegerXMLEventParser) this.getParser(INTEGER);

        return this.integerParser;
    }

    public BooleanXMLEventParser getBooleanParser()
    {
        if (this.booleanParser == null)
            this.booleanParser = (BooleanXMLEventParser) this.getParser(BOOLEAN);

        return this.booleanParser;
    }

    public BooleanIntegerXMLEventParser getBooleanIntegerParser()
    {
        if (this.booleanIntegerParser == null)
            this.booleanIntegerParser = (BooleanIntegerXMLEventParser) this.getParser(BOOLEAN_INTEGER);

        return this.booleanIntegerParser;
    }

    /**
     * Returns a parser to handle unrecognized elements. The default unrecognized event parser is {@link
     * gov.nasa.worldwind.util.xml.UnrecognizedXMLEventParser}, and may be replaced by calling {@link
     * #registerParser(javax.xml.namespace.QName, XMLEventParser)} and specifying {@link #UNRECOGNIZED} as the parser
     * name.
     *
     * @return a parser to handle unrecognized elements.
     */
    public XMLEventParser getUnrecognizedElementParser()
    {
        return this.getParser(UNRECOGNIZED);
    }

    public String getCharacters(XMLEvent event)
    {
        if (event == null)
        {
            String message = Logging.getMessage("nullValue.EventIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        return event.isCharacters() ? event.asCharacters().getData() : null;
    }

    @SuppressWarnings({"SimplifiableIfStatement"})
    public boolean isSameName(QName qa, QName qb)
    {
        if (qa.equals(qb))
            return true;

        if (!qa.getLocalPart().equals(qb.getLocalPart()))
            return false;

        if (qa.getNamespaceURI().equals(XMLConstants.NULL_NS_URI))
            return qb.getNamespaceURI().equals(this.getDefaultNamespaceURI());

        if (qb.getNamespaceURI().equals(XMLConstants.NULL_NS_URI))
            return qa.getNamespaceURI().equals(this.getDefaultNamespaceURI());

        return false;
    }

    @SuppressWarnings({"SimplifiableIfStatement"})
    public boolean isSameAttributeName(QName qa, QName qb)
    {
        return qa != null && qb != null && qa.getLocalPart() != null && qa.getLocalPart().equals(qb.getLocalPart());
    }

    public boolean isStartElement(XMLEvent event, QName elementName)
    {
        if (event == null)
        {
            String message = Logging.getMessage("nullValue.EventIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        if (elementName == null)
        {
            String message = Logging.getMessage("nullValue.ElementNameIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        return (event.isStartElement() && this.isSameName(event.asStartElement().getName(), elementName));
    }

    public boolean isStartElement(XMLEvent event, String elementName)
    {
        if (event == null)
        {
            String message = Logging.getMessage("nullValue.EventIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        if (elementName == null)
        {
            String message = Logging.getMessage("nullValue.ElementNameIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        return (event.isStartElement() && event.asStartElement().getName().getLocalPart().equals(elementName));
    }

    public boolean isEndElement(XMLEvent event, XMLEvent startElement)
    {
        if (event == null || startElement == null)
        {
            String message = Logging.getMessage("nullValue.EventIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        return isEndElementEvent(event, startElement);
    }

    public static boolean isEndElementEvent(XMLEvent event, XMLEvent startElement)
    {
        if (event == null || startElement == null)
        {
            String message = Logging.getMessage("nullValue.EventIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        return (event.isEndElement()
            && event.asEndElement().getName().equals(startElement.asStartElement().getName()));
    }

    public void registerParser(QName elementName, XMLEventParser parser)
    {
        if (parser == null)
        {
            String message = Logging.getMessage("nullValue.ParserIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        if (elementName == null)
        {
            String message = Logging.getMessage("nullValue.ElementNameIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.parsers.put(elementName, parser);
    }

    public XMLEventParser getParser(QName name)
    {
        if (name == null)
        {
            String message = Logging.getMessage("nullValue.ElementNameIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        XMLEventParser factoryParser = this.parsers.get(name);
        if (factoryParser == null)
        {
            // Try alternate forms that assume a default namespace in either the input name or the table key.
            if (isNullNamespace(name.getNamespaceURI()))
            {
                // input name has no namespace but table key has the default namespace
                QName altName = new QName(this.getDefaultNamespaceURI(), name.getLocalPart());
                factoryParser = this.parsers.get(altName);
            }
            else if (this.isDefaultNamespace(name.getNamespaceURI()))
            {
                // input name has the default namespace but table name has no namespace
                QName altName = new QName(name.getLocalPart());
                factoryParser = this.parsers.get(altName);
            }
        }

        try
        {
            if (factoryParser == null)
                return null;

            return factoryParser.newInstance();
        }
        catch (Exception e)
        {
            String message = Logging.getMessage("XML.ParserCreationException", name);
            Logging.logger().log(java.util.logging.Level.WARNING, message, e);
            return null;
        }
    }

    protected static boolean isNullNamespace(String namespaceURI)
    {
        return namespaceURI == null || XMLConstants.NULL_NS_URI.equals(namespaceURI);
    }

    public boolean isDefaultNamespace(String namespaceURI)
    {
        return this.getDefaultNamespaceURI() != null && this.getDefaultNamespaceURI().equals(namespaceURI);
    }

    @Deprecated
    public void resolveInternalReferences(String referenceName, String fieldName, AbstractXMLEventParser parser)
    {
        if (parser == null || !parser.hasFields())
            return;

        Map newFields = null;

        for (Map.Entry p : parser.getFields().getEntries())
        {
            String key = p.getKey();
            if (key == null || key.equals("id"))
                continue;

            Object v = p.getValue();
            if (v == null)
                continue;

            if (v instanceof String)
            {
                String value = (String) v;

                if (value.startsWith("#") && key.endsWith(referenceName))
                {
                    Object o = this.getIdTable().get(value.substring(1, value.length()));
                    if (/*o instanceof KMLStyle &&*/ !parser.hasField(fieldName))
                    {
                        if (newFields == null)
                            newFields = new HashMap();
                        newFields.put(fieldName, o);
                    }
                }
            }
        }

        if (newFields != null)
            parser.setFields(newFields);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy