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 + -
显示快捷键?