You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by md...@apache.org on 2010/08/12 13:53:20 UTC

svn commit: r984729 - in /jackrabbit/trunk: jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/

Author: mduerig
Date: Thu Aug 12 11:53:20 2010
New Revision: 984729

URL: http://svn.apache.org/viewvc?rev=984729&view=rev
Log:
JCR-2711: BTreeManager needs more flexible mechanism for ignoring (internal) properties

Added:
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/FilterIterator.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/ItemSequenceTest.java
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/BTreeManager.java
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/ItemSequence.java
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/TreeManager.java
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/TreeTraverser.java

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/ItemSequenceTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/ItemSequenceTest.java?rev=984729&r1=984728&r2=984729&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/ItemSequenceTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/ItemSequenceTest.java Thu Aug 12 11:53:20 2010
@@ -24,8 +24,10 @@ import org.apache.jackrabbit.commons.fla
 import org.apache.jackrabbit.commons.flat.Rank;
 import org.apache.jackrabbit.commons.flat.TreeManager;
 import org.apache.jackrabbit.commons.flat.TreeTraverser;
+import org.apache.jackrabbit.commons.flat.TreeTraverser.ErrorHandler;
 import org.apache.jackrabbit.test.AbstractJCRTest;
 
+import javax.jcr.Item;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.Property;
@@ -40,11 +42,17 @@ import java.io.IOException;
 import java.io.InputStreamReader;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
 public class ItemSequenceTest extends AbstractJCRTest {
     private Node testNode;
+    private final ErrorHandler errorHandler = new ErrorHandler() {
+        public void call(Item item, RepositoryException exception) {
+            fail("An exception occurred on " + item + ": " + exception);
+        }
+    };
 
     @Override
     public void setUp() throws Exception {
@@ -53,10 +61,45 @@ public class ItemSequenceTest extends Ab
         superuser.save();
     }
 
+    public void testEmptyNodeSequence() throws RepositoryException {
+        Comparator<String> order = Rank.<String>comparableComparator();
+        TreeManager treeManager = new BTreeManager(testNode, 5, 10, order, true);
+        NodeSequence nodes = ItemSequence.createNodeSequence(treeManager, errorHandler);
+
+        Iterator<Node> nodeIt = nodes.iterator();
+        assertTrue(nodeIt.hasNext());
+        assertTrue(treeManager.isRoot(nodeIt.next()));
+        assertFalse(nodeIt.hasNext());
+
+        checkTreeProperty(testNode, 5, 10, order);
+        checkOrder(nodes, order);
+        assertEmpty(nodes);
+    }
+
+    public void testSingletonNodeSequence() throws RepositoryException {
+        Comparator<String> order = Rank.<String>comparableComparator();
+        TreeManager treeManager = new BTreeManager(testNode, 5, 10, order, true);
+        NodeSequence nodes = ItemSequence.createNodeSequence(treeManager, errorHandler);
+
+        nodes.addNode("key", NodeType.NT_UNSTRUCTURED);
+        assertTrue(nodes.hasItem("key"));
+
+        Iterator<Node> nodeIt = nodes.iterator();
+        assertTrue(nodeIt.hasNext());
+        assertEquals("key", nodeIt.next().getName());
+        assertFalse(nodeIt.hasNext());
+
+        checkTreeProperty(testNode, 5, 10, order);
+        checkOrder(nodes, order);
+
+        nodes.removeNode("key");
+        assertEmpty(nodes);
+    }
+
     public void testNodeSequence() throws RepositoryException, IOException {
         Comparator<String> order = Rank.<String>comparableComparator();
         TreeManager treeManager = new BTreeManager(testNode, 5, 10, order, true);
-        NodeSequence nodes = ItemSequence.createNodeSequence(treeManager);
+        NodeSequence nodes = ItemSequence.createNodeSequence(treeManager, errorHandler);
 
         List<String> words = loadWords();
         Collections.shuffle(words);
@@ -75,13 +118,41 @@ public class ItemSequenceTest extends Ab
         checkLookup(nodes, words);
 
         removeAll(nodes, words);
-        checkEmpty(nodes);
+        assertEmpty(nodes);
+    }
+
+    public void testEmptyPropertySequence() throws RepositoryException {
+        Comparator<String> order = Rank.<String>comparableComparator();
+        TreeManager treeManager = new BTreeManager(testNode, 2, 4, order, true);
+        PropertySequence properties = ItemSequence.createPropertySequence(treeManager, errorHandler);
+
+        Iterator<Property> propertyIt = properties.iterator();
+        assertFalse(propertyIt.hasNext());
+        assertEmpty(properties);
+    }
+
+    public void testSingletonPropertySequence() throws RepositoryException {
+        Comparator<String> order = Rank.<String>comparableComparator();
+        TreeManager treeManager = new BTreeManager(testNode, 2, 4, order, true);
+        PropertySequence properties = ItemSequence.createPropertySequence(treeManager, errorHandler);
+
+        ValueFactory vFactory = testNode.getSession().getValueFactory();
+        properties.addProperty("key", vFactory.createValue("key_"));
+        assertTrue(properties.hasItem("key"));
+
+        Iterator<Property> propertyIt = properties.iterator();
+        assertTrue(propertyIt.hasNext());
+        assertEquals("key", propertyIt.next().getName());
+        assertFalse(propertyIt.hasNext());
+
+        properties.removeProperty("key");
+        assertEmpty(properties);
     }
 
     public void testPropertySequence() throws RepositoryException, IOException {
         Comparator<String> order = Rank.<String>comparableComparator();
         TreeManager treeManager = new BTreeManager(testNode, 2, 4, order, true);
-        PropertySequence properties = ItemSequence.createPropertySequence(treeManager);
+        PropertySequence properties = ItemSequence.createPropertySequence(treeManager, errorHandler);
 
         List<String> words = loadWords();
         Collections.shuffle(words);
@@ -100,7 +171,7 @@ public class ItemSequenceTest extends Ab
         checkLookup(properties, words);
 
         removeAll(properties, words);
-        checkEmpty(properties);
+        assertEmpty(properties);
     }
 
     // -----------------------------------------------------< internal >---
@@ -263,13 +334,15 @@ public class ItemSequenceTest extends Ab
         }
     }
 
