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.ArrayList;
020: import java.util.Collections;
021: import java.util.Iterator;
022: import java.util.List;
023:
024: import org.apache.commons.configuration.tree.ConfigurationNode;
025: import org.apache.commons.jxpath.ri.Compiler;
026: import org.apache.commons.jxpath.ri.QName;
027: import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
028: import org.apache.commons.jxpath.ri.compiler.NodeTest;
029: import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
030: import org.apache.commons.jxpath.ri.model.NodePointer;
031: import org.apache.commons.lang.StringUtils;
032:
033: /**
034: * A specialized iterator implementation for the child nodes of a configuration
035: * node.
036: *
037: * @since 1.3
038: * @author Oliver Heger
039: * @version $Id: ConfigurationNodeIteratorChildren.java 439648 2006-09-02 20:42:10Z oheger $
040: */
041: class ConfigurationNodeIteratorChildren extends
042: ConfigurationNodeIteratorBase {
043: /**
044: * Creates a new instance of <code>ConfigurationNodeIteratorChildren</code>
045: * and initializes it.
046: *
047: * @param parent the parent pointer
048: * @param nodeTest the test selecting the sub nodes
049: * @param reverse the reverse flag
050: * @param startsWith the first element of the iteration
051: */
052: public ConfigurationNodeIteratorChildren(NodePointer parent,
053: NodeTest nodeTest, boolean reverse, NodePointer startsWith) {
054: super (parent, reverse);
055: ConfigurationNode root = (ConfigurationNode) parent.getNode();
056: List childNodes = createSubNodeList(root, nodeTest);
057: initSubNodeList(childNodes);
058: if (startsWith != null) {
059: setStartOffset(findStartIndex(root,
060: (ConfigurationNode) startsWith.getNode()));
061: }
062: }
063:
064: /**
065: * Creates the list with sub nodes. This method gets called during
066: * initialization phase. It finds out, based on the given test, which nodes
067: * must be iterated over.
068: *
069: * @param node the current node
070: * @param test the test object
071: * @return a list with the matching nodes
072: */
073: protected List createSubNodeList(ConfigurationNode node,
074: NodeTest test) {
075: List children = node.getChildren();
076:
077: if (test == null) {
078: return children;
079: } else {
080: if (test instanceof NodeNameTest) {
081: NodeNameTest nameTest = (NodeNameTest) test;
082: QName name = nameTest.getNodeName();
083: if (name.getPrefix() == null) {
084: if (nameTest.isWildcard()) {
085: return children;
086: }
087:
088: List result = new ArrayList();
089: for (Iterator it = children.iterator(); it
090: .hasNext();) {
091: ConfigurationNode child = (ConfigurationNode) it
092: .next();
093: if (StringUtils.equals(name.getName(), child
094: .getName())) {
095: result.add(child);
096: }
097: }
098: return result;
099: }
100: }
101:
102: else if (test instanceof NodeTypeTest) {
103: NodeTypeTest typeTest = (NodeTypeTest) test;
104: if (typeTest.getNodeType() == Compiler.NODE_TYPE_NODE
105: || typeTest.getNodeType() == Compiler.NODE_TYPE_TEXT) {
106: return children;
107: }
108: }
109: }
110:
111: return Collections.EMPTY_LIST;
112: }
113:
114: /**
115: * Determines the start position of the iteration. Finds the index of the
116: * given start node in the children of the root node.
117: *
118: * @param node the root node
119: * @param startNode the start node
120: * @return the start node's index
121: */
122: protected int findStartIndex(ConfigurationNode node,
123: ConfigurationNode startNode) {
124: for (int index = 0; index < node.getChildrenCount(); index++) {
125: if (node.getChild(index) == startNode) {
126: return index;
127: }
128: }
129:
130: return -1;
131: }
132: }
|