Package org.exoplatform.services.jcr.impl.core.query.lucene

Source Code of org.exoplatform.services.jcr.impl.core.query.lucene.NodeTraversingQueryHits$TraversingNodeIterator

/*
* 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.exoplatform.services.jcr.impl.core.query.lucene;

import org.apache.commons.collections.iterators.IteratorChain;
import org.exoplatform.services.jcr.impl.core.NodeImpl;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;

/**
* <code>NodeTraversingQueryHits</code> implements query hits that traverse
* a node hierarchy.
*/
public class NodeTraversingQueryHits extends AbstractQueryHits
{

   private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.NodeTraversingQueryHits");

   /**
     * The nodes to traverse.
     */
    private final Iterator nodes;

    /**
     * Creates query hits that consist of the nodes that are traversed from a
     * given <code>start</code> node.
     *
     * @param start        the start node of the traversal.
     * @param includeStart whether to include the start node in the result.
     */
    public NodeTraversingQueryHits(Node start, boolean includeStart) {
        this(start, includeStart, Integer.MAX_VALUE);
    }

    /**
     * Creates query hits that consist of the nodes that are traversed from a
     * given <code>start</code> node.
     *
     * @param start        the start node of the traversal.
     * @param includeStart whether to include the start node in the result.
     * @param maxDepth     the maximum depth of nodes to traverse.
     */
    public NodeTraversingQueryHits(Node start,
                                   boolean includeStart,
                                   int maxDepth) {
        this.nodes = new TraversingNodeIterator(start, maxDepth);
        if (!includeStart) {
            nodes.next();
        }
    }

    /**
     * {@inheritDoc}
     */
    public ScoreNode nextScoreNode() throws IOException {
        if (nodes.hasNext()) {
            NodeImpl n = (NodeImpl) nodes.next();
            return new ScoreNode(n.getData().getIdentifier(), 1.0f);
        } else {
            return null;
        }
    }

    /**
     * Implements a node iterator that traverses a node tree in document
     * order.
     */
    private class TraversingNodeIterator implements Iterator {

        /**
         * The current <code>Node</code>, which acts as the starting point for
         * the traversal.
         */
        private final Node currentNode;

        /**
         * The maximum depth of the traversal.
         */
        private final int maxDepth;

        /**
         * The chain of iterators which includes the iterators of the children
         * of the current node.
         */
        private Iterator selfAndChildren;

        /**
         * Creates a <code>TraversingNodeIterator</code>.
         *
         * @param start    the node from where to start the traversal.
         * @param maxDepth the maximum depth of nodes to traverse.
         */
        TraversingNodeIterator(Node start, int maxDepth) {
            if (maxDepth < 0) {
                throw new IllegalArgumentException("maxDepth must be >= 0");
            }
            currentNode = start;
            this.maxDepth = maxDepth;
        }

        /**
         * @exception UnsupportedOperationException always.
         */
        public void remove() {
            throw new UnsupportedOperationException("remove");
        }

        /**
         * @inheritDoc
         */
        public boolean hasNext() {
            init();
            return selfAndChildren.hasNext();
        }

        /**
         * @inheritDoc
         */
        public Object next() {
            init();
            NodeImpl n = (NodeImpl) selfAndChildren.next();
            return n;
        }

        /**
         * Initializes the iterator chain once.
         */
      private void init()
      {
         if (selfAndChildren == null)
         {
            List allIterators = new ArrayList();
            Iterator current = Collections.singletonList(currentNode).iterator();
            allIterators.add(current);
            if (maxDepth == 0)
            {
               // only current node
            }
            else if (maxDepth == 1)
            {
               try
               {
                  allIterators.add(currentNode.getNodes());
               }
               catch (RepositoryException e)
               {
                  if (LOG.isTraceEnabled())
                  {
                     LOG.trace("An exception occurred: " + e.getMessage());
                  }
               }
            }
            else
            {
               // create new TraversingNodeIterator for each child
               try
               {
                  NodeIterator children = currentNode.getNodes();
                  while (children.hasNext())
                  {
                     allIterators.add(new TraversingNodeIterator(children.nextNode(), maxDepth - 1));
                  }
               }
               catch (RepositoryException e)
               {
                  if (LOG.isTraceEnabled())
                  {
                     LOG.trace("An exception occurred: " + e.getMessage());
                  }
               }
            }
            selfAndChildren = new IteratorChain(allIterators);
         }
      }
    }
}
TOP

Related Classes of org.exoplatform.services.jcr.impl.core.query.lucene.NodeTraversingQueryHits$TraversingNodeIterator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.