001: package org.objectweb.celtix.helpers;
002:
003: import java.util.ArrayList;
004: import java.util.List;
005: import java.util.ListIterator;
006:
007: public class NSStack {
008:
009: private static final String NS_PREFIX_PREFIX = "ns";
010:
011: private final List<List<NSDecl>> stack = new ArrayList<List<NSDecl>>();
012: private List<NSDecl> top;
013: private int size;
014: private int nsPrefixCount = 1;
015:
016: public synchronized void push() {
017: top = new ArrayList<NSDecl>();
018: stack.add(top);
019: size++;
020: }
021:
022: /**
023: * Leave a scope: this removes any NS declarations that were added
024: * in the last scope. Note that I don't bother to validate that you
025: * don't call popScope too many times; that's your problem.
026: */
027: public synchronized void pop() {
028: stack.remove(--size);
029: top = null;
030: if (size != 0) {
031: top = stack.get(size - 1);
032: }
033: }
034:
035: /**
036: * Add a new declaration to the current scope. This is visible within
037: * the current scope as well as from any nested scopes.
038: *
039: * @param prefix the prefix to be used for this namespace
040: * @param URI the namespace name of this namespace.
041: */
042: public synchronized void add(String prefix, String uri) {
043: top.add(new NSDecl(prefix, uri));
044: }
045:
046: /**
047: * Add a new declaration to the current scope using a unique prefix
048: * and return the prefix. This is useful when one just wants to add a
049: * decl and doesn't want to have to deal with creating unique prefixes.
050: * If the namespace name is already declared and in scope, then the
051: * previously declared prefix is returned.
052: *
053: * @param URI the namespace name of this namespace
054: * @return the unique prefix created or previously declared
055: * for this namespace
056: */
057: public synchronized String add(String uri) {
058: String uniquePrefix = getPrefix(uri);
059:
060: if (uniquePrefix == null) {
061: do {
062: uniquePrefix = NS_PREFIX_PREFIX + nsPrefixCount++;
063: } while (getURI(uniquePrefix) != null);
064: add(uniquePrefix, uri);
065: }
066: return uniquePrefix;
067: }
068:
069: /**
070: * Return the prefix associated with the given namespace name by
071: * looking thru all the namespace declarations that are in scope.
072: *
073: * @param URI the namespace name for whom a declared prefix is desired
074: * @return the prefix or null if namespace name not found
075: */
076: public String getPrefix(String uri) {
077: for (int i = size - 1; i >= 0; i--) {
078: List<NSDecl> scope = stack.get(i);
079: ListIterator<NSDecl> lsIterator = scope.listIterator();
080:
081: while (lsIterator.hasNext()) {
082: NSDecl nsd = lsIterator.next();
083:
084: if (nsd.getUri().equals(uri)) {
085: return nsd.getPrefix();
086: }
087: }
088: }
089: return null;
090: }
091:
092: /**
093: * Return the namespace name associated with the given prefix by
094: * looking thru all the namespace declarations that are in scope.
095: *
096: * @param prefix the prefix for whom a declared namespace name is desired
097: * @return the namespace name or null if prefix not found
098: */
099: public String getURI(String prefix) {
100: for (int i = size - 1; i >= 0; i--) {
101: List<NSDecl> scope = stack.get(i);
102: ListIterator<NSDecl> lsIterator = scope.listIterator();
103:
104: while (lsIterator.hasNext()) {
105: NSDecl nsd = lsIterator.next();
106:
107: if (nsd.getPrefix().equals(prefix)) {
108: return nsd.getUri();
109: }
110: }
111: }
112: return null;
113: }
114:
115: }
|