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

com.sun.org.apache.xerces.internal.dom.DeepNodeListImpl Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 *
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 * 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 com.sun.org.apache.xerces.internal.dom;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.Vector;

/**
 * This class implements the DOM's NodeList behavior for
 * Element.getElementsByTagName()
 * 

* The DOM describes NodeList as follows: *

* 1) It may represent EITHER nodes scattered through a subtree (when * returned by Element.getElementsByTagName), or just the immediate * children (when returned by Node.getChildNodes). The latter is easy, * but the former (which this class addresses) is more challenging. *

* 2) Its behavior is "live" -- that is, it always reflects the * current state of the document tree. To put it another way, the * NodeLists obtained before and after a series of insertions and * deletions are effectively identical (as far as the user is * concerned, the former has been dynamically updated as the changes * have been made). *

* 3) Its API accesses individual nodes via an integer index, with the * listed nodes numbered sequentially in the order that they were * found during a preorder depth-first left-to-right search of the tree. * (Of course in the case of getChildNodes, depth is not involved.) As * nodes are inserted or deleted in the tree, and hence the NodeList, * the numbering of nodes that follow them in the NodeList will * change. *

* It is rather painful to support the latter two in the * getElementsByTagName case. The current solution is for Nodes to * maintain a change count (eventually that may be a Digest instead), * which the NodeList tracks and uses to invalidate itself. *

* Unfortunately, this does _not_ respond efficiently in the case that * the dynamic behavior was supposed to address: scanning a tree while * it is being extended. That requires knowing which subtrees have * changed, which can become an arbitrarily complex problem. *

* We save some work by filling the vector only as we access the * item()s... but I suspect the same users who demanded index-based * access will also start by doing a getLength() to control their loop, * blowing this optimization out of the water. *

* NOTE: Level 2 of the DOM will probably _not_ use NodeList for its * extended search mechanisms, partly for the reasons just discussed. * * @xerces.internal * * @version $Id: DeepNodeListImpl.java,v 1.6 2010-11-01 04:39:38 joehw Exp $ * @since PR-DOM-Level-1-19980818. */ public class DeepNodeListImpl implements NodeList { // // Data // protected NodeImpl rootNode; // Where the search started protected String tagName; // Or "*" to mean all-tags-acceptable protected int changes=0; protected Vector nodes; protected String nsName; protected boolean enableNS = false; // // Constructors // /** Constructor. */ public DeepNodeListImpl(NodeImpl rootNode, String tagName) { this.rootNode = rootNode; this.tagName = tagName; nodes = new Vector(); } /** Constructor for Namespace support. */ public DeepNodeListImpl(NodeImpl rootNode, String nsName, String tagName) { this(rootNode, tagName); this.nsName = (nsName != null && !nsName.equals("")) ? nsName : null; enableNS = true; } // // NodeList methods // /** Returns the length of the node list. */ public int getLength() { // Preload all matching elements. (Stops when we run out of subtree!) item(java.lang.Integer.MAX_VALUE); return nodes.size(); } /** Returns the node at the specified index. */ public Node item(int index) { Node thisNode; // Tree changed. Do it all from scratch! if(rootNode.changes() != changes) { nodes = new Vector(); changes = rootNode.changes(); } // In the cache if (index < nodes.size()) return (Node)nodes.elementAt(index); // Not yet seen else { // Pick up where we left off (Which may be the beginning) if (nodes.size() == 0) thisNode = rootNode; else thisNode=(NodeImpl)(nodes.lastElement()); // Add nodes up to the one we're looking for while(thisNode != null && index >= nodes.size()) { thisNode=nextMatchingElementAfter(thisNode); if (thisNode != null) nodes.addElement(thisNode); } // Either what we want, or null (not avail.) return thisNode; } } // item(int):Node // // Protected methods (might be overridden by an extending DOM) // /** * Iterative tree-walker. When you have a Parent link, there's often no * need to resort to recursion. NOTE THAT only Element nodes are matched * since we're specifically supporting getElementsByTagName(). */ protected Node nextMatchingElementAfter(Node current) { Node next; while (current != null) { // Look down to first child. if (current.hasChildNodes()) { current = (current.getFirstChild()); } // Look right to sibling (but not from root!) else if (current != rootNode && null != (next = current.getNextSibling())) { current = next; } // Look up and right (but not past root!) else { next = null; for (; current != rootNode; // Stop when we return to starting point current = current.getParentNode()) { next = current.getNextSibling(); if (next != null) break; } current = next; } // Have we found an Element with the right tagName? // ("*" matches anything.) if (current != rootNode && current != null && current.getNodeType() == Node.ELEMENT_NODE) { if (!enableNS) { if (tagName.equals("*") || ((ElementImpl) current).getTagName().equals(tagName)) { return current; } } else { // DOM2: Namespace logic. if (tagName.equals("*")) { if (nsName != null && nsName.equals("*")) { return current; } else { ElementImpl el = (ElementImpl) current; if ((nsName == null && el.getNamespaceURI() == null) || (nsName != null && nsName.equals(el.getNamespaceURI()))) { return current; } } } else { ElementImpl el = (ElementImpl) current; if (el.getLocalName() != null && el.getLocalName().equals(tagName)) { if (nsName != null && nsName.equals("*")) { return current; } else { if ((nsName == null && el.getNamespaceURI() == null) || (nsName != null && nsName.equals(el.getNamespaceURI()))) { return current; } } } } } } // Otherwise continue walking the tree } // Fell out of tree-walk; no more instances found return null; } // nextMatchingElementAfter(int):Node } // class DeepNodeListImpl





© 2015 - 2024 Weber Informatics LLC | Privacy Policy