You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2005/08/16 11:22:51 UTC
svn commit: r232969 - in /cocoon/branches/BRANCH_2_1_X/src:
java/org/apache/cocoon/xml/NamespacesTable.java
test/org/apache/cocoon/xml/NamespacesTableTestCase.java
Author: sylvain
Date: Tue Aug 16 02:22:46 2005
New Revision: 232969
URL: http://svn.apache.org/viewcvs?rev=232969&view=rev
Log:
Declared prefix mappings can be known after leaveScope()
Modified:
cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/xml/NamespacesTable.java
cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/xml/NamespacesTableTestCase.java
Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/xml/NamespacesTable.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/xml/NamespacesTable.java?rev=232969&r1=232968&r2=232969&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/xml/NamespacesTable.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/xml/NamespacesTable.java Tue Aug 16 02:22:46 2005
@@ -49,7 +49,7 @@
* }
*
* public void endPrefixMapping(String prefix) throws SAXException {
- * namespaces.removeDeclaration(prefix);
+ * // Ignore, it is handled by leaveScope()
* }
* </pre>
*
@@ -58,6 +58,11 @@
public class NamespacesTable {
/** The last namespace declaration. */
private Entry lastEntry;
+
+ /** The entry that start the prefix mappings for the scope that's about to be entered
+ * or was just left.
+ */
+ private Entry lastDeclaredEntry;
private boolean usesScopes = false;
@@ -74,7 +79,7 @@
* @since 2.1.8
*/
public void clear() {
- this.lastEntry=Entry.create("","");
+ this.lastEntry = Entry.create("","");
this.addDeclaration("xml", "http://www.w3.org/XML/1998/namespace");
// Lock this scope
this.lastEntry.closedScopes = 1;
@@ -103,16 +108,19 @@
e.previous = this.lastEntry;
e.overrides = dup;
this.lastEntry = e;
+ // this always starts the declared prefix chain
+ this.lastDeclaredEntry = e;
return e;
}
/**
- * Undeclare a namespace prefix-uri mapping.
- * <br>
- * If the prefix was previously declared mapping another URI, its value
- * is restored.
+ * Undeclare a namespace prefix-uri mapping. If the prefix was previously declared
+ * mapping another URI, its value is restored.
+ * <p>
+ * When using {@link #enterScope()}/{@link #leaveScope()}, this method does nothing and always
+ * returns <code>null</code>, as declaration removal is handled in {@link #leaveScope()}.
*
- * @return The removed <code>Declaration</code> or <b>null</b>.
+ * @return the removed <code>Declaration</code> or <b>null</b>.
*/
public Declaration removeDeclaration(String prefix) {
if (usesScopes) {
@@ -142,6 +150,14 @@
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;
}
@@ -158,18 +174,23 @@
}
/**
- * Enter a new scope, with no declared mappings.
+ * Enter a new scope. This starts a new, empty list of declarations for the new scope.
+ * <p>
+ * Typically called in a SAX handler <em>before</em> sending a <code>startElement()</code>
+ * event.
*
- * @see #getCurrentScopeDeclarations()
* @since 2.1.8
*/
public void enterScope() {
this.usesScopes = true;
this.lastEntry.closedScopes++;
+ this.lastDeclaredEntry = null;
}
/**
- * Start all declared mappings of the current scope and enter a new scope.
+ * Start all declared mappings of the current scope and enter a new scope. This starts a new,
+ * empty list of declarations for the new scope.
+ * <p>
* Typically called in a SAX handler <em>before</em> sending a <code>startElement()</code>
* event.
*
@@ -185,37 +206,54 @@
current = current.previous;
}
this.lastEntry.closedScopes++;
+ this.lastDeclaredEntry = null;
}
/**
- * Leave a scope. If <code>autoRemove</code> is true, all declared mappings for the
- * scope that is left are automatically removed, without having to explicitely call
- * {@link #removeDeclaration(String)}.
+ * Leave a scope. The namespace declarations that occured before the corresponding
+ * <code>enterScope()</code> are no more visible using the resolution methods, but
+ * still available using {@link #getCurrentScopeDeclarations()} until the next call
+ * to {@link #addDeclaration(String, String)} or {@link #enterScope()}.
+ * <p>
+ * Typically called in a SAX handler <em>after</em> sending a <code>endElement()</code>
+ * event.
*
- * @param autoUndeclare if <code>true</code>, remove all mappings for the current scope.
* @since 2.1.8
*/
public void leaveScope() {
Entry current = this.lastEntry;
- if (current.closedScopes <= 0) {
- throw new IllegalStateException("Misbalanced enter and leaving of scope.");
+
+ // Purge declarations that were added but not included in a scope
+ while (current.closedScopes == 0) {
+ current = current.previous;
}
+
current.closedScopes--;
- if (usesScopes) {
- while (current != null && current.closedScopes == 0) {
- Entry overrides = current.overrides;
- if (overrides != null) {
- // No more overriden
- overrides.overriden = false;
- }
- current = current.previous;
+
+ 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;
}
/**
- * Leave a scope and end all declared mappings of the new scope.
+ * Leave a scope. The namespace declarations that occured before the corresponding
+ * <code>enterScope()</code> are no more visible using the resolution methods, but
+ * still available using {@link #getCurrentScopeDeclarations()} until the next call
+ * to {@link #addDeclaration(String, String)} or {@link #enterScope()}.
+ * <p>
* Typically called in a SAX handler <em>after</em> sending a <code>endElement()</code>
* event.
*
@@ -225,10 +263,21 @@
*/
public void leaveScope(ContentHandler handler) throws SAXException {
Entry current = this.lastEntry;
- if (current.closedScopes <= 0) {
- throw new IllegalStateException("Misbalanced enter and leaving of scope.");
+
+ // 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;
@@ -247,12 +296,12 @@
/**
* Get the declarations that were declared within the current scope.
*
- * @return the declarations (never null)
+ * @return the declarations (possibly empty, but never null)
* @since 2.1.8
*/
public Declaration[] getCurrentScopeDeclarations() {
int count = 0;
- Entry current = this.lastEntry;
+ Entry current = this.lastDeclaredEntry;
while (current != null && current.closedScopes == 0) {
count++;
current = current.previous;
@@ -262,7 +311,7 @@
Declaration[] decls = new Declaration[count];
count = 0;
- current = this.lastEntry;
+ current = this.lastDeclaredEntry;
while (current != null && current.closedScopes == 0) {
decls[count++] = current;
current = current.previous;
Modified: cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/xml/NamespacesTableTestCase.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/xml/NamespacesTableTestCase.java?rev=232969&r1=232968&r2=232969&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/xml/NamespacesTableTestCase.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/xml/NamespacesTableTestCase.java Tue Aug 16 02:22:46 2005
@@ -1,3 +1,18 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package org.apache.cocoon.xml;
import junit.framework.TestCase;
@@ -5,6 +20,11 @@
import org.xml.sax.ContentHandler;
import org.xml.sax.helpers.DefaultHandler;
+/**
+ * Test case for NamespacesTable
+ *
+ * @version $Id$
+ */
public class NamespacesTableTestCase extends TestCase {
public NamespacesTableTestCase(String name) {
super(name);
@@ -18,40 +38,50 @@
ns.enterScope();
- assertEquals("http://ns1", ns.getUri("ns1"));
- assertEquals("ns1", ns.getPrefix("http://ns1"));
+ assertEquals("http://ns1", ns.getUri("ns1"));
+ assertEquals("ns1", ns.getPrefix("http://ns1"));
- assertEquals("http://ns2", ns.getUri("ns2"));
- assertEquals("ns2", ns.getPrefix("http://ns2"));
+ assertEquals("http://ns2", ns.getUri("ns2"));
+ assertEquals("ns2", ns.getPrefix("http://ns2"));
- assertNull(ns.getPrefix(ns.getPrefix("http://ns3")));
- assertNull(ns.getUri("ns3"));
+ ns.enterScope();
- ns.leaveScope();
- // Declarations that occured before this scope are no more visible
- assertNull(ns.removeDeclaration("ns1"));
- assertNull(ns.removeDeclaration("ns2"));
- assertNull(ns.removeDeclaration("ns3"));
- }
-
- public void testWrongUndeclare() {
- NamespacesTable ns = new NamespacesTable();
+ ns.addDeclaration("ns3", "http://ns3");
+ ns.enterScope();
- ns.enterScope();
- ns.addDeclaration("ns1", "http://ns1");
- ns.addDeclaration("ns2", "http://ns2");
+ assertEquals("ns1", ns.getPrefix("http://ns1"));
+ assertEquals("ns3", ns.getPrefix("http://ns3"));
+ assertEquals(0, ns.getCurrentScopeDeclarations().length);
+ ns.leaveScope();
+
+ // Declarations in this scope are no more visible...
+ assertNull(ns.getUri("ns3"));
+ // ... but still listed in the declared mappings
+ assertEquals(1, ns.getCurrentScopeDeclarations().length);
+ assertEquals("ns3", ns.getCurrentScopeDeclarations()[0].getPrefix());
- ns.enterScope(); // increments closedScopes on ns2
+ ns.leaveScope();
- ns.addDeclaration("ns3", "http://ns3");
+ assertNull(ns.getPrefix(ns.getPrefix("http://ns3")));
+ assertNull(ns.getUri("ns3"));
- try {
- ns.leaveScope();
- } catch(IllegalStateException e) {
- return;
- }
+ ns.leaveScope();
+ // Declarations that occured before this scope are no more visible...
+ assertNull(ns.getUri("ns1"));
+ assertNull(ns.getPrefix("http://ns1"));
+
+ assertNull(ns.getUri("ns2"));
+ assertNull(ns.getPrefix("http://ns2"));
+
+ //... but are still available in getDeclaredPrefixes
+ NamespacesTable.Declaration[] prefixes = ns.getCurrentScopeDeclarations();
+ assertEquals(2, prefixes.length);
+
+ assertEquals("ns2", prefixes[0].getPrefix());
+ assertEquals("http://ns2", prefixes[0].getUri());
+ assertEquals("ns1", prefixes[1].getPrefix());
+ assertEquals("http://ns1", prefixes[1].getUri());
- fail();
}
public void testOverride() {
@@ -128,20 +158,21 @@
ns.addDeclaration("ft", "http://apache.org/cocoon/forms/1.0#template");
ns.addDeclaration("fi", "http://apache.org/cocoon/forms/1.0#instance");
ns.addDeclaration("jx", "http://apache.org/cocoon/templates/jx/1.0");
-// ns.enterScope(handler);
+ ns.enterScope(handler);
+ assertEquals("ft", ns.getPrefix("http://apache.org/cocoon/forms/1.0#template"));
+ assertEquals("fi", ns.getPrefix("http://apache.org/cocoon/forms/1.0#instance"));
+ assertEquals("jx", ns.getPrefix("http://apache.org/cocoon/templates/jx/1.0"));
+
+ // Add declarations that won't be used
ns.addDeclaration("jx", "http://apache.org/cocoon/templates/jx/1.0");
ns.addDeclaration("fi", "http://apache.org/cocoon/forms/1.0#instance");
ns.addDeclaration("bu", "http://apache.org/cocoon/browser-update/1.0");
- ns.removeDeclaration("jx");
- ns.removeDeclaration("fi");
- ns.removeDeclaration("bu");
-// ns.leaveScope(handler);
- assertEquals("ft", ns.getPrefix("http://apache.org/cocoon/forms/1.0#template"));
- assertEquals("fi", ns.getPrefix("http://apache.org/cocoon/forms/1.0#instance"));
- assertEquals("jx", ns.getPrefix("http://apache.org/cocoon/templates/jx/1.0"));
- ns.removeDeclaration("ft");
- ns.removeDeclaration("fi");
- ns.removeDeclaration("jx");
+
+ ns.leaveScope(handler);
+ assertNull(ns.getPrefix("http://apache.org/cocoon/forms/1.0#template"));
+ assertNull(ns.getPrefix("http://apache.org/cocoon/forms/1.0#instance"));
+ assertNull(ns.getPrefix("http://apache.org/cocoon/templates/jx/1.0"));
+ assertEquals(3, ns.getCurrentScopeDeclarations().length);
}