Home | History | Annotate | Download | only in dom3
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements. See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership. The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the  "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 /*
     19  * $Id:  $
     20  */
     21 
     22 package org.apache.xml.serializer.dom3;
     23 
     24 import java.util.Enumeration;
     25 import java.util.NoSuchElementException;
     26 
     27 /**
     28  * Namespace support for XML document handlers. This class doesn't
     29  * perform any error checking and assumes that all strings passed
     30  * as arguments to methods are unique symbols. The SymbolTable class
     31  * can be used for this purpose.
     32  *
     33  * Derived from org.apache.xerces.util.NamespaceSupport
     34  *
     35  * @author Andy Clark, IBM
     36  *
     37  * @version $Id: Exp $
     38  */
     39 public class NamespaceSupport {
     40 
     41 	static final String PREFIX_XML = "xml".intern();
     42 
     43 	static final String PREFIX_XMLNS = "xmlns".intern();
     44 
     45     /**
     46      * The XML Namespace ("http://www.w3.org/XML/1998/namespace"). This is
     47      * the Namespace URI that is automatically mapped to the "xml" prefix.
     48      */
     49     public final static String XML_URI = "http://www.w3.org/XML/1998/namespace".intern();
     50 
     51     /**
     52      * XML Information Set REC
     53      * all namespace attributes (including those named xmlns,
     54      * whose [prefix] property has no value) have a namespace URI of http://www.w3.org/2000/xmlns/
     55      */
     56     public final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/".intern();
     57 
     58 	//
     59     // Data
     60     //
     61 
     62     /**
     63      * Namespace binding information. This array is composed of a
     64      * series of tuples containing the namespace binding information:
     65      * <prefix, uri>. The default size can be set to anything
     66      * as long as it is a power of 2 greater than 1.
     67      *
     68      * @see #fNamespaceSize
     69      * @see #fContext
     70      */
     71     protected String[] fNamespace = new String[16 * 2];
     72 
     73     /** The top of the namespace information array. */
     74     protected int fNamespaceSize;
     75 
     76     // NOTE: The constructor depends on the initial context size
     77     //       being at least 1. -Ac
     78 
     79     /**
     80      * Context indexes. This array contains indexes into the namespace
     81      * information array. The index at the current context is the start
     82      * index of declared namespace bindings and runs to the size of the
     83      * namespace information array.
     84      *
     85      * @see #fNamespaceSize
     86      */
     87     protected int[] fContext = new int[8];
     88 
     89     /** The current context. */
     90     protected int fCurrentContext;
     91 
     92     protected String[] fPrefixes = new String[16];
     93 
     94     //
     95     // Constructors
     96     //
     97 
     98     /** Default constructor. */
     99     public NamespaceSupport() {
    100     } // <init>()
    101 
    102     //
    103     // Public methods
    104     //
    105 
    106 	/**
    107 	 * @see org.apache.xerces.xni.NamespaceContext#reset()
    108 	 */
    109     public void reset() {
    110 
    111         // reset namespace and context info
    112         fNamespaceSize = 0;
    113         fCurrentContext = 0;
    114         fContext[fCurrentContext] = fNamespaceSize;
    115 
    116         // bind "xml" prefix to the XML uri
    117         fNamespace[fNamespaceSize++] = PREFIX_XML;
    118         fNamespace[fNamespaceSize++] = XML_URI;
    119         // bind "xmlns" prefix to the XMLNS uri
    120         fNamespace[fNamespaceSize++] = PREFIX_XMLNS;
    121         fNamespace[fNamespaceSize++] = XMLNS_URI;
    122         ++fCurrentContext;
    123 
    124     } // reset(SymbolTable)
    125 
    126 
    127 	/**
    128 	 * @see org.apache.xerces.xni.NamespaceContext#pushContext()
    129 	 */
    130     public void pushContext() {
    131 
    132         // extend the array, if necessary
    133         if (fCurrentContext + 1 == fContext.length) {
    134             int[] contextarray = new int[fContext.length * 2];
    135             System.arraycopy(fContext, 0, contextarray, 0, fContext.length);
    136             fContext = contextarray;
    137         }
    138 
    139         // push context
    140         fContext[++fCurrentContext] = fNamespaceSize;
    141 
    142     } // pushContext()
    143 
    144 
    145 	/**
    146 	 * @see org.apache.xerces.xni.NamespaceContext#popContext()
    147 	 */
    148     public void popContext() {
    149         fNamespaceSize = fContext[fCurrentContext--];
    150     } // popContext()
    151 
    152 	/**
    153 	 * @see org.apache.xerces.xni.NamespaceContext#declarePrefix(String, String)
    154 	 */
    155     public boolean declarePrefix(String prefix, String uri) {
    156         // ignore "xml" and "xmlns" prefixes
    157         if (prefix == PREFIX_XML || prefix == PREFIX_XMLNS) {
    158             return false;
    159         }
    160 
    161         // see if prefix already exists in current context
    162         for (int i = fNamespaceSize; i > fContext[fCurrentContext]; i -= 2) {
    163             //if (fNamespace[i - 2] == prefix) {
    164         	if (fNamespace[i - 2].equals(prefix) )  {
    165                 // REVISIT: [Q] Should the new binding override the
    166                 //          previously declared binding or should it
    167                 //          it be ignored? -Ac
    168                 // NOTE:    The SAX2 "NamespaceSupport" helper allows
    169                 //          re-bindings with the new binding overwriting
    170                 //          the previous binding. -Ac
    171                 fNamespace[i - 1] = uri;
    172                 return true;
    173             }
    174         }
    175 
    176         // resize array, if needed
    177         if (fNamespaceSize == fNamespace.length) {
    178             String[] namespacearray = new String[fNamespaceSize * 2];
    179             System.arraycopy(fNamespace, 0, namespacearray, 0, fNamespaceSize);
    180             fNamespace = namespacearray;
    181         }
    182 
    183         // bind prefix to uri in current context
    184         fNamespace[fNamespaceSize++] = prefix;
    185         fNamespace[fNamespaceSize++] = uri;
    186 
    187         return true;
    188 
    189     } // declarePrefix(String,String):boolean
    190 
    191 	/**
    192 	 * @see org.apache.xerces.xni.NamespaceContext#getURI(String)
    193 	 */
    194     public String getURI(String prefix) {
    195 
    196         // find prefix in current context
    197         for (int i = fNamespaceSize; i > 0; i -= 2) {
    198             //if (fNamespace[i - 2] == prefix) {
    199         	if (fNamespace[i - 2].equals(prefix) ) {
    200                 return fNamespace[i - 1];
    201             }
    202         }
    203 
    204         // prefix not found
    205         return null;
    206 
    207     } // getURI(String):String
    208 
    209 
    210 	/**
    211 	 * @see org.apache.xerces.xni.NamespaceContext#getPrefix(String)
    212 	 */
    213     public String getPrefix(String uri) {
    214 
    215         // find uri in current context
    216         for (int i = fNamespaceSize; i > 0; i -= 2) {
    217             //if (fNamespace[i - 1] == uri) {
    218         	if (fNamespace[i - 1].equals(uri) ) {
    219                 //if (getURI(fNamespace[i - 2]) == uri)
    220         		if (getURI(fNamespace[i - 2]).equals(uri) )
    221                     return fNamespace[i - 2];
    222             }
    223         }
    224 
    225         // uri not found
    226         return null;
    227 
    228     } // getPrefix(String):String
    229 
    230 
    231 	/**
    232 	 * @see org.apache.xerces.xni.NamespaceContext#getDeclaredPrefixCount()
    233 	 */
    234     public int getDeclaredPrefixCount() {
    235         return (fNamespaceSize - fContext[fCurrentContext]) / 2;
    236     } // getDeclaredPrefixCount():int
    237 
    238 	/**
    239 	 * @see org.apache.xerces.xni.NamespaceContext#getDeclaredPrefixAt(int)
    240 	 */
    241     public String getDeclaredPrefixAt(int index) {
    242         return fNamespace[fContext[fCurrentContext] + index * 2];
    243     } // getDeclaredPrefixAt(int):String
    244 
    245 	/**
    246 	 * @see org.apache.xerces.xni.NamespaceContext#getAllPrefixes()
    247 	 */
    248 	public Enumeration getAllPrefixes() {
    249         int count = 0;
    250         if (fPrefixes.length < (fNamespace.length/2)) {
    251             // resize prefix array
    252             String[] prefixes = new String[fNamespaceSize];
    253             fPrefixes = prefixes;
    254         }
    255         String prefix = null;
    256         boolean unique = true;
    257         for (int i = 2; i < (fNamespaceSize-2); i += 2) {
    258             prefix = fNamespace[i + 2];
    259             for (int k=0;k<count;k++){
    260                 if (fPrefixes[k]==prefix){
    261                     unique = false;
    262                     break;
    263                 }
    264             }
    265             if (unique){
    266                 fPrefixes[count++] = prefix;
    267             }
    268             unique = true;
    269         }
    270 		return new Prefixes(fPrefixes, count);
    271 	}
    272 
    273     protected final class Prefixes implements Enumeration {
    274         private String[] prefixes;
    275         private int counter = 0;
    276         private int size = 0;
    277 
    278 		/**
    279 		 * Constructor for Prefixes.
    280 		 */
    281 		public Prefixes(String [] prefixes, int size) {
    282 			this.prefixes = prefixes;
    283             this.size = size;
    284 		}
    285 
    286        /**
    287 		 * @see java.util.Enumeration#hasMoreElements()
    288 		 */
    289 		public boolean hasMoreElements() {
    290 			return (counter< size);
    291 		}
    292 
    293 		/**
    294 		 * @see java.util.Enumeration#nextElement()
    295 		 */
    296 		public Object nextElement() {
    297             if (counter< size){
    298                 return fPrefixes[counter++];
    299             }
    300 			throw new NoSuchElementException("Illegal access to Namespace prefixes enumeration.");
    301 		}
    302 
    303         public String toString(){
    304             StringBuffer buf = new StringBuffer();
    305             for (int i=0;i<size;i++){
    306                 buf.append(prefixes[i]);
    307                 buf.append(" ");
    308             }
    309 
    310             return buf.toString();
    311         }
    312 
    313 }
    314 
    315 } // class NamespaceSupport
    316