Keeps track of namespaces declarations and resolve namespaces names.
This class also provides a very convenient and safe way of handling
namespace declarations in SAX pipes. It also allows to filter duplicate namespace
declarations that too often clutter up XML documents that went through
several transformations, and avoid useless namespace declarations that aren't followed
by element events.
| Method from org.apache.cocoon.xml.NamespacesTable Detail: |
public NamespacesTable.Declaration addDeclaration(String prefix,
String uri) {
// Find a previous declaration of the same prefix
Entry dup = this.lastEntry;
while (dup != null && !dup.prefix.equals(prefix)) {
dup = dup.previous;
}
if (dup != null) {
if (usesScopes && dup.uri.equals(uri)) {
return dup;
}
dup.overriden = true;
}
Entry e = Entry.create(prefix, uri);
e.previous = this.lastEntry;
e.overrides = dup;
this.lastEntry = e;
// this always starts the declared prefix chain
this.lastDeclaredEntry = e;
return e;
}
Declare a new namespace prefix-uri mapping. |
public void clear() {
this.lastEntry = Entry.create("","");
this.addDeclaration("xml", "http://www.w3.org/XML/1998/namespace");
// Lock this scope
this.lastEntry.closedScopes = 1;
}
Clear and reinitialize this namespace table before reuse. |
public void enterScope() {
this.usesScopes = true;
this.lastEntry.closedScopes++;
this.lastDeclaredEntry = null;
}
|
public void enterScope(ContentHandler handler) throws SAXException {
this.usesScopes = true;
Entry current = this.lastEntry;
while (current != null && current.closedScopes == 0) {
handler.startPrefixMapping(current.prefix, current.uri);
current = current.previous;
}
this.lastEntry.closedScopes++;
this.lastDeclaredEntry = null;
}
|
public NamespacesTable.Declaration[] getCurrentScopeDeclarations() {
int count = 0;
Entry current = this.lastDeclaredEntry;
while (current != null && current.closedScopes == 0) {
count++;
current = current.previous;
}
if (count == 0) return NO_DECLS;
Declaration[] decls = new Declaration[count];
count = 0;
current = this.lastDeclaredEntry;
while (current != null && current.closedScopes == 0) {
decls[count++] = current;
current = current.previous;
}
return decls;
}
Get the declarations that were declared within the current scope. |
public String getPrefix(String uri) {
Entry current = this.lastEntry;
while (current != null) {
if(!current.overriden && current.uri.equals(uri))
return current.prefix;
current = current.previous;
}
return null;
}
Return one of the prefixes currently mapped to the specified URI or
null. |
public String[] getPrefixes(String uri) {
Entry current=this.lastEntry;
int count=0;
while (current!=null) {
if(!current.overriden && current.uri.equals(uri))
count++;
current=current.previous;
}
if (count==0) return(new String[0]);
String prefixes[]=new String[count];
count=0;
current = this.lastEntry;
while (current!=null) {
if(!current.overriden && current.uri.equals(uri))
prefixes[count++] = current.prefix;
current = current.previous;
}
return prefixes;
}
Return an array with all prefixes currently mapped to the specified URI.
The array length might be zero if no prefixes are associated with
the specified uri. |
public String getUri(String prefix) {
Entry current = this.lastEntry;
while (current != null) {
if (current.prefix.equals(prefix)) {
return current.uri;
}
current = current.previous;
}
// Not found
return null;
}
Return the URI associated with the given prefix or null if the
prefix was not mapped. |
public void leaveScope() {
Entry current = this.lastEntry;
// Purge declarations that were added but not included in a scope
while (current.closedScopes == 0) {
current = current.previous;
}
current.closedScopes--;
if (current.closedScopes == 0) {
this.lastDeclaredEntry = current;
} else {
// More than one scope closed here: no local declarations
this.lastDeclaredEntry = null;
}
while (current != null && current.closedScopes == 0) {
Entry overrides = current.overrides;
if (overrides != null) {
// No more overriden
overrides.overriden = false;
}
current = current.previous;
}
this.lastEntry = current;
}
|
public void leaveScope(ContentHandler handler) throws SAXException {
Entry current = this.lastEntry;
// Purge declarations that were added but not included in a scope
while (current.closedScopes == 0) {
current = current.previous;
}
current.closedScopes--;
if (current.closedScopes == 0) {
this.lastDeclaredEntry = current;
} else {
// More than one scope closed here: no local declarations
this.lastDeclaredEntry = null;
}
while (current != null && current.closedScopes == 0) {
handler.endPrefixMapping(current.prefix);
Entry overrides = current.overrides;
if (overrides != null) {
// No more overriden
overrides.overriden = false;
}
current = current.previous;
}
this.lastEntry = current;
}
|
public NamespacesTable.Declaration removeDeclaration(String prefix) {
if (usesScopes) {
// Automatically handled in leaveScope
return null; // or throw and IllegalStateException if enterScope(handler) was used?
}
Entry current = this.lastEntry;
Entry afterCurrent = null;
while(current != null) {
if (current.closedScopes > 0) {
// Don't undeclare mappings not declared in this scope
return null;
}
if (current.prefix.equals(prefix)) {
// Got it
// Remove it from the chain
if (afterCurrent != null) {
afterCurrent.previous = current.previous;
}
// And report closed scopes on the previous entry
current.previous.closedScopes += current.closedScopes;
Entry overrides = current.overrides;
if (overrides != null) {
// No more overriden
overrides.overriden = false;
}
if (this.lastDeclaredEntry == current) {
if (current.previous.closedScopes == 0) {
this.lastDeclaredEntry = current.previous;
} else {
this.lastDeclaredEntry = null;
}
}
if (this.lastEntry == current) {
this.lastEntry = current.previous;
}
return current;
}
afterCurrent = current;
current = current.previous;
}
// Not found
return null;
}
Undeclare a namespace prefix-uri mapping. If the prefix was previously declared
mapping another URI, its value is restored.
When using #enterScope() /#leaveScope() , this method does nothing and always
returns null, as declaration removal is handled in #leaveScope() . |
public NamespacesTable.Name resolve(String uri,
String raw,
String prefix,
String local) throws SAXException {
if (uri==null) uri="";
if (raw==null) raw="";
if (prefix==null) prefix="";
if (local==null) local="";
// Start examining the URI
if (raw.length() >0) {
// The raw name was specified
int pos=raw.indexOf(':");
if (pos >0) {
// We have a namespace prefix:local separator
String pre=raw.substring(0,pos);
String loc=raw.substring(pos+1);
if (prefix.length()==0) prefix=pre;
else if (!prefix.equals(pre))
throw new SAXException("Raw/Prefix mismatch");
if (local.length()==0) local=loc;
else if (!local.equals(loc))
throw new SAXException("Raw/Local Name mismatch");
} else {
// We don't have a prefix:local separator
if (prefix.length() >0)
throw new SAXException("Raw Name/Prefix mismatch");
if (local.length()==0) local=raw;
else if (!local.equals(raw))
throw new SAXException("Raw Name/Local Name mismatch");
}
} else {
// The raw name was not specified
if (local.length()==0) throw new SAXException("No Raw/Local Name");
if (prefix.length()==0) raw=local;
else raw=prefix+':"+local;
}
// We have resolved and checked data between the raw, local, and
// prefix... We have to doublecheck the namespaces.
if (uri.length() >0) {
// We have a URI and a prefix, check them
if ((prefix.length() >0) && (!uri.equals(this.getUri(prefix)))) {
throw new SAXException("URI/Prefix mismatch [" + prefix + "," + uri + "]");
} else {
String temp=this.getPrefix(uri);
if (temp==null) throw new SAXException("URI not declared");
else if (temp.length() >0) {
prefix=temp;
raw=prefix+':"+local;
}
}
} else {
// We don't have a URI, check if we can find one from the prefix.
String temp=this.getUri(prefix);
if (temp==null) throw new SAXException("Prefix not declared");
else uri=temp;
}
NameImpl name=new NameImpl();
if (uri.length() > 0) name.uri=uri;
else name.uri=null;
name.raw=raw;
name.prefix=prefix;
name.local=local;
return(name);
}
Resolve a namespace-aware name against the current namespaces
declarations. |