/*
* 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.integration;
import static org.apache.jackrabbit.spi.commons.iterator.Iterators.filterIterator;
import static org.apache.jackrabbit.spi.commons.iterator.Iterators.singleton;
import static org.apache.jackrabbit.spi.commons.iterator.Iterators.transformIterator;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.commons.flat.TreeTraverser;
import org.apache.jackrabbit.spi.commons.iterator.Iterators;
import org.apache.jackrabbit.spi.commons.iterator.Predicate;
import org.apache.jackrabbit.spi.commons.iterator.Transformer;
import org.apache.jackrabbit.test.AbstractJCRTest;
import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeType;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import junit.framework.AssertionFailedError;
public class TreeTraverserTest extends AbstractJCRTest {
private Node testNode;
private final TreeTraverser.ErrorHandler errorHandler = new TreeTraverser.ErrorHandler() {
public void call(Item item, RepositoryException exception) {
throw (AssertionFailedError) new AssertionFailedError().initCause(exception);
}
};
private final List<String> nodes = Arrays.asList(
"",
"a",
"a/b",
"a/a",
"a/c",
"b",
"c",
"d",
"d/a",
"d/a/b",
"d/a/b/c",
"d/a/b/c/d",
"d/a/b/c/d/e",
"d/a/b/c/d/e/f",
"e"
);
private final Set<String> properties = new HashSet<String>() {{
add("v");
add("w");
add("x");
add("a/v");
add("a/w");
add("a/x");
add("a/a/a");
add("d/a/b/c/d/e/f/q");
}};
private final List<String> leaves = new LinkedList<String>();
@Override
public void setUp() throws Exception {
super.setUp();
testNode = testRootNode.addNode("TreeTraverserTest", NodeType.NT_UNSTRUCTURED);
superuser.save();
// Determine leave nodes
outer:
for (String node : nodes) {
for (String other : nodes) {
if (other.startsWith(node) && !other.equals(node)) {
continue outer;
}
}
leaves.add(node);
}
}
public void testTraverseNodesEmpty() throws RepositoryException {
TreeTraverser traverser = new TreeTraverser(testNode, errorHandler, TreeTraverser.InclusionPolicy.ALL);
checkNodes(traverser, singleton(""), testNode.getPath());
}
public void testTraverseLeavesEmpty() throws RepositoryException {
TreeTraverser traverser = new TreeTraverser(testNode, errorHandler, TreeTraverser.InclusionPolicy.LEAVES);
checkNodes(traverser, singleton(""), testNode.getPath());
}
public void testTraverseNodes() throws RepositoryException {
addNodes(testNode, nodes);
TreeTraverser traverser = new TreeTraverser(testNode, errorHandler, TreeTraverser.InclusionPolicy.ALL);
checkNodes(traverser, nodes.iterator(), testNode.getPath());
}
public void testTraverseLeaves() throws RepositoryException {
addNodes(testNode, nodes);
TreeTraverser traverser = new TreeTraverser(testNode, errorHandler, TreeTraverser.InclusionPolicy.LEAVES);
checkNodes(traverser, leaves.iterator(), testNode.getPath());
}
public void testTraversePropertiesEmpty() throws RepositoryException {
Iterator<Node> nodeIt = TreeTraverser.nodeIterator(testNode);
Iterator<Property> propertyIt = TreeTraverser.propertyIterator(nodeIt);
checkProperties(propertyIt, Iterators.<String>empty(), testNode.getPath());
addNodes(testNode, nodes);
checkProperties(propertyIt, Iterators.<String>empty(), testNode.getPath());
}
public void testTraverseProperties() throws RepositoryException {
addNodes(testNode, nodes);
addProperties(testNode, properties);
Iterator<Node> nodeIt = TreeTraverser.nodeIterator(testNode);
Iterator<Property> propertyIt = TreeTraverser.propertyIterator(nodeIt);
checkProperties(propertyIt, properties.iterator(), testNode.getPath());
}
// -----------------------------------------------------< internal >---
private static void addNodes(Node root, Iterable<String> nodes) throws RepositoryException {
for (String name : nodes) {
if (!"".equals(name)) {
root.addNode(name);
}
}
root.getSession().save();
}
private static void addProperties(Node root, Iterable<String> properties) throws RepositoryException {
for (String name : properties) {
int i = name.lastIndexOf('/');
Node n;
String propName;
if (i <= 0) {
n = root;
propName = name;
}
else {
n = root.getNode(name.substring(0, i));
propName = name.substring(i + 1);
}
n.setProperty(propName, propName + " value");
}
root.getSession().save();
}
private static void checkNodes(TreeTraverser treeTraverser, Iterator<String> expectedNodes, String pathPrefix)
throws RepositoryException {
for (Node node : treeTraverser) {
assertTrue("No more nodes. Expected " + node, expectedNodes.hasNext());
assertEquals(cat(pathPrefix, expectedNodes.next()), node.getPath());
}
assertFalse(expectedNodes.hasNext());
}
private static void checkProperties(Iterator<Property> actualProperties,
Iterator<String> expectedProperties, String pathPrefix) {
List<String> actualPaths = toList(property2Path(removeIgnored(actualProperties)));
List<String> expectedPaths = toList(cat(pathPrefix, expectedProperties));
Collections.sort(actualPaths);
Collections.sort(expectedPaths);
assertEquals(expectedPaths, actualPaths);
}
private static Iterator<Property> removeIgnored(Iterator<Property> properties) {
return filterIterator(properties, new Predicate<Property>() {
public boolean evaluate(Property property) {
try {
return !JcrConstants.JCR_PRIMARYTYPE.equals(property.getName());
}
catch (RepositoryException e) {
throw (AssertionFailedError) new AssertionFailedError().initCause(e);
}
}
});
}
private static Iterator<String> property2Path(Iterator<Property> properties) {
return transformIterator(properties, new Transformer<Property, String>() {
public String transform(Property property) {
try {
return property.getPath();
}
catch (RepositoryException e) {
throw (AssertionFailedError) new AssertionFailedError().initCause(e);
}
}
});
}
private static <T> List<T> toList(Iterator<T> iterator) {
List<T> list = new LinkedList<T>();
while (iterator.hasNext()) {
list.add(iterator.next());
}
return list;
}
private static String cat(String s1, String s2) {
if ("".equals(s2)) {
return s1;
}
else {
return s1 + "/" + s2;
}
}
private static Iterator<String> cat(final String s, Iterator<String> strings) {
return transformIterator(strings, new Transformer<String, String>() {
public String transform(String string) {
return cat(s, string);
}
});
}
}