[Practicalxml-commits] SF.net SVN: practicalxml:[125] trunk
Brought to you by:
kdgregory
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-10 13:39:29
|
Revision: 125
http://practicalxml.svn.sourceforge.net/practicalxml/?rev=125&view=rev
Author: kdgregory
Date: 2009-09-10 13:39:16 +0000 (Thu, 10 Sep 2009)
Log Message:
-----------
add NodeListIterator
Modified Paths:
--------------
trunk/pom.xml
trunk/src/main/java/net/sf/practicalxml/util/NodeListIterable.java
Added Paths:
-----------
trunk/src/main/java/net/sf/practicalxml/util/NodeListIterator.java
trunk/src/test/java/net/sf/practicalxml/util/TestNodeListIterator.java
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2009-09-08 16:06:13 UTC (rev 124)
+++ trunk/pom.xml 2009-09-10 13:39:16 UTC (rev 125)
@@ -5,7 +5,7 @@
<groupId>net.sf.practicalxml</groupId>
<artifactId>practicalxml</artifactId>
<packaging>jar</packaging>
- <version>1.0.3</version>
+ <version>1.0.4</version>
<name>practicalxml</name>
<url>http://sourceforge.net/projects/practicalxml/</url>
Modified: trunk/src/main/java/net/sf/practicalxml/util/NodeListIterable.java
===================================================================
--- trunk/src/main/java/net/sf/practicalxml/util/NodeListIterable.java 2009-09-08 16:06:13 UTC (rev 124)
+++ trunk/src/main/java/net/sf/practicalxml/util/NodeListIterable.java 2009-09-10 13:39:16 UTC (rev 125)
@@ -15,15 +15,15 @@
package net.sf.practicalxml.util;
import java.util.Iterator;
-import java.util.NoSuchElementException;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
- * A wrapper for a DOM <code>NodeList</code> that allows it to be used in
- * a JDK 1.5 for-each loop.
+ * A wrapper for a DOM <code>NodeList</code> that allows it to be used in a
+ * JDK 1.5 for-each loop. See {@link net.sf.practicalxml.util.NodeListIterator}
+ * if you want full iterator operation.
*/
public class NodeListIterable
implements Iterable<Node>
@@ -37,30 +37,6 @@
public Iterator<Node> iterator()
{
- return new MyIterator();
+ return new NodeListIterator(_list);
}
-
-
- private class MyIterator
- implements Iterator<Node>
- {
- int _position = 0;
-
- public boolean hasNext()
- {
- return _position < _list.getLength();
- }
-
- public Node next()
- {
- if (!hasNext())
- throw new NoSuchElementException();
- return _list.item(_position++);
- }
-
- public void remove()
- {
- throw new UnsupportedOperationException("unable to remove from NodeList");
- }
- }
}
Added: trunk/src/main/java/net/sf/practicalxml/util/NodeListIterator.java
===================================================================
--- trunk/src/main/java/net/sf/practicalxml/util/NodeListIterator.java (rev 0)
+++ trunk/src/main/java/net/sf/practicalxml/util/NodeListIterator.java 2009-09-10 13:39:16 UTC (rev 125)
@@ -0,0 +1,79 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// 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 net.sf.practicalxml.util;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+/**
+ * A wrapper for {@link org.w3c.dom.NodeList} that provides full iterator
+ * behavior. See {@link net.sf.practicalxml.util.NodeListIterable} if all
+ * you want to do is use the NodeList in a JDK 1.5 <code>for</code> loop.
+ * <p>
+ * Because a <code>NodeList</code> is a view on a DOM tree, this iterator has
+ * slightly different semantics than a typical <code>java.util</code> iterator.
+ * First, it is not "fail fast": the DOM consists of independent nodes, and we
+ * have no way to track when changes to the DOM may have made the nodelist
+ * invalid.
+ * <p>
+ * Second, and more important, removal via the iterator changes the DOM, not
+ * just the underlying list.
+ */
+public class NodeListIterator
+implements Iterator<Node>
+{
+ private NodeList _list;
+ private int _pos;
+ private Node _current;
+
+
+ public NodeListIterator(NodeList nodelist)
+ {
+ _list = nodelist;
+ }
+
+
+ public boolean hasNext()
+ {
+ return _pos < _list.getLength();
+ }
+
+
+ public Node next()
+ {
+ if (hasNext())
+ {
+ _current = _list.item(_pos++);
+ return _current;
+ }
+ throw new NoSuchElementException("invalid index: " + _pos);
+ }
+
+
+ public void remove()
+ {
+ if (_current == null)
+ throw new IllegalStateException("no current node");
+
+ Node _parent = _current.getParentNode();
+ _parent.removeChild(_current);
+ _pos--;
+ _current = null;
+ }
+}
Added: trunk/src/test/java/net/sf/practicalxml/util/TestNodeListIterator.java
===================================================================
--- trunk/src/test/java/net/sf/practicalxml/util/TestNodeListIterator.java (rev 0)
+++ trunk/src/test/java/net/sf/practicalxml/util/TestNodeListIterator.java 2009-09-10 13:39:16 UTC (rev 125)
@@ -0,0 +1,179 @@
+// Copyright 2008-2009 severally by the contributors
+//
+// 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 net.sf.practicalxml.util;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import junit.framework.TestCase;
+
+import static net.sf.practicalxml.builder.XmlBuilder.*;
+
+
+public class TestNodeListIterator
+extends TestCase
+{
+ public final static String EL_CHILD1 = "child1";
+ public final static String EL_CHILD2 = "child2";
+ public final static String TXT1 = "some text";
+
+ private Element _testData
+ = element("root",
+ element(EL_CHILD1),
+ text(TXT1),
+ element(EL_CHILD2))
+ .toDOM().getDocumentElement();
+
+//----------------------------------------------------------------------------
+// Test Cases
+//----------------------------------------------------------------------------
+
+ public void testBasicIteration() throws Exception
+ {
+ Iterator<Node> itx = new NodeListIterator(_testData.getChildNodes());
+
+ assertTrue(itx.hasNext());
+ Node node1 = itx.next();
+ assertTrue(node1 instanceof Element);
+ assertEquals(EL_CHILD1, node1.getNodeName());
+
+ assertTrue(itx.hasNext());
+ Node node2 = itx.next();
+ assertTrue(node2 instanceof Text);
+ assertEquals(TXT1, node2.getNodeValue());
+
+ assertTrue(itx.hasNext());
+ Node node3 = itx.next();
+ assertTrue(node3 instanceof Element);
+ assertEquals(EL_CHILD2, node3.getNodeName());
+
+ assertFalse(itx.hasNext());
+ }
+
+
+ public void testIterationOffTheEnd() throws Exception
+ {
+ Iterator<Node> itx = new NodeListIterator(_testData.getChildNodes());
+ while (itx.hasNext())
+ itx.next();
+
+ try
+ {
+ itx.next();
+ fail("able to iterate off end of list");
+ }
+ catch (NoSuchElementException ee)
+ {
+ // success
+ }
+ }
+
+
+ public void testRemove() throws Exception
+ {
+ Iterator<Node> itx = new NodeListIterator(_testData.getChildNodes());
+
+ itx.next();
+ itx.next();
+ itx.remove();
+
+ assertTrue(itx.hasNext());
+ Node node = itx.next();
+ assertTrue(node instanceof Element);
+ assertEquals(EL_CHILD2, node.getNodeName());
+
+ assertFalse(itx.hasNext());
+
+ // verify that DOM was changed
+
+ NodeList list = _testData.getChildNodes();
+ assertEquals(2, list.getLength());
+
+ Node node1 = list.item(0);
+ assertTrue(node1 instanceof Element);
+ assertEquals(EL_CHILD1, node1.getNodeName());
+
+ Node node2 = list.item(1);
+ assertTrue(node2 instanceof Element);
+ assertEquals(EL_CHILD2, node2.getNodeName());
+ }
+
+
+ public void testRemoveAtEndOfIteration() throws Exception
+ {
+ Iterator<Node> itx = new NodeListIterator(_testData.getChildNodes());
+
+ itx.next();
+ itx.next();
+ itx.next();
+ assertFalse(itx.hasNext());
+
+ itx.remove();
+
+ // verify that DOM was changed
+
+ NodeList list = _testData.getChildNodes();
+ assertEquals(2, list.getLength());
+
+ Node node1 = list.item(0);
+ assertTrue(node1 instanceof Element);
+ assertEquals(EL_CHILD1, node1.getNodeName());
+
+ Node node2 = list.item(1);
+ assertTrue(node2 instanceof Text);
+ assertEquals(TXT1, node2.getNodeValue());
+ }
+
+
+ public void testRemoveFailsIfNextNotCalled() throws Exception
+ {
+ Iterator<Node> itx = new NodeListIterator(_testData.getChildNodes());
+
+ try
+ {
+ itx.remove();
+ fail("remove() succeeded without initial next()");
+ }
+ catch (IllegalStateException ee)
+ {
+ // success
+ }
+ }
+
+
+ public void testRemoveFailsIfCalledTwice() throws Exception
+ {
+ Iterator<Node> itx = new NodeListIterator(_testData.getChildNodes());
+
+ itx.next();
+ itx.next();
+ itx.remove();
+
+ try
+ {
+ itx.remove();
+ fail("remove() succeeded without intervening next()");
+ }
+ catch (IllegalStateException ee)
+ {
+ // success
+ }
+ }
+}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|