All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.htmlunit.xpath.NodeSet Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the  "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.sourceforge.htmlunit.xpath;

import net.sourceforge.htmlunit.xpath.res.XPATHErrorResources;
import net.sourceforge.htmlunit.xpath.res.XPATHMessages;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * The NodeSet class can act as either a NodeVector, NodeList, or NodeIterator. However, in order
 * for it to act as a NodeVector or NodeList, it's required that setShouldCacheNodes(true) be called
 * before the first nextNode() is called, in order that nodes can be added as they are fetched.
 * Derived classes that implement iterators must override runTo(int index), in order that they may
 * run the iteration to the given index.
 *
 * 

Note that we directly implement the DOM's NodeIterator interface. We do not emulate all the * behavior of the standard NodeIterator. In particular, we do not guarantee to present a "live * view" of the document ... but in XSLT, the source document should never be mutated, so this * should never be an issue. * *

Thought: Should NodeSet really implement NodeList and NodeIterator, or should there be * specific subclasses of it which do so? The advantage of doing it all here is that all NodeSets * will respond to the same calls; the disadvantage is that some of them may return * less-than-enlightening results when you do so. */ public class NodeSet implements NodeList, Cloneable { /** * Create an empty, using the given block size. * * @param blocksize Size of blocks to allocate */ public NodeSet(int blocksize) { m_blocksize = blocksize; m_mapSize = 0; } private void runTo(int index) { if (!m_cacheNodes) throw new RuntimeException( XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_CANNOT_INDEX, null)); if ((index >= 0) && (m_next < m_firstFree)) m_next = index; else m_next = m_firstFree - 1; } /** {@inheritDoc} */ @Override public Node item(int index) { runTo(index); if (null == m_map) return null; return m_map[index]; } /** {@inheritDoc} */ @Override public int getLength() { runTo(-1); return this.size(); } /** * Add a node to the NodeSet. Not all types of NodeSets support this operation * * @param n Node to be added * @throws RuntimeException thrown if this NodeSet is not of a mutable type. */ public void addNode(Node n) { if (!m_mutable) throw new RuntimeException( XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_NODESET_NOT_MUTABLE, null)); if ((m_firstFree + 1) >= m_mapSize) { if (null == m_map) { m_map = new Node[m_blocksize]; m_mapSize = m_blocksize; } else { m_mapSize += m_blocksize; Node[] newMap = new Node[m_mapSize]; System.arraycopy(m_map, 0, newMap, 0, m_firstFree + 1); m_map = newMap; } } m_map[m_firstFree] = n; m_firstFree++; } /** If this node is being used as an iterator, the next index that nextNode() will return. */ protected transient int m_next = 0; /** True if this list can be mutated. */ protected final transient boolean m_mutable = true; /** * True if this list is cached. * * @serial */ protected final transient boolean m_cacheNodes = true; /** * Size of blocks to allocate. * * @serial */ private final int m_blocksize; /** * Array of nodes this points to. * * @serial */ Node[] m_map; /** * Number of nodes in this NodeVector. * * @serial */ protected int m_firstFree = 0; /** * Size of the array this points to. * * @serial */ private int m_mapSize; // lazy initialization /** {@inheritDoc} */ @Override public Object clone() throws CloneNotSupportedException { NodeSet clone = (NodeSet) super.clone(); if ((null != this.m_map) && (this.m_map == clone.m_map)) { clone.m_map = new Node[this.m_map.length]; System.arraycopy(this.m_map, 0, clone.m_map, 0, this.m_map.length); } return clone; } public int size() { return m_firstFree; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy