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

gov.nasa.worldwind.util.xml.XMLEventParserContextFactory 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.ogc.collada.*;
//import gov.nasa.worldwind.ogc.kml.*;

import gov.nasa.worldwind.ogc.kml.*;
import gov.nasa.worldwind.util.Logging;

import javax.xml.XMLConstants;
import java.lang.reflect.Constructor;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;

/**
 * Provides a global registry of XML parsers. Enables registration of parsers for specific mime types and namespace
 * specialization. Parsers should generally be drawn from this class in order to ensure that parsers configured by World
 * Wind and the application are used.
 *
 * @author tag
 * @version $Id: XMLEventParserContextFactory.java 1171 2013-02-11 21:45:02Z dcollins $
 */
public class XMLEventParserContextFactory
{
    /** Holds the mime types and the associated prototype parser. */
    protected static class ParserTableEntry
    {
        /** The mime types for which the associated parser should be used. */
        protected List mimeTypes = new ArrayList();
        /**
         * A prototype parser able to construct a copy of itself. The copy typically shares the prototype's parser table
         * and may also share other internal fields.
         */
        XMLEventParserContext prototypeParser;

        /**
         * Construct an instance for a specified list of mime types and a specified prototype parser.
         *
         * @param mimeTypes        the list of mime types for which to use the specified prototype parser context.
         * @param prototypeContext the prototype parser context to use for the specified mime types. This parser
         *                         context's class must provide a copy constructor, a constructor that takes an instance
         *                         of its class as its only argument.
         *
         * @throws IllegalArgumentException if the mime type list is null or empty or the prototype context is null or
         *                                  has no copy constructor.
         */
        public ParserTableEntry(String[] mimeTypes, XMLEventParserContext prototypeContext)
        {
            for (String mimeType : mimeTypes)
            {
                this.mimeTypes.add(mimeType);
            }

            this.prototypeParser = prototypeContext;

            // Ensure the prototype has a copy constructor
            try
            {
                prototypeContext.getClass().getConstructor(prototypeContext.getClass());
            }
            catch (NoSuchMethodException e)
            {
                String message = Logging.getMessage("XML.NoCopyConstructor");
                Logging.logger().severe(message);
                throw new IllegalArgumentException(message);
            }
        }
    }

    /**
     * The list of registered parser contexts. A copy-on-write list is used to avoid the need to explicitly synchronize
     * access.
     */
    protected static List parsers = new CopyOnWriteArrayList();

    static
    {
        // Register a KML parser context for the default KML namespace and one for the empty namespace.
        String[] mimeTypes = new String[] {KMLConstants.KML_MIME_TYPE, KMLConstants.KMZ_MIME_TYPE};
        parsers.add(new ParserTableEntry(mimeTypes, new KMLParserContext(KMLConstants.KML_NAMESPACE)));
        parsers.add(new ParserTableEntry(mimeTypes, new KMLParserContext(XMLConstants.NULL_NS_URI)));
//
//        // Register a Collada parser context for the default Collada namespace and one for the empty namespace.
//        mimeTypes = new String[] {KMLConstants.COLLADA_MIME_TYPE};
//        parsers.add(new ParserTableEntry(mimeTypes, new ColladaParserContext(ColladaConstants.COLLADA_NAMESPACE)));
//        parsers.add(new ParserTableEntry(mimeTypes, new ColladaParserContext(XMLConstants.NULL_NS_URI)));
    }

    /**
     * Appends a specified prototype parser context to the list of those already registered.
     *
     * @param mimeTypes        the list of mime types for which to use the specified prototype parser context.
     * @param prototypeContext the prototype parser context to use for the specified mime types. This parser context's
     *                         class must provide a copy constructor, a constructor that takes an instance of its class
     *                         as its only argument.
     *
     * @throws IllegalArgumentException if the mime type list is null or empty or the prototype context is null or has
     *                                  no copy constructor.
     */
    public static void addParserContext(String[] mimeTypes, XMLEventParserContext prototypeContext)
    {
        if (mimeTypes == null || mimeTypes.length == 0)
        {
            String message = Logging.getMessage("nullValue.MimeTypeListIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

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

        parsers.add(new ParserTableEntry(mimeTypes, prototypeContext));
    }

    /**
     * Prepends a specified prototype parser context to the list of those already registered. Because the new entry is
     * prepended to the list of registered parsers, it will be the first match for the specified mime types.
     *
     * @param mimeTypes        the list of mime types for which to use the specified prototype parser context.
     * @param prototypeContext the prototype parser context to use for the specified mime types. This parser context's
     *                         class must provide a copy constructor, a constructor that takes an instance of its class
     *                         as its only argument.
     *
     * @throws IllegalArgumentException if the mime type list is null or empty or the prototype context is null or has
     *                                  no copy constructor.
     */
    public static void prependParserContext(String[] mimeTypes, XMLEventParserContext prototypeContext)
    {
        if (mimeTypes == null || mimeTypes.length == 0)
        {
            String message = Logging.getMessage("nullValue.MimeTypeListIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

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

        parsers.add(0, new ParserTableEntry(mimeTypes, prototypeContext));
    }

    /**
     * Constructs and returns a parser context for a specified mime type and namespace. The list of registered parser
     * contexts is searched from first to last. A parser context is constructed from the first entry matching the
     * specified mime type and namespace. Null is returned if no match is found.
     * 

* Note that the empty namespace, {@link XMLConstants#NULL_NS_URI} does not match any other namespace. In order for * a parser context with the empty namespace to be returned, one with the empty namespace must be registered. * * @param mimeType the mime type for which to construct a parser. * @param defaultNamespace a namespace qualifying the parser context to return. May be null, in which case a parser * context for the specified mime type and an empty namespace, {@link * XMLConstants#NULL_NS_URI}, is searched for. * * @return a new parser context constructed from the prototype context registered for the specified mime type and * having the specified default namespace. * * @throws IllegalArgumentException if the specified mime type is null. */ public static XMLEventParserContext createParserContext(String mimeType, String defaultNamespace) { if (mimeType == null) { String message = Logging.getMessage("nullValue.MimeTypeIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } for (ParserTableEntry entry : parsers) { for (String entryMimeType : entry.mimeTypes) { if (entryMimeType.equals(mimeType)) { String ns = entry.prototypeParser.getDefaultNamespaceURI(); ns = ns != null ? ns : XMLConstants.NULL_NS_URI; defaultNamespace = defaultNamespace != null ? defaultNamespace : XMLConstants.NULL_NS_URI; if (ns.equals(defaultNamespace)) try { return createInstanceFromPrototype(entry.prototypeParser); } catch (Exception e) { String message = Logging.getMessage("XML.ExceptionCreatingParserContext", e.getMessage()); Logging.logger().log(Level.WARNING, message); // continue on to subsequent entries } } } } return null; } /** * Constructs a new parser context given a prototype parser context. * * @param prototype the prototype parser context. This parser context's class must provide a copy constructor, a * constructor that takes an instance of the class as its only argument. * * @return the new parser context. * * @throws Exception if an exception occurs while attempting to construct the new context. */ protected static XMLEventParserContext createInstanceFromPrototype(XMLEventParserContext prototype) throws Exception { Constructor constructor; constructor = prototype.getClass().getConstructor(prototype.getClass()); return constructor.newInstance(prototype); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy