You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tn...@apache.org on 2013/01/26 21:14:44 UTC
svn commit: r1438955 - in /commons/proper/collections/trunk: ./ src/changes/
src/main/java/org/apache/commons/collections/
src/main/java/org/apache/commons/collections/iterators/
src/test/java/org/apache/commons/collections/ src/test/java/org/apache/co...
Author: tn
Date: Sat Jan 26 20:14:43 2013
New Revision: 1438955
URL: http://svn.apache.org/viewvc?rev=1438955&view=rev
Log:
[COLLECTIONS-322] Added new NodeListIterator to iterate over a dom NodeList, thanks to Thomas Vahrst.
Added:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/iterators/NodeListIterator.java (with props)
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/iterators/NodeListIteratorTest.java (with props)
Modified:
commons/proper/collections/trunk/pom.xml
commons/proper/collections/trunk/src/changes/changes.xml
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/IteratorUtils.java
commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/IteratorUtilsTest.java
Modified: commons/proper/collections/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/pom.xml?rev=1438955&r1=1438954&r2=1438955&view=diff
==============================================================================
--- commons/proper/collections/trunk/pom.xml (original)
+++ commons/proper/collections/trunk/pom.xml Sat Jan 26 20:14:43 2013
@@ -382,6 +382,9 @@
<name>Kazuya Ujihara</name>
</contributor>
<contributor>
+ <name>Thomas Vahrst</name>
+ </contributor>
+ <contributor>
<name>Jeff Varszegi</name>
</contributor>
<contributor>
Modified: commons/proper/collections/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/changes/changes.xml?rev=1438955&r1=1438954&r2=1438955&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/changes/changes.xml (original)
+++ commons/proper/collections/trunk/src/changes/changes.xml Sat Jan 26 20:14:43 2013
@@ -22,6 +22,10 @@
<body>
<release version="4.0" date="TBA" description="Next release">
+ <action issue="COLLECTIONS-322" dev="tn" type="add" due-to="Thomas Vahrst">
+ Added NodeListIterator and convenience methods in IteratorUtils to iterate over
+ a org.w3c.dom.NodeList.
+ </action>
<action issue="COLLECTIONS-436" dev="tn" type="add" due-to="Arman Sharif">
Added "emptyIfNull" methods to classes "CollectionUtils", "ListUtils", "SetUtils"
and "MapUtils".
Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/IteratorUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/IteratorUtils.java?rev=1438955&r1=1438954&r2=1438955&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/IteratorUtils.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/IteratorUtils.java Sat Jan 26 20:14:43 2013
@@ -46,6 +46,7 @@ import org.apache.commons.collections.it
import org.apache.commons.collections.iterators.ListIteratorWrapper;
import org.apache.commons.collections.iterators.LoopingIterator;
import org.apache.commons.collections.iterators.LoopingListIterator;
+import org.apache.commons.collections.iterators.NodeListIterator;
import org.apache.commons.collections.iterators.ObjectArrayIterator;
import org.apache.commons.collections.iterators.ObjectArrayListIterator;
import org.apache.commons.collections.iterators.ObjectGraphIterator;
@@ -55,6 +56,8 @@ import org.apache.commons.collections.it
import org.apache.commons.collections.iterators.UnmodifiableIterator;
import org.apache.commons.collections.iterators.UnmodifiableListIterator;
import org.apache.commons.collections.iterators.UnmodifiableMapIterator;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
/**
* Provides static utility methods and decorators for {@link Iterator}
@@ -756,6 +759,45 @@ public class IteratorUtils {
return new LoopingListIterator<E>(list);
}
+ // org.w3c.dom.NodeList iterators
+ //-----------------------------------------------------------------------
+ /**
+ * Gets an {@link Iterator} that wraps the specified {@link NodeList}.
+ * The returned {@link Iterator} can be used for a single iteration.
+ *
+ * @param nodeList the node list to use, not null
+ * @return a new, single use {@link Iterator}
+ * @throws NullPointerException if nodeList is null
+ */
+ public static NodeListIterator nodeListIterator(final NodeList nodeList) {
+ if (nodeList == null) {
+ throw new NullPointerException("NodeList must not be null");
+ }
+ return new NodeListIterator(nodeList);
+ }
+
+ /**
+ * Gets an {@link Iterator} that wraps the specified node's childNodes.
+ * The returned {@link Iterator} can be used for a single iteration.
+ * <p>
+ * Convenience method, allows easy iteration over NodeLists:
+ * <pre>
+ * for(Node childNode : IteratorUtils.asIterable(node)){
+ * ...
+ * }
+ * </pre>
+ *
+ * @param node the node to use, not null
+ * @return a new, single use {@link Iterator}
+ * @throws NullPointerException if node is null
+ */
+ public static NodeListIterator nodeListIterator(final Node node) {
+ if (node == null) {
+ throw new NullPointerException("Node must not be null");
+ }
+ return new NodeListIterator(node);
+ }
+
// Views
//-----------------------------------------------------------------------
/**
@@ -823,6 +865,7 @@ public class IteratorUtils {
return new IteratorIterable<E>(iterator, false);
}
+
/**
* Gets an iterable that wraps an iterator. The returned iterable can be
* used for multiple iterations.
@@ -957,6 +1000,8 @@ public class IteratorUtils {
* <li>array - iterator over array returned
* <li>object with iterator() public method accessed by reflection
* <li>object - singleton iterator
+ * <li>NodeList - iterator over the list
+ * <li>Node - iterator over the child nodes
* </ul>
*
* @param obj the object to convert to an iterator
@@ -981,6 +1026,12 @@ public class IteratorUtils {
if (obj instanceof Map) {
return ((Map<?, ?>) obj).values().iterator();
}
+ if (obj instanceof NodeList) {
+ return new NodeListIterator((NodeList) obj);
+ }
+ if (obj instanceof Node) {
+ return new NodeListIterator((Node) obj);
+ }
if (obj instanceof Dictionary) {
return new EnumerationIterator<Object>(((Dictionary<?, ?>) obj).elements());
} else if (obj.getClass().isArray()) {
Added: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/iterators/NodeListIterator.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/iterators/NodeListIterator.java?rev=1438955&view=auto
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/iterators/NodeListIterator.java (added)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/iterators/NodeListIterator.java Sat Jan 26 20:14:43 2013
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2013 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.commons.collections.iterators;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * An {@link Iterator} over a {@link NodeList}.
+ * <p>
+ * This iterator does not support {@link #remove()} as a {@link NodeList} does not support
+ * removal of items.
+ *
+ * @since 4.0
+ * @version $Id$
+ * @see org.w3c.NodeList
+ */
+public class NodeListIterator implements Iterator<Node> {
+
+ /** the original NodeList instance */
+ private NodeList nodeList;
+ /** The current iterator index */
+ protected int index = 0;
+
+ /**
+ * Convenience constructor, which creates a new NodeListIterator from
+ * the specified node's childNodes.
+ *
+ * @param node Node, who's child nodes are wrapped by this class. Must not be null
+ * @throws IllegalArgumentException if node is null
+ */
+ public NodeListIterator(Node node) {
+ if (node == null) {
+ throw new IllegalArgumentException("node must not be null!");
+ }
+ this.nodeList = node.getChildNodes();
+ }
+
+ /**
+ * Constructor, that creates a new NodeListIterator from the specified
+ * <code>org.w3c.NodeList</code>
+ *
+ * @param nodeList node list, which is wrapped by this class. Must not be null
+ * @throws IllegalArgumentException if nodeList is null
+ */
+ public NodeListIterator(NodeList nodeList) {
+ if (nodeList == null) {
+ throw new IllegalArgumentException("nodeList must not be null!");
+ }
+ this.nodeList = nodeList;
+ }
+
+ public boolean hasNext() {
+ return nodeList == null ? false : index < nodeList.getLength();
+ }
+
+ public Node next() {
+ if (nodeList != null && index < nodeList.getLength()) {
+ return nodeList.item(index++);
+ } else {
+ throw new NoSuchElementException("underlying nodeList has no more elements");
+ }
+ }
+
+ /**
+ * Throws {@link UnsupportedOperationException}.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ public void remove() {
+ throw new UnsupportedOperationException("remove() method not supported for an NodeListIterator.");
+ }
+}
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/iterators/NodeListIterator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/iterators/NodeListIterator.java
------------------------------------------------------------------------------
svn:keywords = Id Revision HeadURL
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections/iterators/NodeListIterator.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/IteratorUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/IteratorUtilsTest.java?rev=1438955&r1=1438954&r2=1438955&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/IteratorUtilsTest.java (original)
+++ commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/IteratorUtilsTest.java Sat Jan 26 20:14:43 2013
@@ -30,13 +30,17 @@ import org.apache.commons.collections.it
import org.apache.commons.collections.iterators.EmptyMapIterator;
import org.apache.commons.collections.iterators.EmptyOrderedIterator;
import org.apache.commons.collections.iterators.EmptyOrderedMapIterator;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
/**
* Tests for IteratorUtils.
*
- * @version $Revision$
- *
- * @author Unknown
+ * @version $Id$
*/
public class IteratorUtilsTest extends BulkTest {
@@ -69,7 +73,7 @@ public class IteratorUtilsTest extends B
fail("should not be able to iterate twice");
}
}
-
+
public void testAsIterableNull() {
try {
IteratorUtils.asIterable(null);
@@ -787,4 +791,83 @@ public class IteratorUtilsTest extends B
}
}
+ /**
+ * Tests method nodeListIterator(NodeList)
+ */
+ public void testNodeListIterator() {
+ Node[] nodes = createNodes();
+ NodeList nodeList = createNodeList(nodes);
+
+ final Iterator<Node> iterator = IteratorUtils.nodeListIterator(nodeList);
+ int expectedNodeIndex = 0;
+ for (final Node actual : IteratorUtils.asIterable(iterator)) {
+ assertEquals(nodes[expectedNodeIndex], actual);
+ ++expectedNodeIndex;
+ }
+
+ // insure iteration occurred
+ assertTrue(expectedNodeIndex > 0);
+
+ // single use iterator
+ for (final Node actual : IteratorUtils.asIterable(iterator)) {
+ fail("should not be able to iterate twice");
+ }
+ }
+ /**
+ * Tests method nodeListIterator(Node)
+ */
+ public void testNodeIterator() {
+ Node[] nodes = createNodes();
+ NodeList nodeList = createNodeList(nodes);
+ Node parentNode = createMock(Node.class);
+ expect(parentNode.getChildNodes()).andStubReturn(nodeList);
+ replay(parentNode);
+
+ final Iterator<Node> iterator = IteratorUtils.nodeListIterator(parentNode);
+ int expectedNodeIndex = 0;
+ for (final Node actual : IteratorUtils.asIterable(iterator)) {
+ assertEquals(nodes[expectedNodeIndex], actual);
+ ++expectedNodeIndex;
+ }
+
+ // insure iteration occurred
+ assertTrue(expectedNodeIndex > 0);
+
+ // single use iterator
+ for (final Node actual : IteratorUtils.asIterable(iterator)) {
+ fail("should not be able to iterate twice");
+ }
+ }
+
+ /**
+ * creates an array of four Node instances, mocked by EasyMock.
+ * @return
+ */
+ private Node[] createNodes() {
+ Node node1 = createMock(Node.class);
+ Node node2 = createMock(Node.class);
+ Node node3 = createMock(Node.class);
+ Node node4 = createMock(Node.class);
+ replay(node1);
+ replay(node2);
+ replay(node3);
+ replay(node4);
+
+ return new Node[]{node1, node2, node3, node4};
+}
+
+ /**
+ * Creates a NodeList containing the specified nodes.
+ */
+ private NodeList createNodeList(final Node[] nodes) {
+ return new NodeList() {
+ public Node item(int index) {
+ return nodes[index];
+ }
+ public int getLength() {
+ return nodes.length;
+ }
+ };
+ }
+
}
Added: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/iterators/NodeListIteratorTest.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/iterators/NodeListIteratorTest.java?rev=1438955&view=auto
==============================================================================
--- commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/iterators/NodeListIteratorTest.java (added)
+++ commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/iterators/NodeListIteratorTest.java Sat Jan 26 20:14:43 2013
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2013 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.commons.collections.iterators;
+
+import java.util.Iterator;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+/**
+ * Tests the NodeListIterator.
+ */
+public class NodeListIteratorTest extends AbstractIteratorTest<Node> {
+
+ // Node array to be filled with mocked Node instances
+ private Node[] nodes;
+
+ // NodeListIterator supports two constructors. This flag allows to
+ // control, which constructor to use in makeObject() and makeEmtpyIterator
+ private boolean createIteratorWithStandardConstr = true;
+
+ /**
+ * Constructor
+ * @param testName
+ */
+ public NodeListIteratorTest(final String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Default: use standard constr.
+ createIteratorWithStandardConstr = true;
+
+
+ // create mocked Node Instances and fill Node[] to be used by test cases
+ Node node1 = createMock(Element.class);
+ Node node2 = createMock(Element.class);
+ Node node3 = createMock(Text.class);
+ Node node4 = createMock(Element.class);
+ nodes = new Node[] {node1, node2, node3, node4};
+
+ replay(node1);
+ replay(node2);
+ replay(node3);
+ replay(node4);
+ }
+
+ @Override
+ public Iterator<Node> makeEmptyIterator() {
+ NodeList emptyNodeList = new NodeList() {
+ public Node item(int index) {
+ throw new IndexOutOfBoundsException();
+ }
+ public int getLength() {
+ return 0;
+ }
+ };
+
+ if (createIteratorWithStandardConstr) {
+ return new NodeListIterator(emptyNodeList);
+ } else {
+ Node parentNode = createMock(Node.class);
+ expect(parentNode.getChildNodes()).andStubReturn(emptyNodeList);
+ replay(parentNode);
+
+ return new NodeListIterator(parentNode);
+ }
+ }
+
+ @Override
+ public Iterator<Node> makeObject() {
+ NodeList nodeList = new NodeList() {
+ public Node item(int index) {
+ return nodes[index];
+ }
+ public int getLength() {
+ return nodes.length;
+ }
+ };
+
+ return new NodeListIterator(nodeList);
+ }
+
+ @Override
+ public boolean supportsRemove() {
+ return false;
+ }
+
+ //-----------------------------------------------------------------------
+ public void testNullConstructor(){
+ try{
+ @SuppressWarnings("unused")
+ NodeListIterator iter = new NodeListIterator((Node) null);
+ fail("IllegalArgumentException expected!");
+ }catch(IllegalArgumentException e){
+ // expected.
+ }
+ }
+
+ /**
+ * tests the convenience Constructor with parameter type org.w3c.Node
+ */
+ public void testEmptyIteratorWithNodeConstructor(){
+ createIteratorWithStandardConstr = false;
+ testEmptyIterator();
+ }
+
+ /**
+ * tests the convenience Constructor with parameter type org.w3c.Node
+ */
+ public void testFullIteratorWithNodeConstructor(){
+ createIteratorWithStandardConstr = false;
+ testFullIterator();
+ }
+}
Propchange: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/iterators/NodeListIteratorTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/iterators/NodeListIteratorTest.java
------------------------------------------------------------------------------
svn:keywords = Id Revision HeadURL
Propchange: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections/iterators/NodeListIteratorTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain