19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/* 29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one 39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * or more contributor license agreements. See the NOTICE file 49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed with this work for additional information 59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * regarding copyright ownership. The ASF licenses this file 69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to you under the Apache License, Version 2.0 (the "License"); 79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * you may not use this file except in compliance with the License. 89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * You may obtain a copy of the License at 99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unless required by applicable law or agreed to in writing, software 139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * See the License for the specific language governing permissions and 169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * limitations under the License. 179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/* 199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * $Id: NamespaceMappings.java 469648 2006-10-31 20:52:27Z minchau $ 209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpackage org.apache.xml.serializer; 229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.util.Enumeration; 249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.util.Hashtable; 259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.xml.sax.ContentHandler; 279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.xml.sax.SAXException; 289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/** 309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This class keeps track of the currently defined namespaces. Conceptually the 319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * prefix/uri/depth triplets are pushed on a stack pushed on a stack. The depth 329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * indicates the nesting depth of the element for which the mapping was made. 339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <p>For example: 359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <pre> 369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <chapter xmlns:p1="def"> 379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <paragraph xmlns:p2="ghi"> 389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <sentance xmlns:p3="jkl"> 399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * </sentance> 409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * </paragraph> 419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <paragraph xlmns:p4="mno"> 429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * </paragraph> 439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * </chapter> 449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * </pre> 459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * When the <chapter> element is encounted the prefix "p1" associated with uri 479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * "def" is pushed on the stack with depth 1. 489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * When the first <paragraph> is encountered "p2" and "ghi" are pushed with 499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * depth 2. 509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * When the <sentance> is encountered "p3" and "jkl" are pushed with depth 3. 519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * When </sentance> occurs the popNamespaces(3) will pop "p3"/"jkl" off the 529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * stack. Of course popNamespaces(2) would pop anything with depth 2 or 539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * greater. 549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * So prefix/uri pairs are pushed and poped off the stack as elements are 569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * processed. At any given moment of processing the currently visible prefixes 579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * are on the stack and a prefix can be found given a uri, or a uri can be found 589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * given a prefix. 599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This class is intended for internal use only. However, it is made public because 619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * other packages require it. 629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @xsl.usage internal 639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpublic class NamespaceMappings 659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson{ 669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This member is continually incremented when new prefixes need to be 689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * generated. ("ns0" "ns1" ...) 699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private int count = 0; 719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Each entry (prefix) in this hashtable points to a Stack of URIs 749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This table maps a prefix (String) to a Stack of NamespaceNodes. 759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * All Namespace nodes in that retrieved stack have the same prefix, 769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * though possibly different URI's or depths. Such a stack must have 779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * mappings at deeper depths push later on such a stack. Mappings pushed 789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * earlier on the stack will have smaller values for MappingRecord.m_declarationDepth. 799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private Hashtable m_namespaces = new Hashtable(); 819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This stack is used as a convenience. 849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * It contains the pushed NamespaceNodes (shallowest 859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to deepest) and is used to delete NamespaceNodes 869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * when leaving the current element depth 879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to returning to the parent. The mappings of the deepest 889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * depth can be popped of the top and the same node 899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * can be removed from the appropriate prefix stack. 909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * All prefixes pushed at the current depth can be 929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * removed at the same time by using this stack to 939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * ensure prefix/uri map scopes are closed correctly. 949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private Stack m_nodeStack = new Stack(); 969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private static final String EMPTYSTRING = ""; 989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private static final String XML_PREFIX = "xml"; // was "xmlns" 999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Default constructor 1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @see java.lang.Object#Object() 1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public NamespaceMappings() 1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson initNamespaces(); 1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This method initializes the namespace object with appropriate stacks 1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * and predefines a few prefix/uri pairs which always exist. 1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private void initNamespaces() 1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // The initial prefix mappings will never be deleted because they are at element depth -1 1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // (a kludge) 1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Define the default namespace (initially maps to "" uri) 1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Stack stack; 1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MappingRecord nn; 1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson nn = new MappingRecord(EMPTYSTRING, EMPTYSTRING, -1); 1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson stack = createPrefixStack(EMPTYSTRING); 1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson stack.push(nn); 1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // define "xml" namespace 1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson nn = new MappingRecord(XML_PREFIX, "http://www.w3.org/XML/1998/namespace", -1); 1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson stack = createPrefixStack(XML_PREFIX); 1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson stack.push(nn); 1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Use a namespace prefix to lookup a namespace URI. 1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param prefix String the prefix of the namespace 1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return the URI corresponding to the prefix, returns "" 1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * if there is no visible mapping. 1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public String lookupNamespace(String prefix) 1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson String uri = null; 1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final Stack stack = getPrefixStack(prefix); 1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (stack != null && !stack.isEmpty()) { 1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson uri = ((MappingRecord) stack.peek()).m_uri; 1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (uri == null) 1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson uri = EMPTYSTRING; 1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return uri; 1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MappingRecord getMappingFromPrefix(String prefix) { 1529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final Stack stack = (Stack) m_namespaces.get(prefix); 1539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return stack != null && !stack.isEmpty() ? 1549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson ((MappingRecord) stack.peek()) : null; 1559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 1589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Given a namespace uri, and the namespaces mappings for the 1599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * current element, return the current prefix for that uri. 1609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param uri the namespace URI to be search for 1629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return an existing prefix that maps to the given URI, null if no prefix 1639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * maps to the given namespace URI. 1649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 1659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public String lookupPrefix(String uri) 1669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson String foundPrefix = null; 1689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Enumeration prefixes = m_namespaces.keys(); 1699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while (prefixes.hasMoreElements()) 1709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson String prefix = (String) prefixes.nextElement(); 1729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson String uri2 = lookupNamespace(prefix); 1739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (uri2 != null && uri2.equals(uri)) 1749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson foundPrefix = prefix; 1769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson break; 1779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return foundPrefix; 1809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MappingRecord getMappingFromURI(String uri) 1839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MappingRecord foundMap = null; 1859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Enumeration prefixes = m_namespaces.keys(); 1869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while (prefixes.hasMoreElements()) 1879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson String prefix = (String) prefixes.nextElement(); 1899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MappingRecord map2 = getMappingFromPrefix(prefix); 1909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (map2 != null && (map2.m_uri).equals(uri)) 1919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson foundMap = map2; 1939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson break; 1949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return foundMap; 1979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 2009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Undeclare the namespace that is currently pointed to by a given prefix 2019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 2029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson boolean popNamespace(String prefix) 2039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Prefixes "xml" and "xmlns" cannot be redefined 2059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (prefix.startsWith(XML_PREFIX)) 2069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 2089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Stack stack; 2119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if ((stack = getPrefixStack(prefix)) != null) 2129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson stack.pop(); 2149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return true; 2159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 2179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 2209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Declare a mapping of a prefix to namespace URI at the given element depth. 2219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param prefix a String with the prefix for a qualified name 2229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param uri a String with the uri to which the prefix is to map 2239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param elemDepth the depth of current declaration 2249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 2259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public boolean pushNamespace(String prefix, String uri, int elemDepth) 2269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Prefixes "xml" and "xmlns" cannot be redefined 2289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (prefix.startsWith(XML_PREFIX)) 2299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 2319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Stack stack; 2349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Get the stack that contains URIs for the specified prefix 2359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if ((stack = (Stack) m_namespaces.get(prefix)) == null) 2369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_namespaces.put(prefix, stack = new Stack()); 2389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (!stack.empty()) 2419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MappingRecord mr = (MappingRecord)stack.peek(); 2439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (uri.equals(mr.m_uri) || elemDepth == mr.m_declarationDepth) { 2449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // If the same prefix/uri mapping is already on the stack 2459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // don't push this one. 2469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Or if we have a mapping at the same depth 2479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // don't replace by pushing this one. 2489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return false; 2499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MappingRecord map = new MappingRecord(prefix,uri,elemDepth); 2529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson stack.push(map); 2539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_nodeStack.push(map); 2549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return true; 2559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 2589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Pop, or undeclare all namespace definitions that are currently 2599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * declared at the given element depth, or deepter. 2609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param elemDepth the element depth for which mappings declared at this 2619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * depth or deeper will no longer be valid 2629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param saxHandler The ContentHandler to notify of any endPrefixMapping() 2639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * calls. This parameter can be null. 2649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 2659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson void popNamespaces(int elemDepth, ContentHandler saxHandler) 2669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while (true) 2689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (m_nodeStack.isEmpty()) 2709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return; 2719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MappingRecord map = (MappingRecord) (m_nodeStack.peek()); 2729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int depth = map.m_declarationDepth; 2739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (elemDepth < 1 || map.m_declarationDepth < elemDepth) 2749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson break; 2759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /* the depth of the declared mapping is elemDepth or deeper 2769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * so get rid of it 2779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 2789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MappingRecord nm1 = (MappingRecord) m_nodeStack.pop(); 2809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // pop the node from the stack 2819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson String prefix = map.m_prefix; 2829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Stack prefixStack = getPrefixStack(prefix); 2849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MappingRecord nm2 = (MappingRecord) prefixStack.peek(); 2859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (nm1 == nm2) 2869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // It would be nice to always pop() but we 2889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // need to check that the prefix stack still has 2899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // the node we want to get rid of. This is because 2909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // the optimization of essentially this situation: 2919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // <a xmlns:x="abc"><b xmlns:x="" xmlns:x="abc" /></a> 2929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // will remove both mappings in <b> because the 2939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // new mapping is the same as the masked one and we get 2949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // <a xmlns:x="abc"><b/></a> 2959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // So we are only removing xmlns:x="" or 2969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // xmlns:x="abc" from the depth of element <b> 2979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // when going back to <a> if in fact they have 2989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // not been optimized away. 2999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // 3009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson prefixStack.pop(); 3019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (saxHandler != null) 3029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson try 3049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson saxHandler.endPrefixMapping(prefix); 3069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson catch (SAXException e) 3089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // not much we can do if they aren't willing to listen 3109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 3189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Generate a new namespace prefix ( ns0, ns1 ...) not used before 3199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return String a new namespace prefix ( ns0, ns1, ns2 ...) 3209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 3219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public String generateNextPrefix() 3229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return "ns" + (count++); 3249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 3289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This method makes a clone of this object. 3299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 3309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 3319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public Object clone() throws CloneNotSupportedException { 3329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson NamespaceMappings clone = new NamespaceMappings(); 3339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson clone.m_nodeStack = (NamespaceMappings.Stack) m_nodeStack.clone(); 3349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson clone.count = this.count; 3359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson clone.m_namespaces = (Hashtable) m_namespaces.clone(); 3369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson clone.count = count; 3389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return clone; 3399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final void reset() 3439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson this.count = 0; 3459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson this.m_namespaces.clear(); 3469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson this.m_nodeStack.clear(); 3479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson initNamespaces(); 3499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 3529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Just a little class that ties the 3 fields together 3539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * into one object, and this simplifies the pushing 3549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * and popping of namespaces to one push or one pop on 3559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * one stack rather than on 3 separate stacks. 3569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 3579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson class MappingRecord { 3589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final String m_prefix; // the prefix 3599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final String m_uri; // the uri, possibly "" but never null 3609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // the depth of the element where declartion was made 3619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final int m_declarationDepth; 3629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson MappingRecord(String prefix, String uri, int depth) { 3639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_prefix = prefix; 3649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_uri = (uri==null)? EMPTYSTRING : uri; 3659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_declarationDepth = depth; 3669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 3709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Rather than using java.util.Stack, this private class 3719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * provides a minimal subset of methods and is faster 3729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * because it is not thread-safe. 3739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 3749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private class Stack { 3759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private int top = -1; 3769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private int max = 20; 3779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Object[] m_stack = new Object[max]; 3789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public Object clone() throws CloneNotSupportedException { 3809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson NamespaceMappings.Stack clone = new NamespaceMappings.Stack(); 3819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson clone.max = this.max; 3829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson clone.top = this.top; 3839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson clone.m_stack = new Object[clone.max]; 3849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (int i=0; i <= top; i++) { 3859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // We are just copying references to immutable MappingRecord objects here 3869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // so it is OK if the clone has references to these. 3879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson clone.m_stack[i] = this.m_stack[i]; 3889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return clone; 3909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public Stack() 3939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public Object push(Object o) { 3979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson top++; 3989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (max <= top) { 3999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int newMax = 2*max + 1; 4009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Object[] newArray = new Object[newMax]; 4019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson System.arraycopy(m_stack,0, newArray, 0, max); 4029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson max = newMax; 4039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_stack = newArray; 4049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_stack[top] = o; 4069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return o; 4079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public Object pop() { 4109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Object o; 4119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (0 <= top) { 4129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson o = m_stack[top]; 4139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // m_stack[top] = null; do we really care? 4149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson top--; 4159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 4179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson o = null; 4189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return o; 4199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public Object peek() { 4229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Object o; 4239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (0 <= top) { 4249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson o = m_stack[top]; 4259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 4279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson o = null; 4289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return o; 4299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public Object peek(int idx) { 4329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return m_stack[idx]; 4339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public boolean isEmpty() { 4369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return (top < 0); 4379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public boolean empty() { 4399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return (top < 0); 4409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public void clear() { 4439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (int i=0; i<= top; i++) 4449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_stack[i] = null; 4459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson top = -1; 4469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public Object getElement(int index) { 4499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return m_stack[index]; 4509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 4539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * A more type-safe way to get a stack of prefix mappings 4549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * from the Hashtable m_namespaces 4559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * (this is the only method that does the type cast). 4569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 4579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private Stack getPrefixStack(String prefix) { 4599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Stack fs = (Stack) m_namespaces.get(prefix); 4609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return fs; 4619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 4649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * A more type-safe way of saving stacks under the 4659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * m_namespaces Hashtable. 4669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 4679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private Stack createPrefixStack(String prefix) 4689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Stack fs = new Stack(); 4709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_namespaces.put(prefix, fs); 4719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return fs; 4729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 4759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Given a namespace uri, get all prefixes bound to the Namespace URI in the current scope. 4769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 4779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param uri the namespace URI to be search for 4789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return An array of Strings which are 4799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * all prefixes bound to the namespace URI in the current scope. 4809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * An array of zero elements is returned if no prefixes map to the given 4819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * namespace URI. 4829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 4839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public String[] lookupAllPrefixes(String uri) 4849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson java.util.ArrayList foundPrefixes = new java.util.ArrayList(); 4869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson Enumeration prefixes = m_namespaces.keys(); 4879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson while (prefixes.hasMoreElements()) 4889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson String prefix = (String) prefixes.nextElement(); 4909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson String uri2 = lookupNamespace(prefix); 4919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (uri2 != null && uri2.equals(uri)) 4929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson foundPrefixes.add(prefix); 4949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson String[] prefixArray = new String[foundPrefixes.size()]; 4979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson foundPrefixes.toArray(prefixArray); 4989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return prefixArray; 4999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 5009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 501