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: */
017: package org.apache.commons.configuration.tree.xpath;
018:
019: import java.util.List;
020:
021: import org.apache.commons.configuration.tree.ConfigurationNode;
022: import org.apache.commons.jxpath.ri.model.NodeIterator;
023: import org.apache.commons.jxpath.ri.model.NodePointer;
024:
025: /**
026: * <p>
027: * A base class for implementing iterators over configuration nodes.
028: * </p>
029: * <p>
030: * This class already provides common functionality for implementing the
031: * iteration process. Derived classes will implement specific behavior based on
032: * the concrete node type (child node or attribute node).
033: * </p>
034: *
035: * @since 1.3
036: * @author Oliver Heger
037: * @version $Id: ConfigurationNodeIteratorBase.java 439648 2006-09-02 20:42:10Z oheger $
038: */
039: abstract class ConfigurationNodeIteratorBase implements NodeIterator {
040: /** Stores the parent node pointer. */
041: private NodePointer parent;
042:
043: /** Stores the list with the sub nodes. */
044: private List subNodes;
045:
046: /** Stores the current position. */
047: private int position;
048:
049: /** Stores the start offset of the iterator. */
050: private int startOffset;
051:
052: /** Stores the reverse flag. */
053: private boolean reverse;
054:
055: /**
056: * Creates a new instance of <code>ConfigurationNodeIteratorBase</code>
057: * and initializes it.
058: *
059: * @param parent the parent pointer
060: * @param reverse the reverse flag
061: */
062: protected ConfigurationNodeIteratorBase(NodePointer parent,
063: boolean reverse) {
064: this .parent = parent;
065: this .reverse = reverse;
066: }
067:
068: /**
069: * Returns the position of the iteration.
070: *
071: * @return the position
072: */
073: public int getPosition() {
074: return position;
075: }
076:
077: /**
078: * Sets the position of the iteration.
079: *
080: * @param pos the new position
081: * @return a flag if this is a valid position
082: */
083: public boolean setPosition(int pos) {
084: position = pos;
085: return pos >= 1 && pos <= getMaxPosition();
086: }
087:
088: /**
089: * Returns the current node pointer.
090: *
091: * @return the current pointer in this iteration
092: */
093: public NodePointer getNodePointer() {
094: if (getPosition() < 1 && !setPosition(1)) {
095: return null;
096: }
097:
098: return createNodePointer((ConfigurationNode) subNodes
099: .get(positionToIndex(getPosition())));
100: }
101:
102: /**
103: * Returns the parent node pointer.
104: *
105: * @return the parent node pointer
106: */
107: protected NodePointer getParent() {
108: return parent;
109: }
110:
111: /**
112: * Returns the start offset of the iteration.
113: *
114: * @return the start offset
115: */
116: protected int getStartOffset() {
117: return startOffset;
118: }
119:
120: /**
121: * Sets the start offset of the iteration. This is used when a start element
122: * was set.
123: *
124: * @param startOffset the start offset
125: */
126: protected void setStartOffset(int startOffset) {
127: this .startOffset = startOffset;
128: if (reverse) {
129: this .startOffset--;
130: } else {
131: this .startOffset++;
132: }
133: }
134:
135: /**
136: * Initializes the list of sub nodes for the iteration. This method must be
137: * called during initialization phase.
138: *
139: * @param nodes the list with the sub nodes
140: */
141: protected void initSubNodeList(List nodes) {
142: subNodes = nodes;
143: if (reverse) {
144: setStartOffset(subNodes.size());
145: }
146: }
147:
148: /**
149: * Returns the maximum position for this iterator.
150: *
151: * @return the maximum allowed position
152: */
153: protected int getMaxPosition() {
154: return reverse ? getStartOffset() + 1 : subNodes.size()
155: - getStartOffset();
156: }
157:
158: /**
159: * Creates the configuration node pointer for the current position. This
160: * method is called by <code>getNodePointer()</code>. Derived classes
161: * must create the correct pointer object.
162: *
163: * @param node the current configuration node
164: * @return the node pointer
165: */
166: protected NodePointer createNodePointer(ConfigurationNode node) {
167: return new ConfigurationNodePointer(getParent(), node);
168: }
169:
170: /**
171: * Returns the index in the data list for the given position. This method
172: * also checks the reverse flag.
173: *
174: * @param pos the position (1-based)
175: * @return the corresponding list index
176: */
177: protected int positionToIndex(int pos) {
178: return (reverse ? 1 - pos : pos - 1) + getStartOffset();
179: }
180: }
|