docordernodeiteratorimpl.java
来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 265 行
JAVA
265 行
/* * 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 org.apache.jackrabbit.core.query.lucene;import org.apache.jackrabbit.core.ItemManager;import org.apache.jackrabbit.core.NodeImpl;import org.apache.jackrabbit.name.Path;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.jcr.Node;import javax.jcr.NodeIterator;import javax.jcr.RepositoryException;import java.util.Arrays;import java.util.Comparator;import java.util.List;import java.util.ArrayList;/** * Implements a NodeIterator that returns the nodes in document order. */class DocOrderNodeIteratorImpl implements ScoreNodeIterator { /** Logger instance for this class */ private static final Logger log = LoggerFactory.getLogger(DocOrderNodeIteratorImpl.class); /** A node iterator with ordered nodes */ private NodeIteratorImpl orderedNodes; /** Unordered list of {@link ScoreNode}s. */ private final List scoreNodes; /** ItemManager to turn UUIDs into Node instances */ protected final ItemManager itemMgr; /** * Creates a <code>DocOrderNodeIteratorImpl</code> that orders the nodes in * <code>scoreNodes</code> in document order. * * @param itemMgr the item manager of the session executing the query. * @param scoreNodes the ids of the matching nodes with their score value. */ DocOrderNodeIteratorImpl(final ItemManager itemMgr, List scoreNodes) { this.itemMgr = itemMgr; this.scoreNodes = scoreNodes; } /** * {@inheritDoc} */ public Object next() { return nextNodeImpl(); } /** * {@inheritDoc} */ public Node nextNode() { return nextNodeImpl(); } /** * {@inheritDoc} */ public NodeImpl nextNodeImpl() { initOrderedIterator(); return orderedNodes.nextNodeImpl(); } /** * @throws UnsupportedOperationException always. */ public void remove() { throw new UnsupportedOperationException("remove"); } /** * {@inheritDoc} */ public void skip(long skipNum) { initOrderedIterator(); orderedNodes.skip(skipNum); } /** * Returns the number of nodes in this iterator. * </p> * Note: The number returned by this method may differ from the number * of nodes actually returned by calls to hasNext() / getNextNode()! This * is because this iterator works on a lazy instantiation basis and while * iterating over the nodes some of them might have been deleted in the * meantime. Those will not be returned by getNextNode(). As soon as an * invalid node is detected, the size of this iterator is adjusted. * * @return the number of node in this iterator. */ public long getSize() { if (orderedNodes != null) { return orderedNodes.getSize(); } else { return scoreNodes.size(); } } /** * {@inheritDoc} */ public long getPosition() { initOrderedIterator(); return orderedNodes.getPosition(); } /** * {@inheritDoc} */ public boolean hasNext() { initOrderedIterator(); return orderedNodes.hasNext(); } /** * {@inheritDoc} */ public float getScore() { initOrderedIterator(); return orderedNodes.getScore(); } //------------------------< internal >-------------------------------------- /** * Initializes the NodeIterator in document order */ private void initOrderedIterator() { if (orderedNodes != null) { return; } long time = System.currentTimeMillis(); ScoreNode[] nodes = (ScoreNode[]) scoreNodes.toArray(new ScoreNode[scoreNodes.size()]); final List invalidIDs = new ArrayList(2); do { if (invalidIDs.size() > 0) { // previous sort run was not successful -> remove failed uuids List tmp = new ArrayList(); for (int i = 0; i < nodes.length; i++) { if (!invalidIDs.contains(nodes[i].getNodeId())) { tmp.add(nodes[i]); } } nodes = (ScoreNode[]) tmp.toArray(new ScoreNode[tmp.size()]); invalidIDs.clear(); } try { // sort the uuids Arrays.sort(nodes, new Comparator() { public int compare(Object o1, Object o2) { ScoreNode n1 = (ScoreNode) o1; ScoreNode n2 = (ScoreNode) o2; try { NodeImpl node1; try { node1 = (NodeImpl) itemMgr.getItem(n1.getNodeId()); } catch (RepositoryException e) { log.warn("Node " + n1.getNodeId() + " does not exist anymore: " + e); // node does not exist anymore invalidIDs.add(n1.getNodeId()); throw new SortFailedException(); } NodeImpl node2; try { node2 = (NodeImpl) itemMgr.getItem(n2.getNodeId()); } catch (RepositoryException e) { log.warn("Node " + n2.getNodeId() + " does not exist anymore: " + e); // node does not exist anymore invalidIDs.add(n2.getNodeId()); throw new SortFailedException(); } Path.PathElement[] path1 = node1.getPrimaryPath().getElements(); Path.PathElement[] path2 = node2.getPrimaryPath().getElements(); // find nearest common ancestor int commonDepth = 0; // root while (path1.length > commonDepth && path2.length > commonDepth) { if (path1[commonDepth].equals(path2[commonDepth])) { commonDepth++; } else { break; } } // path elements at last depth were equal commonDepth--; // check if either path is an ancestor of the other if (path1.length - 1 == commonDepth) { // path1 itself is ancestor of path2 return -1; } if (path2.length - 1 == commonDepth) { // path2 itself is ancestor of path1 return 1; } // get common ancestor node NodeImpl commonNode = (NodeImpl) node1.getAncestor(commonDepth); // move node1/node2 to the commonDepth + 1 // node1 and node2 then will be child nodes of commonNode node1 = (NodeImpl) node1.getAncestor(commonDepth + 1); node2 = (NodeImpl) node2.getAncestor(commonDepth + 1); for (NodeIterator it = commonNode.getNodes(); it.hasNext();) { Node child = it.nextNode(); if (child.isSame(node1)) { return -1; } else if (child.isSame(node2)) { return 1; } } log.error("Internal error: unable to determine document order of nodes:"); log.error("\tNode1: " + node1.getPath()); log.error("\tNode2: " + node2.getPath()); } catch (RepositoryException e) { log.error("Exception while sorting nodes in document order: " + e.toString(), e); } // if we get here something went wrong // remove both uuids from array invalidIDs.add(n1.getNodeId()); invalidIDs.add(n2.getNodeId()); // terminate sorting throw new SortFailedException(); } }); } catch (SortFailedException e) { // retry } } while (invalidIDs.size() > 0); if (log.isDebugEnabled()) { log.debug("" + nodes.length + " node(s) ordered in " + (System.currentTimeMillis() - time) + " ms"); } orderedNodes = new NodeIteratorImpl(itemMgr, nodes); } /** * Indicates that sorting failed. */ private static final class SortFailedException extends RuntimeException { }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?