/* * Copyright 2001-2004 The Apache Software Foundation. * * 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.apache.fop.xml; import org.apache.fop.datatypes.Ints; import java.util.HashMap; import java.util.ArrayList; /** * Maintains the namespaces encountered by an invocation of * <tt>XMLSerialHandler</tt>. * <p>One instance of <i>XMLNamespaces</i> is maintained across all * documents that may be processed in a single invocation of * <tt>XMLSerialhandler</tt>. A reference to that instance is kept with * every instance of <tt>XMLEvent</tt>. * @author <a href="mailto:pbwest@powerup.com.au">Peter B. West</a> */ public class XMLNamespaces { private static final String tag = "$Name$"; private static final String revision = "$Revision$"; public static final String DefAttrNSpace = ""; public static final String XSLNamespace = "http://www.w3.org/1999/XSL/Format"; public static final String SVGNamespace = "http://www.w3.org/2000/svg"; public static final String XlinkNamespace = "http://www.w3.org/1999/xlink"; public static final int DefAttrNSIndex = 0; public static final int XSLNSpaceIndex = 1; public static final int SVGNSpaceIndex = 2; public static final int XLinkNSpaceIndex = 3; /** * A <tt>HashMap</tt> mapping a namespace URI to an <tt>int</tt> * index. The HashMap is initialized with a few well-known URIs. As * URIs are encountered in parsing, they are converted to an integer * index by lookup in this HashMap. If the URI has not been seen, it * is added to the <i>uriIndices</i> and <i>uris</i> for future reference. * <b>It is vital that no URI, once added, ever be deleted * from this <tt>HashMap</tt></b>. * <p><tt>HashMap</> is unsynchronized, so accesses and updates must be * protected. * <p> * Updates will be very rare, and accesses are directly related to the * number of elements (and attributes) encountered. */ private HashMap uriIndices; /** * A <tt>ArrayList</tt> of namespace URIs. Effectively, a mapping of * an <tt>int</tt> index onto a URI. * ArrayList is initialized with a few well-known URIs. As * URIs are encountered in parsing, they are converted to an integer * index by lookup in the <i>uriIndices</i> Hashmap. If the URI has not * been seen, it is added to <i>uriIndices</i> and <i>uris</i> * for future reference. * <p> * <tt>ArrayList</> is unsynchronized, so access and updates must be * protected. Both will be more rare than accesses to <i>uriIndices</i>. */ private ArrayList uris; /** * A sequence object for use by <tt>XMLEvent</tt>s. Because an * <tt>XMLEvent</tt> object must always be associated with an * <i>XMLNamespace</i> object, this namespace object will act as a * singleton for <tt>XMLEvent</tt>s. This field provides a * counter for those objects. The range of values which may be * assigned to <i>sequence</i> is restricted by <i>seqMask</i>. */ private int sequence = 0; /** Mask to restrict the range of values within which <i>sequence</i> * may cycle. */ public final int seqMask = (1 << 20) - 1; /** * The access function for the sequence. * @return the next positive sequence number. This number may wrap * but is guaranteed to be within the range seqMask >= sequence >= 0. */ public int getSequence() { sequence = ++sequence & seqMask; return sequence; } public XMLNamespaces() { uriIndices = new HashMap(4); uris = new ArrayList(4); uriIndices.put(DefAttrNSpace, Ints.consts.get(DefAttrNSIndex)); uris.add(DefAttrNSIndex, DefAttrNSpace); uriIndices.put(XSLNamespace, Ints.consts.get(XSLNSpaceIndex)); uris.add(XSLNSpaceIndex, XSLNamespace); uriIndices.put(SVGNamespace, Ints.consts.get(SVGNSpaceIndex)); uris.add(SVGNSpaceIndex, SVGNamespace); uriIndices.put(XlinkNamespace, Ints.consts.get(XLinkNSpaceIndex)); uris.add(XLinkNSpaceIndex, XlinkNamespace); } /** * @return size of the <tt>uris</tt> <ttArrayList</tt>. */ public synchronized int getUrisSize() { return uris.size(); } /** * If the URI is not pre-defined, and has not been seen before, add * it to the stored namespaces, and return the index. * @param uri the namespace uri * @return integer index of the namespace URI */ public synchronized int getURIIndex(String uri) { int i; Integer intg = (Integer)uriIndices.get(uri); if (intg == null) { // update the indices i = uris.size(); //System.out.println("****Adding namespace " + uri + " " + i); uriIndices.put(uri, Ints.consts.get(i)); uris.add(i, uri); return i; } // not null - found the integer return intg.intValue(); } /** * @param index the integer index of the namespace URI * @return the corresponding namespace URI */ public synchronized String getIndexURI(int index) { return (String)uris.get(index); } }