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

org.codehaus.mojo.jaxb2.helpers.SimpleNamespaceResolver Maven / Gradle / Ivy

Go to download

Mojo's JAXB-2 Maven plugin is used to create an object graph from XSDs based on the JAXB 2.x implementation and to generate XSDs from JAXB annotated Java classes.

There is a newer version: 3.2.0
Show newest version
package org.codehaus.mojo.jaxb2.helpers;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;

import org.codehaus.plexus.util.IOUtil;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * Namespace resolver for XML documents. Doubles as a JAXB NamespaeContext, if we decide to
 * use JAXB instead of DOM to parse our generated schema files.
 *
 * @author Lennart Jörelid
 */
public class SimpleNamespaceResolver
    implements NamespaceContext
{
    // Constants
    private static final String DEFAULT_NS = "DEFAULT";

    private static final String TARGET_NAMESPACE = "targetNamespace";

    private static final String SCHEMA = "schema";

    // Internal state
    private String sourceFilename;

    private String localNamespaceURI;

    private Map prefix2Uri = new HashMap();

    private Map uri2Prefix = new HashMap();

    /**
     * Creates a new SimpleNamespaceResolver which collects namespace data
     * from the provided XML file.
     *
     * @param xmlFile The XML file from which to collect namespace data, should not be null.
     */
    public SimpleNamespaceResolver( final File xmlFile )
    {
        this.sourceFilename = xmlFile.getName();

        Reader reader = null;
        try
        {
            reader = new FileReader( xmlFile );
            initialize( reader );
        }
        catch ( FileNotFoundException e )
        {
            throw new IllegalArgumentException( "File [" + xmlFile + "] could not be found." );
        }
        finally 
        {
            IOUtil.close( reader ); 
        }
    }

    /** {@inheritDoc} */
    public String getNamespaceURI( final String prefix )
    {
        if ( prefix == null )
        {
            // Be compliant with the JAXB contract for NamespaceResolver.
            throw new IllegalArgumentException( "Cannot handle null prefix argument." );
        }

        return prefix2Uri.get( XMLConstants.DEFAULT_NS_PREFIX.equals( prefix ) ? DEFAULT_NS : prefix );
    }

    /** {@inheritDoc} */
    public String getPrefix( final String namespaceURI )
    {
        if ( namespaceURI == null )
        {
            // Be compliant with the JAXB contract for NamespaceResolver.
            throw new IllegalArgumentException( "Cannot acquire prefix for null namespaceURI." );
        }

        return uri2Prefix.get( namespaceURI );
    }

    /** {@inheritDoc} */
    public Iterator getPrefixes( String namespaceURI )
    {
        if ( namespaceURI == null )
        {
            // Be compliant with the JAXB contract for NamespaceResolver.
            throw new IllegalArgumentException( "Cannot acquire prefixes for null namespaceURI." );
        }

        return Collections.singletonList( uri2Prefix.get( namespaceURI ) ).iterator();
    }

    /**
     * @return A readonly map relating namespace URIs to namespace prefixes.
     */
    public Map getNamespaceURI2PrefixMap()
    {
        return Collections.unmodifiableMap( uri2Prefix );
    }

    /**
     * @return The namespace URI of the default namespace within the sourceFile of this SimpleNamespaceResolver.
     */
    public String getLocalNamespaceURI()
    {
        return localNamespaceURI;
    }

    /**
     * @return The name of the source file used for this SimpleNamespaceResolver.
     */
    public String getSourceFilename()
    {
        return sourceFilename;
    }

    //
    // Private helpers
    //

    /**
     * Initializes this SimpleNamespaceResolver to collect namespace data from the provided stream.
     *
     * @param xmlFileStream A Reader connected to the XML file from which we should read namespace data.
     */
    private void initialize( final Reader xmlFileStream )
    {
        // Build a DOM model.
        final Document parsedDocument = SchemagenHelper.parseXmlStream( xmlFileStream );

        // Process the DOM model.
        SchemagenHelper.process( parsedDocument.getFirstChild(), true, new NamespaceAttributeNodeProcessor() );
    }

    class NamespaceAttributeNodeProcessor
        implements NodeProcessor
    {
        /**
         * Defines if this visitor should process the provided node.
         *
         * @param aNode The DOM node to process.
         * @return true if the provided Node should be processed by this NodeProcessor.
         */
        public boolean accept( Node aNode )
        {
            if ( aNode.getNamespaceURI() != null && XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(
                aNode.getNamespaceURI() ) )
            {
                return true;
            }

            // Is this Node the targetNamespace attribute?
            if ( aNode instanceof Attr )
            {

                final Attr attribute = (Attr) aNode;
                final Element parent = attribute.getOwnerElement();
                if ( XMLConstants.W3C_XML_SCHEMA_NS_URI.equals( parent.getNamespaceURI() )
                    && SCHEMA.equalsIgnoreCase( parent.getLocalName() )
                    && TARGET_NAMESPACE.equals( attribute.getLocalName() ) )
                {

                    SimpleNamespaceResolver.this.localNamespaceURI = attribute.getNodeValue();
                }
            }

            // Ignore processing this Node.
            return false;
        }

        /**
         * Processes the provided DOM Node.
         *
         * @param aNode The DOM Node to process.
         */
        public void process( Node aNode )
        {
            // If we have no namespace, use the DEFAULT_NS as the prefix
            final String cacheKey =
                ( XMLConstants.XMLNS_ATTRIBUTE.equals( aNode.getNodeName() ) ) ? DEFAULT_NS : aNode.getLocalName();
            final String nodeValue = aNode.getNodeValue();

            // Cache the namespace in both caches.
            final String oldUriValue = prefix2Uri.put( cacheKey, nodeValue );
            final String oldPrefixValue = uri2Prefix.put( nodeValue, cacheKey );

            // Check sanity; we should not be overwriting values here.
            if ( oldUriValue != null )
            {
                throw new IllegalStateException(
                    "Replaced URI [" + oldUriValue + "] with [" + aNode.getNodeValue() + "] for prefix [" + cacheKey
                        + "]" );
            }
            if ( oldPrefixValue != null )
            {
                throw new IllegalStateException(
                    "Replaced prefix [" + oldPrefixValue + "] with [" + cacheKey + "] for URI [" + aNode.getNodeValue()
                        + "]" );
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy