[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. |