1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.configuration.tree.xpath; 18 19 import java.util.List; 20 21 import org.apache.commons.configuration.tree.ConfigurationNode; 22 import org.apache.commons.jxpath.ri.model.NodeIterator; 23 import org.apache.commons.jxpath.ri.model.NodePointer; 24 25 /** 26 * <p> 27 * A base class for implementing iterators over configuration nodes. 28 * </p> 29 * <p> 30 * This class already provides common functionality for implementing the 31 * iteration process. Derived classes will implement specific behavior based on 32 * the concrete node type (child node or attribute node). 33 * </p> 34 * 35 * @since 1.3 36 * @author <a 37 * href="http://commons.apache.org/configuration/team-list.html">Commons 38 * Configuration team</a> 39 * @version $Id: ConfigurationNodeIteratorBase.java 1206491 2011-11-26 16:51:50Z oheger $ 40 */ 41 abstract class ConfigurationNodeIteratorBase implements NodeIterator 42 { 43 /** Stores the parent node pointer. */ 44 private NodePointer parent; 45 46 /** Stores the list with the sub nodes. */ 47 private List<ConfigurationNode> subNodes; 48 49 /** Stores the current position. */ 50 private int position; 51 52 /** Stores the start offset of the iterator. */ 53 private int startOffset; 54 55 /** Stores the reverse flag. */ 56 private boolean reverse; 57 58 /** 59 * Creates a new instance of {@code ConfigurationNodeIteratorBase} 60 * and initializes it. 61 * 62 * @param parent the parent pointer 63 * @param reverse the reverse flag 64 */ 65 protected ConfigurationNodeIteratorBase(NodePointer parent, boolean reverse) 66 { 67 this.parent = parent; 68 this.reverse = reverse; 69 } 70 71 /** 72 * Returns the position of the iteration. 73 * 74 * @return the position 75 */ 76 public int getPosition() 77 { 78 return position; 79 } 80 81 /** 82 * Sets the position of the iteration. 83 * 84 * @param pos the new position 85 * @return a flag if this is a valid position 86 */ 87 public boolean setPosition(int pos) 88 { 89 position = pos; 90 return pos >= 1 && pos <= getMaxPosition(); 91 } 92 93 /** 94 * Returns the current node pointer. 95 * 96 * @return the current pointer in this iteration 97 */ 98 public NodePointer getNodePointer() 99 { 100 if (getPosition() < 1 && !setPosition(1)) 101 { 102 return null; 103 } 104 105 return createNodePointer(subNodes.get(positionToIndex(getPosition()))); 106 } 107 108 /** 109 * Returns the parent node pointer. 110 * 111 * @return the parent node pointer 112 */ 113 protected NodePointer getParent() 114 { 115 return parent; 116 } 117 118 /** 119 * Returns the start offset of the iteration. 120 * 121 * @return the start offset 122 */ 123 protected int getStartOffset() 124 { 125 return startOffset; 126 } 127 128 /** 129 * Sets the start offset of the iteration. This is used when a start element 130 * was set. 131 * 132 * @param startOffset the start offset 133 */ 134 protected void setStartOffset(int startOffset) 135 { 136 this.startOffset = startOffset; 137 if (reverse) 138 { 139 this.startOffset--; 140 } 141 else 142 { 143 this.startOffset++; 144 } 145 } 146 147 /** 148 * Initializes the list of sub nodes for the iteration. This method must be 149 * called during initialization phase. 150 * 151 * @param nodes the list with the sub nodes 152 */ 153 protected void initSubNodeList(List<ConfigurationNode> nodes) 154 { 155 subNodes = nodes; 156 if (reverse) 157 { 158 setStartOffset(subNodes.size()); 159 } 160 } 161 162 /** 163 * Returns the maximum position for this iterator. 164 * 165 * @return the maximum allowed position 166 */ 167 protected int getMaxPosition() 168 { 169 return reverse ? getStartOffset() + 1 : subNodes.size() 170 - getStartOffset(); 171 } 172 173 /** 174 * Creates the configuration node pointer for the current position. This 175 * method is called by {@code getNodePointer()}. Derived classes 176 * must create the correct pointer object. 177 * 178 * @param node the current configuration node 179 * @return the node pointer 180 */ 181 protected NodePointer createNodePointer(ConfigurationNode node) 182 { 183 return new ConfigurationNodePointer(getParent(), node); 184 } 185 186 /** 187 * Returns the index in the data list for the given position. This method 188 * also checks the reverse flag. 189 * 190 * @param pos the position (1-based) 191 * @return the corresponding list index 192 */ 193 protected int positionToIndex(int pos) 194 { 195 return (reverse ? 1 - pos : pos - 1) + getStartOffset(); 196 } 197 }