    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.jxpath.ri.model.beans;
    018
    019    import java.util.ArrayList;
    020    import java.util.List;
    021
    022    import org.apache.commons.jxpath.JXPathException;
    023    import org.apache.commons.jxpath.ri.model.NodeIterator;
    024    import org.apache.commons.jxpath.ri.model.NodePointer;
    025
    026    /**
    027     * Combines node iterators of all elements of a collection into one
    028     * aggregate node iterator.
    029     *
    030     * @author Dmitri Plotnikov
    031     * @version $Revision: 652845 $ $Date: 2008-05-02 12:46:46 -0500 (Fri, 02 May 2008) $
    032     */
    033    public abstract class CollectionNodeIterator implements NodeIterator {
    034        private CollectionPointer pointer;
    035        private boolean reverse;
    036        private NodePointer startWith;
    037        private int position;
    038        private List collection;
    039
    040        /**
    041         * Create a new CollectionNodeIterator.
    042         * @param pointer collection pointer
    043         * @param reverse iteration order
    044         * @param startWith starting pointer
    045         */
    046        protected CollectionNodeIterator(
    047            CollectionPointer pointer,
    048            boolean reverse,
    049            NodePointer startWith) {
    050            this.pointer = pointer;
    051            this.reverse = reverse;
    052            this.startWith = startWith;
    053        }
    054
    055        /**
    056         * Implemented by subclasses to produce child/attribute node iterators.
    057         * @param elementPointer owning pointer
    058         * @return NodeIterator
    059         */
    060        protected abstract NodeIterator
    061                getElementNodeIterator(NodePointer elementPointer);
    062
    063        public int getPosition() {
    064            return position;
    065        }
    066
    067        public boolean setPosition(int position) {
    068            if (collection == null) {
    069                prepare();
    070            }
    071
    072            if (position < 1 || position > collection.size()) {
    073                return false;
    074            }
    075            this.position = position;
    076            return true;
    077        }
    078
    079        public NodePointer getNodePointer() {
    080            if (position == 0) {
    081                return null;
    082            }
    083            return (NodePointer) collection.get(position - 1);
    084        }
    085
    086        /**
    087         * Prepare...
    088         */
    089        private void prepare() {
    090            collection = new ArrayList();
    091            NodePointer ptr = (NodePointer) pointer.clone();
    092            int length = ptr.getLength();
    093            for (int i = 0; i < length; i++) {
    094                ptr.setIndex(i);
    095                NodePointer elementPointer = ptr.getValuePointer();
    096                NodeIterator iter = getElementNodeIterator(elementPointer);
    097
    098                for (int j = 1; iter.setPosition(j); j++) {
    099                    NodePointer childPointer = iter.getNodePointer();
    100                    if (reverse) {
    101                        collection.add(0, childPointer);
    102                    }
    103                    else {
    104                        collection.add(childPointer);
    105                    }
    106                }
    107            }
    108            if (startWith != null) {
    109                int index = collection.indexOf(startWith);
    110                if (index == -1) {
    111                    throw new JXPathException(
    112                        "Invalid starting pointer for iterator: " + startWith);
    113                }
    114                while (collection.size() > index) {
    115                    if (!reverse) {
    116                        collection.remove(collection.size() - 1);
    117                    }
    118                    else {
    119                        collection.remove(0);
    120                    }
    121                }
    122            }
    123        }
    124    }