-    private static void checkEmpty(NodeSequence nodes) throws RepositoryException {
+    private void assertEmpty(NodeSequence nodes) throws RepositoryException {
         for (Node n : nodes) {
-            fail("NodeSqeuence should be empty but found " + n.getPath());
+            if (!n.isSame(testNode)) {
+                fail("NodeSqeuence should be empty but found " + n.getPath());
+            }
         }
     }
 
-    private static void checkEmpty(PropertySequence properties) throws RepositoryException {
+    private void assertEmpty(PropertySequence properties) throws RepositoryException {
         for (Property p : properties) {
             fail("PropertySqeuence should be empty but found " + p.getPath());
         }

Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/BTreeManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/BTreeManager.java?rev=984729&r1=984728&r2=984729&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/BTreeManager.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/BTreeManager.java Thu Aug 12 11:53:20 2010
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.commons.flat;
 
 import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.commons.predicate.Predicate;
 
 import javax.jcr.Item;
 import javax.jcr.Node;
@@ -25,9 +26,11 @@ import javax.jcr.Property;
 import javax.jcr.PropertyIterator;
 import javax.jcr.RepositoryException;
 
+import java.util.Arrays;
 import java.util.Comparator;
+import java.util.HashSet;
 import java.util.Iterator;
-import java.util.NoSuchElementException;
+import java.util.Set;
 
 /**
  * <p>
@@ -91,6 +94,10 @@ public class BTreeManager implements Tre
     private final boolean autoSave;
     private final Comparator<Item> itemOrder;
 
+    private final Set<String> ignoredProperties = new HashSet<String>(Arrays.asList(
+            JcrConstants.JCR_PRIMARYTYPE,
+            JcrConstants.JCR_MIXINTYPES));
+
     /**
      * Create a new {@link BTreeManager} rooted at Node <code>root</code>.
      *
@@ -142,6 +149,16 @@ public class BTreeManager implements Tre
     }
 
     /**
+     * Properties to ignore. The default set contains {@link JcrConstants#JCR_PRIMARYTYPE}
+     * and {@link JcrConstants#JCR_MIXINTYPES}.
+     *
+     * @return
+     */
+    public Set<String> getIgnoredProperties() {
+        return ignoredProperties;
+    }
+
+    /**
      * This implementations splits <code>node</code> when its number of child
      * nodes exceeds the maximum number specified in the constructor. Splitting
      * is done such that after the split each of the new child nodes contains at
@@ -196,9 +213,7 @@ public class BTreeManager implements Tre
         }
 
         if (count == 0) {
-            Node parent = node.getParent();
-            node.remove();
-            removeRec(parent);
+            removeRec(node);
         }
     }
 
@@ -236,7 +251,7 @@ public class BTreeManager implements Tre
      * @see org.apache.jackrabbit.commons.flat.TreeManager#isLeaf(javax.jcr.Node)
      */
     public boolean isLeaf(Node node) throws RepositoryException {
-        return !node.hasNodes() && !isRoot(node);
+        return !node.hasNodes();
     }
 
     public Comparator<String> getOrder() {
@@ -265,43 +280,14 @@ public class BTreeManager implements Tre
     protected SizedIterator<Property> getProperties(Node node) throws RepositoryException {
         final PropertyIterator properties = node.getProperties();
 
-        Iterator<Property> filteredIterator = new Iterator<Property>() {
-            Property next = null;
-
-            public boolean hasNext() {
-                while (next == null && properties.hasNext()) {
-                    Property p = properties.nextProperty();
-                    try {
-                        if (!JcrConstants.JCR_PRIMARYTYPE.equals(p.getName())) {
-                            next = p;
-                        }
-                    }
-                    catch (RepositoryException ignore) {
-                        next = p;
-                    }
-                }
-
-                return next != null;
-            }
-
-            public Property next() {
-                if (hasNext()) {
-                    Property property = next;
-                    next = null;
-                    return property;
-                }
-                else {
-                    throw new NoSuchElementException();
-                }
-            }
-
-            public void remove() {
-                throw new UnsupportedOperationException();
+        long size = properties.getSize();
+        for (Iterator<String> ignored = ignoredProperties.iterator(); size > 0 && ignored.hasNext(); ) {
+            if (node.hasProperty(ignored.next())) {
+                size--;
             }
-        };
+        }
 
-        long size = properties.getSize();
-        return getSizedIterator(filteredIterator, size > 0 ? size - 1 : size);
+        return getSizedIterator(filterProperties(properties), size);
     }
 
     /**
@@ -427,6 +413,23 @@ public class BTreeManager implements Tre
         }
     }
 
+    /**
+     * Filtering ignored properties from the given properties.
+     */
+    private Iterator<Property> filterProperties(Iterator<Property> properties) {
+        return new FilterIterator<Property>(properties, new Predicate() {
+            public boolean evaluate(Object object) {
+                try {
+                    Property p = (Property) object;
+                    return !ignoredProperties.contains(p.getName());
+                }
+                catch (RepositoryException ignore) {
+                    return true;
+                }
+            }
+        });
+    }
+
     private static class WrappedRepositoryException extends RuntimeException {
         private final RepositoryException wrapped;
 

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/FilterIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/FilterIterator.java?rev=984729&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/FilterIterator.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/FilterIterator.java Thu Aug 12 11:53:20 2010
@@ -0,0 +1,76 @@
+/*
+ * 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.flat;
+
+import org.apache.jackrabbit.commons.predicate.Predicate;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Iterator filtering out items which do not match a given predicate.
+ * @param <T>
+ */
+public class FilterIterator<T> implements Iterator<T> {
+    private final Iterator<T> iterator;
+    private final Predicate predicate;
+
+    private T next = null;
+
+    /**
+     * Create a new filtered iterator based on the given <code>iterator</code>.
+     *
+     * @param iterator  iterator to filter
+     * @param predicate  only item matching this predicate are included
+     */
+    public FilterIterator(Iterator<T> iterator, Predicate predicate) {
+        super();
+        this.iterator = iterator;
+        this.predicate = predicate;
+    }
+
+    public boolean hasNext() {
+        while (next == null && iterator.hasNext()) {
+            T e = iterator.next();
+            if (predicate.evaluate(e)) {
+                next = e;
+            }
+        }
+
+        return next != null;
+    }
+
+    public T next() {
+        if (hasNext()) {
+            T e = next;
+            next = null;
+            return e;
+        }
+        else {
+            throw new NoSuchElementException();
+        }
+    }
+
+    /**
+     * @throws  UnsupportedOperationException always
+     * @see java.util.Iterator#remove()
+     */
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/FilterIterator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/FilterIterator.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/ItemSequence.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/ItemSequence.java?rev=984729&r1=984728&r2=984729&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/ItemSequence.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/ItemSequence.java Thu Aug 12 11:53:20 2010
@@ -16,8 +16,9 @@
  */
 package org.apache.jackrabbit.commons.flat;
 
-import org.apache.jackrabbit.commons.flat.TreeTraverser.ErrorHandler;
-import org.apache.jackrabbit.commons.flat.TreeTraverser.InclusionPolicy;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Set;
 
 import javax.jcr.ItemExistsException;
 import javax.jcr.Node;
@@ -28,8 +29,8 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.Value;
 
-import java.util.Comparator;
-import java.util.Iterator;
+import org.apache.jackrabbit.commons.flat.TreeTraverser.ErrorHandler;
+import org.apache.jackrabbit.commons.flat.TreeTraverser.InclusionPolicy;
 
 /**
  * <p>
@@ -173,7 +174,7 @@ public abstract class ItemSequence {
     }
 
     /**
-     * Create a new {@link NodeSequence} instance with the same parametrization
+     * Create a new {@link NodeSequence} instance with the same parameterization
      * as this instance.
      *
      * @return
@@ -359,17 +360,18 @@ public abstract class ItemSequence {
     }
 
     protected static class NodeSequenceImpl extends ItemSequence implements NodeSequence {
+        private final InclusionPolicy<Node> inclusionPolicy = new InclusionPolicy<Node>() {
+            public boolean include(Node node) throws RepositoryException {
+                return treeManager.isLeaf(node);
+            }
+        };
 
         public NodeSequenceImpl(TreeManager treeManager, ErrorHandler errorHandler)  {
             super(treeManager, errorHandler);
         }
 
         public Iterator<Node> iterator() {
-            return TreeTraverser.nodeIterator(root, errorHandler, new InclusionPolicy() {
-                public boolean include(Node node) throws RepositoryException {
-                    return treeManager.isLeaf(node);
-                }
-            });
+            return TreeTraverser.nodeIterator(root, errorHandler, inclusionPolicy);
         }
 
         public Node getItem(String key) throws RepositoryException {
@@ -442,13 +444,19 @@ public abstract class ItemSequence {
     }
 
     protected static class PropertySequenceImpl extends ItemSequence implements PropertySequence {
+        private final InclusionPolicy<Property> inclusionPolicy = new InclusionPolicy<Property>() {
+            private final Set<String> ignoredProperties = treeManager.getIgnoredProperties();
+            public boolean include(Property property) throws RepositoryException {
+                return !ignoredProperties.contains(property.getName());
+            }
+        };
 
         public PropertySequenceImpl(TreeManager treeManager, ErrorHandler errorHandler) {
             super(treeManager, errorHandler);
         }
 
         public Iterator<Property> iterator() {
-            return TreeTraverser.propertyIterator(getNodeSequence().iterator(), errorHandler);
+            return TreeTraverser.propertyIterator(getNodeSequence().iterator(), errorHandler, inclusionPolicy);
         }
 
         public Property getItem(String key) throws RepositoryException {

Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/TreeManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/TreeManager.java?rev=984729&r1=984728&r2=984729&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/TreeManager.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/TreeManager.java Thu Aug 12 11:53:20 2010
@@ -21,6 +21,7 @@ import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 
 import java.util.Comparator;
+import java.util.Set;
 
 /**
  * TreeManager instances are responsible for the mapping between sequence views
@@ -63,6 +64,12 @@ public interface TreeManager {
     boolean isLeaf(Node node) throws RepositoryException;
 
     /**
+     * Properties to ignore.
+     * @return
+     */
+    public Set<String> getIgnoredProperties();
+
+    /**
      * {@link Comparator} used for establishing the order of the keys in the
      * sequence.
      *

Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/TreeTraverser.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/TreeTraverser.java?rev=984729&r1=984728&r2=984729&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/TreeTraverser.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/flat/TreeTraverser.java Thu Aug 12 11:53:20 2010
@@ -18,6 +18,8 @@ package org.apache.jackrabbit.commons.fl
 
 import static org.apache.jackrabbit.commons.iterator.LazyIteratorChain.chain;
 
+import org.apache.jackrabbit.commons.predicate.Predicate;
+
 import javax.jcr.Item;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
@@ -51,7 +53,7 @@ import java.util.Iterator;
 public final class TreeTraverser implements Iterable<Node> {
     private final Node root;
     private final ErrorHandler errorHandler;
-    private final InclusionPolicy inclusionPolicy;
+    private final InclusionPolicy<? super Node> inclusionPolicy;
 
     /**
      * Create a new instance of a TreeTraverser rooted at <code>node</code>.
@@ -61,7 +63,7 @@ public final class TreeTraverser impleme
      * @param inclusionPolicy Inclusion policy to determine which nodes to
      *            include
      */
-    public TreeTraverser(Node root, ErrorHandler errorHandler, InclusionPolicy inclusionPolicy) {
+    public TreeTraverser(Node root, ErrorHandler errorHandler, InclusionPolicy<? super Node> inclusionPolicy) {
         super();
         this.root = root;
         this.errorHandler = errorHandler == null? ErrorHandler.IGNORE : errorHandler;
@@ -103,45 +105,45 @@ public final class TreeTraverser impleme
     }
 
     /**
-     * Inclusion policy to determine which nodes to include when traversing.
+     * Inclusion policy to determine which itmes to include when traversing.
      * There a two predefined inclusion policies:
      * <ul>
-     * <li>{@link #ALL} includes all nodes.</li>
+     * <li>{@link #ALL} includes all items.</li>
      * <li>{@link #LEAVES} includes only leave nodes. A leaf node is a node
-     * which does not have childe nodes.</li>
+     * which does not have child nodes.</li>
      * </ul>
      */
-    public interface InclusionPolicy {
+    public interface InclusionPolicy<T extends Item> {
 
         /**
-         * This inclusions policy includes all nodes.
+         * This inclusions policy includes all items.
          */
-        public static InclusionPolicy ALL = new InclusionPolicy() {
-            public boolean include(Node node) {
+        public static InclusionPolicy<Item> ALL = new InclusionPolicy<Item>() {
+            public boolean include(Item item) {
                 return true;
             }
         };
 
         /**
-         * This inclusion policy only includes leave nodes. A leaf node is a
-         * node which does not have child nodes.
+         * This inclusion policy includes leave nodes only. A leaf
+         * node is a node which does not have child nodes.
          */
-        public static InclusionPolicy LEAVES = new InclusionPolicy() {
+        public static InclusionPolicy<Node> LEAVES = new InclusionPolicy<Node>() {
             public boolean include(Node node) throws RepositoryException {
                 return !node.hasNodes();
             }
         };
 
         /**
-         * Call back method to determine whether to include a given node.
+         * Call back method to determine whether to include a given item.
          *
-         * @param node The node under consideration
-         * @return <code>true</code> when <code>node</code> should be included.
+         * @param item The item under consideration
+         * @return <code>true</code> when <code>item</code> should be included.
          *         <code>false</code> otherwise.
          *
          * @throws RepositoryException
          */
-        boolean include(Node node) throws RepositoryException;
+        boolean include(T item) throws RepositoryException;
     }
 
     /**
@@ -155,7 +157,7 @@ public final class TreeTraverser impleme
      * @return iterator of {@link Node}
      */
     public static Iterator<Node> nodeIterator(Node root, ErrorHandler errorHandler,
-            InclusionPolicy inclusionPolicy) {
+            InclusionPolicy<? super Node> inclusionPolicy) {
 
         return new TreeTraverser(root, errorHandler, inclusionPolicy).iterator();
     }
@@ -180,12 +182,17 @@ public final class TreeTraverser impleme
      *
      * @param nodes nodes whose properties to chain
      * @param errorHandler handler for exceptions occurring on traversal
+     * @param inclusionPolicy inclusion policy to determine properties items to include
+     *
      * @return iterator of {@link Property}
      */
-    public static Iterator<Property> propertyIterator(Iterator<Node> nodes, ErrorHandler errorHandler) {
-        return chain(propertyIterators(nodes, errorHandler));
+    public static Iterator<Property> propertyIterator(Iterator<Node> nodes, ErrorHandler errorHandler,
+            InclusionPolicy<? super Property> inclusionPolicy) {
+
+        return filter(chain(propertyIterators(nodes, errorHandler)), inclusionPolicy);
     }
 
+
     /**
      * Create an iterator of the properties for a given iterator of nodes. The
      * order of the returned properties is only specified so far that if node
@@ -198,7 +205,7 @@ public final class TreeTraverser impleme
      * @return iterator of {@link Property}
      */
     public static Iterator<Property> propertyIterator(Iterator<Node> nodes) {
-        return propertyIterator(nodes, ErrorHandler.IGNORE);
+        return propertyIterator(nodes, ErrorHandler.IGNORE, InclusionPolicy.ALL);
     }
 
     /**
@@ -207,14 +214,15 @@ public final class TreeTraverser impleme
      *
      * @param root root node of the sub-tree to traverse
      * @param errorHandler handler for exceptions occurring on traversal
-     * @param inclusionPolicy inclusion policy to determine which nodes to
+     * @param inclusionPolicy inclusion policy to determine which items to
      *            include
      * @return iterator of {@link Property}
      */
     public static Iterator<Property> propertyIterator(Node root, ErrorHandler errorHandler,
-            InclusionPolicy inclusionPolicy) {
+            InclusionPolicy<Item> inclusionPolicy) {
 
-        return propertyIterator(nodeIterator(root, errorHandler, inclusionPolicy), errorHandler);
+        return propertyIterator(nodeIterator(root, errorHandler, inclusionPolicy), errorHandler,
+                inclusionPolicy);
     }
 
     /**
@@ -323,5 +331,24 @@ public final class TreeTraverser impleme
         return Collections.singleton(value).iterator();
     }
 
+    /**
+     * Filtering items not matching the <code>inclusionPolicy</code> from
+     * <code>iterator</code>.
+     */
+    private static <T extends Item> Iterator<T> filter(final Iterator<T> iterator,
+            final InclusionPolicy<? super T> inclusionPolicy) {
+
+        return new FilterIterator<T>(iterator, new Predicate() {
+            @SuppressWarnings("unchecked")
+            public boolean evaluate(Object object) {
+                try {
+                    return inclusionPolicy.include((T) object);
+                }
+                catch (RepositoryException ignore) {
+                    return true;
+                }
+            }
+        });
+    }
 
 }