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

org.apache.jackrabbit.commons.visitor.FilteringItemVisitor Maven / Gradle / Ivy

/*
 * 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.commons.visitor;

import java.util.LinkedList;

import javax.jcr.Item;
import javax.jcr.ItemVisitor;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;

import org.apache.jackrabbit.commons.predicate.Predicate;

public abstract class FilteringItemVisitor implements ItemVisitor {

    /**
     * Predicate that defines which items are included.
     */
    protected Predicate includePredicate = Predicate.TRUE;

    /**
     * Predicate that defines which items are traversed.
     */
    protected Predicate traversalPredicate = Predicate.TRUE;

    /**
     * Do we want to walk all properties of nodes?
     * The default is false.
     */
    protected boolean walkProperties = false;

    /**
     * indicates if traversal should be done in a breadth-first
     * manner rather than depth-first (which is the default)
     */
    protected boolean breadthFirst = false;

    /**
     * the 0-based level up to which the hierarchy should be traversed
     * (if it's -1, the hierarchy will be traversed until there are no
     * more children of the current item)
     */
    protected int maxLevel = -1;

    /**
     * queues used to implement breadth-first traversal
     */
    protected LinkedList currentQueue;
    protected LinkedList nextQueue;

    /**
     * used to track hierarchy level of item currently being processed
     */
    protected int currentLevel;

    public void setMaxLevel(final int ml) {
        this.maxLevel = ml;
    }

    public void setBreadthFirst(final boolean flag) {
        if ( this.breadthFirst != flag ) {
            this.breadthFirst = flag;
            if (breadthFirst) {
                this.currentQueue = new LinkedList();
                this.nextQueue = new LinkedList();
            } else {
                this.currentQueue = null;
                this.nextQueue = null;
            }

        }
    }
    public void setWalkProperties(final boolean flag) {
        this.walkProperties = flag;
    }

    public void setIncludePredicate(final Predicate ip) {
        this.includePredicate = ip;
    }

    public void setTraversalPredicate(final Predicate tp) {
        this.traversalPredicate = tp;
    }

    /**
     * Implement this method to add behaviour performed before a
     * Property is visited.
     *
     * @param property the Property that is accepting this visitor.
     * @param level    hierarchy level of this property (the root node starts at level 0)
     * @throws RepositoryException if an error occurrs
     */
    protected abstract void entering(Property property, int level)
        throws RepositoryException;

    /**
     * Implement this method to add behaviour performed before a
     * Node is visited.
     *
     * @param node  the Node that is accepting this visitor.
     * @param level hierarchy level of this node (the root node starts at level 0)
     * @throws RepositoryException if an error occurrs
     */
    protected abstract void entering(Node node, int level)
        throws RepositoryException;

    /**
     * Implement this method to add behaviour performed after a
     * Property is visited.
     *
     * @param property the Property that is accepting this visitor.
     * @param level    hierarchy level of this property (the root node starts at level 0)
     * @throws RepositoryException if an error occurrs
     */
    protected abstract void leaving(Property property, int level)
        throws RepositoryException;

    /**
     * Implement this method to add behaviour performed after a
     * Node is visited.
     *
     * @param node  the Node that is accepting this visitor.
     * @param level hierarchy level of this node (the root node starts at level 0)
     * @throws RepositoryException if an error occurrs
     */
    protected abstract void leaving(Node node, int level)
        throws RepositoryException;

    /**
     * Called when the Visitor is passed to a Property.
     * 

* It calls TraversingItemVisitor.entering(Property, int) followed by * TraversingItemVisitor.leaving(Property, int). Implement these abstract methods to * specify behaviour on 'arrival at' and 'after leaving' the Property. *

*

* If this method throws, the visiting process is aborted. * * @param property the Property that is accepting this visitor. * @throws RepositoryException if an error occurrs */ public void visit(Property property) throws RepositoryException { if ( this.walkProperties && this.includePredicate.evaluate(property) ) { entering(property, currentLevel); leaving(property, currentLevel); } } /** * Called when the Visitor is passed to a Node. *

* It calls TraversingItemVisitor.entering(Node, int) followed by * TraversingItemVisitor.leaving(Node, int). Implement these abstract methods to * specify behaviour on 'arrival at' and 'after leaving' the Node. *

* If this method throws, the visiting process is aborted. * * @param node the Node that is accepting this visitor. * @throws RepositoryException if an error occurrs */ public void visit(Node node) throws RepositoryException { if ( this.traversalPredicate.evaluate(node) ) { if ( this.includePredicate == this.traversalPredicate || this.includePredicate.evaluate(node) ) { try { if (!breadthFirst) { // depth-first traversal entering(node, currentLevel); if (maxLevel == -1 || currentLevel < maxLevel) { currentLevel++; if ( this.walkProperties ) { PropertyIterator propIter = node.getProperties(); while (propIter.hasNext()) { propIter.nextProperty().accept(this); } } NodeIterator nodeIter = node.getNodes(); while (nodeIter.hasNext()) { nodeIter.nextNode().accept(this); } currentLevel--; } leaving(node, currentLevel); } else { // breadth-first traversal entering(node, currentLevel); leaving(node, currentLevel); if (maxLevel == -1 || currentLevel < maxLevel) { if ( this.walkProperties ) { PropertyIterator propIter = node.getProperties(); while (propIter.hasNext()) { nextQueue.addLast(propIter.nextProperty()); } } NodeIterator nodeIter = node.getNodes(); while (nodeIter.hasNext()) { nextQueue.addLast(nodeIter.nextNode()); } } while (!currentQueue.isEmpty() || !nextQueue.isEmpty()) { if (currentQueue.isEmpty()) { currentLevel++; currentQueue = nextQueue; nextQueue = new LinkedList(); } Item e = (Item) currentQueue.removeFirst(); e.accept(this); } currentLevel = 0; } } catch (RepositoryException re) { currentLevel = 0; throw re; } } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy