You are viewing a plain text version of this content. The canonical link for it is here.
Posted to soap-dev@xml.apache.org by sn...@apache.org on 2002/11/18 15:23:06 UTC
cvs commit: xml-soap/java/src/org/apache/soap/util/xml NSStack.java
snichol 2002/11/18 06:23:06
Modified: java/src/org/apache/soap/util/xml NSStack.java
Log:
Submitted by: Pavel Ausianik <Pa...@epam.com>
I have prepared patch for NSStack, moving from growing number of Vectors to
3 arrays per stack.
I also used intern() String comparison, but this only do benefits for large
number of comparisons, and it may happen that having just String.equals()
could be better.
Revision Changes Path
1.5 +200 -135 xml-soap/java/src/org/apache/soap/util/xml/NSStack.java
Index: NSStack.java
===================================================================
RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/util/xml/NSStack.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- NSStack.java 10 Nov 2000 15:20:58 -0000 1.4
+++ NSStack.java 18 Nov 2002 14:23:06 -0000 1.5
@@ -2,7 +2,7 @@
* The Apache Software License, Version 1.1
*
*
- * Copyright (c) 2000 The Apache Software Foundation. All rights
+ * Copyright (c) 2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -10,7 +10,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
@@ -18,7 +18,7 @@
* distribution.
*
* 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
+ * if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
@@ -26,7 +26,7 @@
*
* 4. The names "SOAP" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
- * software without prior written permission. For written
+ * software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
@@ -57,9 +57,10 @@
package org.apache.soap.util.xml;
-import java.io.*;
-import java.util.*;
-import org.apache.soap.util.xml.* ;
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.soap.util.xml.*;
/**
* This class implements a namespace stack for XML apps to use. If
@@ -79,134 +80,198 @@
* declaration.
*
* @author Sanjiva Weerawarana (sanjiva@watson.ibm.com)
+ * @author Pavel Ausianik <Pavel_Ausianik@epam.com>
*/
-public class NSStack {
- Vector nss = new Vector (); // vector holding vectors of ns decls (stack)
- int nssCount = 0; // number of items on the stack
- Vector tos; // the vector @ the top of the stack
- private final static String nsPrefixPrefix = "ns";
- private int nsPrefixCount = 1;
-
- /**
- * Enter a new scope: after calling this I'm ready to accept new
- * declarations into that scope.
- */
- public void pushScope () {
- nss.addElement (tos = new Vector ());
- nssCount++;
- }
-
- /**
- * Leave a scope: this removes any NS declarations that were added
- * in the last scope. Note that I don't bother to validate that you
- * don't call popScope too many times; that's your problem.
- */
- public void popScope () {
- nss.removeElementAt (--nssCount);
- tos = (nssCount != 0) ? (Vector) nss.elementAt (nssCount-1) : null;
- }
-
- /**
- * Add a new declaration to the current scope. This is visible within
- * the current scope as well as from any nested scopes.
- *
- * @param prefix the prefix to be used for this namespace
- * @param URI the namespace name of this namespace.
- */
- synchronized public void addNSDeclaration (String prefix, String URI) {
- tos.addElement (new NSDecl (prefix, URI));
- }
-
- /**
- * Add a new declaration to the current scope using a unique prefix
- * and return the prefix. This is useful when one just wants to add a
- * decl and doesn't want to have to deal with creating unique prefixes.
- * If the namespace name is already declared and in scope, then the
- * previously declared prefix is returned.
- *
- * @param URI the namespace name of this namespace
- * @return the unique prefix created or previously declared
- * for this namespace
- */
- synchronized public String addNSDeclaration (String URI) {
- String uniquePrefix = getPrefixFromURI (URI);
- if (uniquePrefix == null) {
- do {
- uniquePrefix = nsPrefixPrefix + nsPrefixCount++;
- } while (getURIFromPrefix (uniquePrefix) != null);
- addNSDeclaration (uniquePrefix, URI);
- }
- return uniquePrefix;
- }
-
- /**
- * Return the prefix associated with the given namespace name by
- * looking thru all the namespace declarations that are in scope.
- *
- * @param URI the namespace name for whom a declared prefix is desired
- * @return the prefix or null if namespace name not found
- */
- public String getPrefixFromURI (String URI) {
- for (int i = nssCount-1; i >= 0; i--) {
- Vector scope = (Vector) nss.elementAt (i);
- for (Enumeration e = scope.elements (); e.hasMoreElements (); ) {
- NSDecl nsd = (NSDecl) e.nextElement ();
- if (nsd.URI.equals (URI)) {
- return nsd.prefix;
- }
- }
- }
- return null;
- }
-
- /**
- * Return the prefix associated with the given namespace name by
- * looking thru all the namespace declarations that are in scope.
- * If the namespace declaration is not found, create one and
- * return the generated prefix.
- *
- * @param URI the namespace name for whom a declared prefix is desired
- * @return the prefix (will never return null)
- */
- synchronized public String getPrefixFromURI (String namespaceURI,
- Writer sink)
- throws IOException {
- String prefix = getPrefixFromURI (namespaceURI);
-
- if (prefix == null) {
- prefix = addNSDeclaration (namespaceURI);
-
- sink.write (" xmlns:" + prefix + "=\"" + namespaceURI + '\"');
- }
-
- return prefix;
- }
-
- /**
- * Return the namespace name associated with the given prefix by
- * looking thru all the namespace declarations that are in scope.
- *
- * @param prefix the prefix for whom a declared namespace name is desired
- * @return the namespace name or null if prefix not found
- */
- public String getURIFromPrefix (String prefix) {
- for (int i = nssCount-1; i >= 0; i--) {
- Vector scope = (Vector) nss.elementAt (i);
- for (Enumeration e = scope.elements (); e.hasMoreElements (); ) {
- NSDecl nsd = (NSDecl) e.nextElement ();
- if (nsd.prefix.equals (prefix)) {
- return nsd.URI;
- }
- }
- }
- return null;
- }
-
- // MJD - debug
- public String toString()
- {
- return nss.toString();
- }
- // MJD - debug
+public final class NSStack {
+ private String[] URIStack;
+ private String[] prefixStack;
+
+ private int[] scope;
+ private int top = 0;
+ private int iterator = -1;
+ private final static String NSPREFIX = "ns";
+ private int nsPrefixCount = 0;
+
+ private static String[] predefinedNamespaces;
+
+ private static final int START_ARRAY_SIZE = 32;
+
+ public NSStack() {
+ URIStack = new String[START_ARRAY_SIZE];
+ prefixStack = new String[START_ARRAY_SIZE];
+ scope = new int[START_ARRAY_SIZE];
+ scope[0] = -1;
+ }
+
+ /**
+ * Creates a predefined Namespace string
+ * Assuming that in the single application , the number of names is the same
+ * between calls. We'll benefit from caching on continuous operations
+ */
+ synchronized private static String getPredefinedNamespace(int nsCount) {
+ if (predefinedNamespaces == null)
+ {
+ predefinedNamespaces = new String[START_ARRAY_SIZE];
+ for (int i=0; i<START_ARRAY_SIZE; i++)
+ predefinedNamespaces[i] = NSPREFIX + (i+1);
+ } else if (nsCount >= predefinedNamespaces.length) {
+ int length = predefinedNamespaces.length;
+ String[] newnamespace = new String[length * 2];
+ System.arraycopy(predefinedNamespaces, 0, newnamespace, 0, length);
+ for (int i=0; i<length; i++)
+ predefinedNamespaces[i+length] = NSPREFIX + (i+length+1);
+ }
+ return predefinedNamespaces[nsCount];
+ }
+
+ /**
+ * Enter a new scope: after calling this I'm ready to accept new
+ * declarations into that scope.
+ */
+ public void pushScope() {
+
+ top++;
+ int length = scope.length;
+
+ if (top >= length) {
+ int newscope[] = new int[length * 2];
+ System.arraycopy(scope, 0, newscope, 0, length);
+ scope = newscope;
+ }
+
+ scope[top] = iterator;
+
+ }
+
+ /**
+ * Leave a scope: this removes any NS declarations that were added
+ * in the last scope. Note that I don't bother to validate that you
+ * don't call popScope too many times; that's your problem.
+ */
+ public void popScope() {
+ scope[top] = 0;
+ top--;
+ iterator = top >= 0 ? scope[top] : 0;
+ }
+
+ /**
+ * Add a new declaration to the current scope. This is visible within
+ * the current scope as well as from any nested scopes.
+ *
+ * @param prefix the prefix to be used for this namespace
+ * @param URI the namespace name of this namespace.
+ */
+ public void addNSDeclaration(String prefix, String namespaceURI) {
+ int length = URIStack.length;
+ iterator++;
+
+ if (iterator >= length) {
+ String newstack[] = new String[length * 2];
+ System.arraycopy(URIStack, 0, newstack, 0, length);
+ URIStack = newstack;
+ newstack = new String[length * 2];
+ System.arraycopy(prefixStack, 0, newstack, 0, length);
+ prefixStack = newstack;
+ }
+ // scope too small - expand - very unlikely
+ URIStack[iterator] = namespaceURI.intern();
+ prefixStack[iterator] = prefix.intern();
+ }
+
+ /**
+ * Add a new declaration to the current scope using a unique prefix
+ * and return the prefix. This is useful when one just wants to add a
+ * decl and doesn't want to have to deal with creating unique prefixes.
+ * If the namespace name is already declared and in scope, then the
+ * previously declared prefix is returned.
+ *
+ * @param URI the namespace name of this namespace
+ * @return the unique prefix created or previously declared
+ * for this namespace
+ */
+ public String addNSDeclaration(String URI) {
+ String uniquePrefix = getPrefixFromURI(URI);
+ if (uniquePrefix == null) {
+ do {
+ uniquePrefix = getPredefinedNamespace(nsPrefixCount++);
+ } while (getURIFromPrefix(uniquePrefix) != null);
+ addNSDeclaration(uniquePrefix, URI);
+ }
+ return uniquePrefix;
+ }
+
+ /**
+ * Return the prefix associated with the given namespace name by
+ * looking thru all the namespace declarations that are in scope.
+ *
+ * @param URI the namespace name for whom a declared prefix is desired
+ * @return the prefix or null if namespace name not found
+ */
+ public String getPrefixFromURI(String namespaceURI) {
+ if ((namespaceURI == null) || (namespaceURI.equals("")))
+ return null;
+
+ namespaceURI = namespaceURI.intern();
+ for (int cursor = iterator; cursor >= 0; cursor--) {
+ if (URIStack[cursor] == namespaceURI)
+ return prefixStack[cursor];
+ }
+ return null;
+ }
+
+ /**
+ * Return the prefix associated with the given namespace name by
+ * looking thru all the namespace declarations that are in scope.
+ * If the namespace declaration is not found, create one and
+ * return the generated prefix.
+ *
+ * @param URI the namespace name for whom a declared prefix is desired
+ * @return the prefix (will never return null)
+ */
+ public String getPrefixFromURI(String namespaceURI, Writer sink)
+ throws IOException {
+ String prefix = getPrefixFromURI(namespaceURI);
+
+ if (prefix == null) {
+ prefix = addNSDeclaration(namespaceURI);
+
+ sink.write(" xmlns:");
+ sink.write(prefix);
+ sink.write("=\"");
+ sink.write(namespaceURI);
+ sink.write('\"');
+ }
+
+ return prefix;
+ }
+
+ /**
+ * Given a prefix, return the associated namespace (if any).
+ */
+ public String getURIFromPrefix(String prefix) {
+ if (prefix == null)
+ prefix = "";
+ prefix = prefix.intern();
+ for (int cursor = iterator; cursor >= 0; cursor--) {
+ if (prefixStack[cursor] == prefix)
+ return URIStack[cursor];
+ }
+
+ return null;
+ }
+
+ public void dump() {
+ int end = iterator;
+ int start = 0;
+ for (int cursor = top; cursor >= 0; cursor--, end = start - 1) {
+ start = scope[cursor] + 1;
+
+ System.out.println("Level: " + cursor);
+
+ for (int j = start; j <= end; j++) {
+ System.out.println(" Map:" + URIStack[cursor] + " -> " +prefixStack[cursor]);
+ }
+ }
+ }
}
--
To unsubscribe, e-mail: <ma...@xml.apache.org>
For additional commands, e-mail: <ma...@xml.apache.org>