001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.jxpath.ri.model.dom; 018 019import org.apache.commons.jxpath.ri.compiler.NodeTest; 020import org.apache.commons.jxpath.ri.model.NodeIterator; 021import org.apache.commons.jxpath.ri.model.NodePointer; 022import org.w3c.dom.Node; 023 024/** 025 * An iterator of children of a DOM Node. 026 * 027 * @author Dmitri Plotnikov 028 * @version $Revision: 652845 $ $Date: 2008-05-02 19:46:46 +0200 (Fr, 02 Mai 2008) $ 029 */ 030public class DOMNodeIterator implements NodeIterator { 031 private NodePointer parent; 032 private NodeTest nodeTest; 033 private Node node; 034 private Node child = null; 035 private boolean reverse; 036 private int position = 0; 037 038 /** 039 * Create a new DOMNodeIterator. 040 * @param parent parent pointer 041 * @param nodeTest test 042 * @param reverse whether to iterate in reverse 043 * @param startWith starting pointer 044 */ 045 public DOMNodeIterator( 046 NodePointer parent, 047 NodeTest nodeTest, 048 boolean reverse, 049 NodePointer startWith) { 050 this.parent = parent; 051 this.node = (Node) parent.getNode(); 052 if (startWith != null) { 053 this.child = (Node) startWith.getNode(); 054 } 055 this.nodeTest = nodeTest; 056 this.reverse = reverse; 057 } 058 059 public NodePointer getNodePointer() { 060 if (position == 0) { 061 setPosition(1); 062 } 063 return child == null ? null : new DOMNodePointer(parent, child); 064 } 065 066 public int getPosition() { 067 return position; 068 } 069 070 public boolean setPosition(int position) { 071 while (this.position < position) { 072 if (!next()) { 073 return false; 074 } 075 } 076 while (this.position > position) { 077 if (!previous()) { 078 return false; 079 } 080 } 081 return true; 082 } 083 084 /** 085 * Set the previous position. 086 * @return whether valid 087 */ 088 private boolean previous() { 089 position--; 090 if (!reverse) { 091 if (position == 0) { 092 child = null; 093 } 094 else if (child == null) { 095 child = node.getLastChild(); 096 } 097 else { 098 child = child.getPreviousSibling(); 099 } 100 while (child != null && !testChild()) { 101 child = child.getPreviousSibling(); 102 } 103 } 104 else { 105 child = child.getNextSibling(); 106 while (child != null && !testChild()) { 107 child = child.getNextSibling(); 108 } 109 } 110 return child != null; 111 } 112 113 /** 114 * Set the next position. 115 * @return whether valid 116 */ 117 private boolean next() { 118 position++; 119 if (!reverse) { 120 if (position == 1) { 121 if (child == null) { 122 child = node.getFirstChild(); 123 } 124 else { 125 child = child.getNextSibling(); 126 } 127 } 128 else { 129 child = child.getNextSibling(); 130 } 131 while (child != null && !testChild()) { 132 child = child.getNextSibling(); 133 } 134 } 135 else { 136 if (position == 1) { 137 if (child == null) { 138 child = node.getLastChild(); 139 } 140 else { 141 child = child.getPreviousSibling(); 142 } 143 } 144 else { 145 child = child.getPreviousSibling(); 146 } 147 while (child != null && !testChild()) { 148 child = child.getPreviousSibling(); 149 } 150 } 151 return child != null; 152 } 153 154 /** 155 * Test child. 156 * @return result of the test 157 */ 158 private boolean testChild() { 159 return DOMNodePointer.testNode(child, nodeTest); 160 } 161}