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

com.sun.org.apache.xalan.internal.xsltc.dom.MultiValuedNodeHeapIterator 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.
 */

/*
 * $Id: MultiValuedNodeHeapIterator.java,v 1.6 2010-11-01 04:34:24 joehw Exp $
 */
package com.sun.org.apache.xalan.internal.xsltc.dom;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIteratorBase;

/**
 * 

MultiValuedNodeHeapIterator takes a set of multi-valued * heap nodes and produces a merged NodeSet in document order with duplicates * removed.

*

Each multi-valued heap node (which might be a * {@link org.apache.xml.dtm.DTMAxisIterator}, but that's not necessary) * generates DTM node handles in document order. The class * maintains the multi-valued heap nodes in a heap, not surprisingly, sorted by * the next DTM node handle available form the heap node.

*

After a DTM node is pulled from the heap node that's at the top of the * heap, the heap node is advanced to the next DTM node handle it makes * available, and the heap nature of the heap is restored to ensure the next * DTM node handle pulled is next in document order overall. * * @author Jacek Ambroziak * @author Santiago Pericas-Geertsen */ public abstract class MultiValuedNodeHeapIterator extends DTMAxisIteratorBase { /** wrapper for NodeIterators to support iterator comparison on the value of their next() method */ /** * An abstract representation of a set of nodes that will be retrieved in * document order. */ public abstract class HeapNode implements Cloneable { protected int _node, _markedNode; protected boolean _isStartSet = false; /** * Advance to the next node represented by this {@link HeapNode} * * @return the next DTM node. */ public abstract int step(); /** * Creates a deep copy of this {@link HeapNode}. The clone is not * reset from the current position of the original. * * @return the cloned heap node */ public HeapNode cloneHeapNode() { HeapNode clone; try { clone = (HeapNode) super.clone(); } catch (CloneNotSupportedException e) { BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR, e.toString()); return null; } clone._node = _node; clone._markedNode = _node; return clone; } /** * Remembers the current node for the next call to {@link #gotoMark()}. */ public void setMark() { _markedNode = _node; } /** * Restores the current node remembered by {@link #setMark()}. */ public void gotoMark() { _node = _markedNode; } /** * Performs a comparison of the two heap nodes * * @param heapNode the heap node against which to compare * @return true if and only if the current node for this * heap node is before the current node of the argument heap * node in document order. */ public abstract boolean isLessThan(HeapNode heapNode); /** * Sets context with respect to which this heap node is evaluated. * * @param node The new context node * @return a {@link HeapNode} which may or may not be the same as * this HeapNode. */ public abstract HeapNode setStartNode(int node); /** * Reset the heap node back to its beginning. * * @return a {@link HeapNode} which may or may not be the same as * this HeapNode. */ public abstract HeapNode reset(); } // end of HeapNode private static final int InitSize = 8; private int _heapSize = 0; private int _size = InitSize; private HeapNode[] _heap = new HeapNode[InitSize]; private int _free = 0; // Last node returned by this MultiValuedNodeHeapIterator to the caller of // next; used to prune duplicates private int _returnedLast; // cached returned last for use in gotoMark private int _cachedReturnedLast = END; // cached heap size for use in gotoMark private int _cachedHeapSize; public DTMAxisIterator cloneIterator() { _isRestartable = false; final HeapNode[] heapCopy = new HeapNode[_heap.length]; try { MultiValuedNodeHeapIterator clone = (MultiValuedNodeHeapIterator)super.clone(); for (int i = 0; i < _free; i++) { heapCopy[i] = _heap[i].cloneHeapNode(); } clone.setRestartable(false); clone._heap = heapCopy; return clone.reset(); } catch (CloneNotSupportedException e) { BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR, e.toString()); return null; } } protected void addHeapNode(HeapNode node) { if (_free == _size) { HeapNode[] newArray = new HeapNode[_size *= 2]; System.arraycopy(_heap, 0, newArray, 0, _free); _heap = newArray; } _heapSize++; _heap[_free++] = node; } public int next() { while (_heapSize > 0) { final int smallest = _heap[0]._node; if (smallest == END) { // iterator _heap[0] is done if (_heapSize > 1) { // Swap first and last (iterator must be restartable) final HeapNode temp = _heap[0]; _heap[0] = _heap[--_heapSize]; _heap[_heapSize] = temp; } else { return END; } } else if (smallest == _returnedLast) { // duplicate _heap[0].step(); // value consumed } else { _heap[0].step(); // value consumed heapify(0); return returnNode(_returnedLast = smallest); } // fallthrough if not returned above heapify(0); } return END; } public DTMAxisIterator setStartNode(int node) { if (_isRestartable) { _startNode = node; for (int i = 0; i < _free; i++) { if(!_heap[i]._isStartSet){ _heap[i].setStartNode(node); _heap[i].step(); // to get the first node _heap[i]._isStartSet = true; } } // build heap for (int i = (_heapSize = _free)/2; i >= 0; i--) { heapify(i); } _returnedLast = END; return resetPosition(); } return this; } protected void init() { for (int i =0; i < _free; i++) { _heap[i] = null; } _heapSize = 0; _free = 0; } /* Build a heap in document order. put the smallest node on the top. * "smallest node" means the node before other nodes in document order */ private void heapify(int i) { for (int r, l, smallest;;) { r = (i + 1) << 1; l = r - 1; smallest = l < _heapSize && _heap[l].isLessThan(_heap[i]) ? l : i; if (r < _heapSize && _heap[r].isLessThan(_heap[smallest])) { smallest = r; } if (smallest != i) { final HeapNode temp = _heap[smallest]; _heap[smallest] = _heap[i]; _heap[i] = temp; i = smallest; } else { break; } } } public void setMark() { for (int i = 0; i < _free; i++) { _heap[i].setMark(); } _cachedReturnedLast = _returnedLast; _cachedHeapSize = _heapSize; } public void gotoMark() { for (int i = 0; i < _free; i++) { _heap[i].gotoMark(); } // rebuild heap after call last() function. fix for bug 20913 for (int i = (_heapSize = _cachedHeapSize)/2; i >= 0; i--) { heapify(i); } _returnedLast = _cachedReturnedLast; } public DTMAxisIterator reset() { for (int i = 0; i < _free; i++) { _heap[i].reset(); _heap[i].step(); } // build heap for (int i = (_heapSize = _free)/2; i >= 0; i--) { heapify(i); } _returnedLast = END; return resetPosition(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy