14c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/*
24c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
34c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * or more contributor license agreements. See the NOTICE file
44c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed with this work for additional information
54c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * regarding copyright ownership. The ASF licenses this file
64c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
74c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * you may not use this file except in compliance with the License.
84c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * You may obtain a copy of the License at
94c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Unless required by applicable law or agreed to in writing, software
134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * See the License for the specific language governing permissions and
164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * limitations under the License.
174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/*
194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * $Id: DTMAxisIterNodeList.java 468653 2006-10-28 07:07:05Z minchau $
204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpackage org.apache.xml.dtm.ref;
224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.DTM;
244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.dtm.DTMAxisIterator;
254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.utils.IntVector;
264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.w3c.dom.Node;
284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/**
304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * <code>DTMAxisNodeList</code> gives us an implementation of the DOM's
314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * NodeList interface wrapped around a DTM Iterator. The author
324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * considers this something of an abominations, since NodeList was not
334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * intended to be a general purpose "list of nodes" API and is
344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * generally considered by the DOM WG to have be a mistake... but I'm
354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * told that some of the XPath/XSLT folks say they must have this
364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * solution.
374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Please note that this is not necessarily equivlaent to a DOM
394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * NodeList operating over the same document. In particular:
404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * <ul>
414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * <li>If there are several Text nodes in logical succession (ie,
434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * across CDATASection and EntityReference boundaries), we will return
444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * only the first; the caller is responsible for stepping through
454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * them.
464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * (%REVIEW% Provide a convenience routine here to assist, pending
474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * proposed DOM Level 3 getAdjacentText() operation?) </li>
484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * <li>Since the whole XPath/XSLT architecture assumes that the source
504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * document is not altered while we're working with it, we do not
514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * promise to implement the DOM NodeList's "live view" response to
524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * document mutation. </li>
534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * </ul>
554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * <p>State: In progress!!</p>
574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * */
584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpublic class DTMAxisIterNodeList extends DTMNodeListBase {
594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    private DTM m_dtm;
604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    private DTMAxisIterator m_iter;
614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    private IntVector m_cachedNodes;
624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    private int m_last = -1;
634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    //================================================================
644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // Methods unique to this class
654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    private DTMAxisIterNodeList() {
664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Public constructor: Wrap a DTMNodeList around an existing
704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * and preconfigured DTMAxisIterator
714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public DTMAxisIterNodeList(DTM dtm, DTMAxisIterator dtmAxisIterator) {
734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        if (dtmAxisIterator == null) {
744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            m_last = 0;
754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        } else {
764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            m_cachedNodes = new IntVector();
774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            m_dtm = dtm;
784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        }
794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        m_iter = dtmAxisIterator;
804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Access the wrapped DTMIterator. I'm not sure whether anyone will
844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * need this or not, but let's write it and think about it.
854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     *
864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public DTMAxisIterator getDTMAxisIterator() {
884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        return m_iter;
894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    //================================================================
934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // org.w3c.dom.NodeList API follows
944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Returns the <code>index</code>th item in the collection. If
974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * <code>index</code> is greater than or equal to the number of nodes in
984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * the list, this returns <code>null</code>.
994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @param index Index into the collection.
1004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @return The node at the <code>index</code>th position in the
1014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     *   <code>NodeList</code>, or <code>null</code> if that is not a valid
1024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     *   index.
1034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
1044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public Node item(int index) {
1054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        if (m_iter != null) {
1064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            int node;
1074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            int count = m_cachedNodes.size();
1084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            if (count > index) {
1104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                node = m_cachedNodes.elementAt(index);
1114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                return m_dtm.getNode(node);
1124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            } else if (m_last == -1) {
1134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                while (((node = m_iter.next()) != DTMAxisIterator.END)
1144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                           && count <= index) {
1154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                    m_cachedNodes.addElement(node);
1164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                    count++;
1174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                }
1184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                if (node == DTMAxisIterator.END) {
1194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                    m_last = count;
1204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                } else {
1214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                    return m_dtm.getNode(node);
1224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                }
1234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            }
1244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        }
1254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        return null;
1264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
1294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * The number of nodes in the list. The range of valid child node indices
1304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * is 0 to <code>length-1</code> inclusive.
1314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
1324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    public int getLength() {
1334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        if (m_last == -1) {
1344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            int node;
1354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            while ((node = m_iter.next()) != DTMAxisIterator.END) {
1364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                m_cachedNodes.addElement(node);
1374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            }
1384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            m_last = m_cachedNodes.size();
1394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        }
1404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        return m_last;
1414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson}
143