Index: jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/DeepNodeCreatorTest.java =================================================================== --- jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/DeepNodeCreatorTest.java (revision 0) +++ jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/DeepNodeCreatorTest.java (revision 0) @@ -0,0 +1,160 @@ +/* + * 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.util; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; + +import java.util.concurrent.atomic.AtomicInteger; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.jackrabbit.JcrConstants; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.junit.Test; + +/** Test the DeepNodeCreator class */ +public class DeepNodeCreatorTest { + + @Test + public void testExistingNode() throws Exception { + final Mockery mockery = new Mockery(); + final DeepNodeCreator c = new DeepNodeCreator(); + final String path = "/foo/bar"; + final Session s = mockery.mock(Session.class); + final Node n = mockery.mock(Node.class); + + mockery.checking(new Expectations() {{ + allowing(s).itemExists(path); + will(returnValue(true)); + + allowing(s).getItem(path); + will(returnValue(n)); + + allowing(n).isNode(); + will(returnValue(true)); + }}); + + final Node result = c.deepCreateNode(path, s, null); + assertTrue("Expecting deepCreate to return existing node", result == n); + } + + public void testCreateFromRoot() throws Exception { + final Mockery mockery = new Mockery(); + final DeepNodeCreator c = new DeepNodeCreator(); + final String rootPath = "/"; + final String fooPath = "/foo"; + final String barPath = "/foo/bar"; + final Session s = mockery.mock(Session.class); + final Node root = mockery.mock(Node.class, rootPath); + final Node foo = mockery.mock(Node.class, fooPath); + final Node bar = mockery.mock(Node.class, barPath); + final String testNodeType = "NT_TEST"; + + mockery.checking(new Expectations() {{ + allowing(s).itemExists(barPath); + will(returnValue(false)); + + allowing(s).itemExists(fooPath); + will(returnValue(false)); + + allowing(s).itemExists(rootPath); + will(returnValue(true)); + + allowing(s).getItem(rootPath); + will(returnValue(root)); + + allowing(root).isNode(); + will(returnValue(true)); + + allowing(root).addNode("foo", testNodeType); + will(returnValue(foo)); + + allowing(foo).addNode("bar", testNodeType); + will(returnValue(bar)); + + allowing(s).save(); + }}); + + final Node result = c.deepCreateNode(barPath, s, testNodeType); + assertTrue("Expecting deepCreate to return create node", result == bar); + } + + public void testCreateWithVariousTypes() throws Exception { + final Mockery mockery = new Mockery(); + + final String fooPath = "/foo"; + final String barPath = "/foo/bar"; + final String wiiPath = "/foo/bar/wii"; + final Session s = mockery.mock(Session.class); + final Node foo = mockery.mock(Node.class, fooPath); + final Node bar = mockery.mock(Node.class, barPath); + final Node wii = mockery.mock(Node.class, wiiPath); + + mockery.checking(new Expectations() {{ + allowing(s).itemExists(wiiPath); + will(returnValue(false)); + + allowing(s).itemExists(barPath); + will(returnValue(false)); + + allowing(s).itemExists(fooPath); + will(returnValue(true)); + + allowing(s).getItem(fooPath); + will(returnValue(foo)); + + allowing(foo).isNode(); + will(returnValue(true)); + + allowing(foo).getPath(); + will(returnValue(fooPath)); + + allowing(foo).addNode("bar", "NT_/foo.bar"); + will(returnValue(bar)); + + allowing(bar).getPath(); + will(returnValue(barPath)); + + allowing(bar).addNode("wii", "NT_/foo/bar.wii"); + will(returnValue(wii)); + + allowing(s).save(); + }}); + + final AtomicInteger counter = new AtomicInteger(); + final DeepNodeCreator c = new DeepNodeCreator() { + + @Override + protected String getNodeType(Node parent, String childPath, String suggestedNodeType) + throws RepositoryException { + return "NT_" + parent.getPath() + "." + childPath; + } + + @Override + protected void nodeCreated(Node n) throws RepositoryException { + counter.addAndGet(1); + } + }; + final Node result = c.deepCreateNode(wiiPath, s, null); + assertTrue("Expecting deepCreate to return created node", result == wii); + assertEquals("Expecting correct count of nodeCreated calls", 2, counter.get()); + } +} Property changes on: jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/DeepNodeCreatorTest.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Rev URL Added: svn:eol-style + native Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/DeepNodeCreator.java =================================================================== --- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/DeepNodeCreator.java (revision 0) +++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/DeepNodeCreator.java (revision 0) @@ -0,0 +1,74 @@ +/* + * 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.util; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +/** + * Deep-creation of nodes: parent nodes are created if needed. + */ +public class DeepNodeCreator { + + /** Create a node, also creating parent nodes as needed + * @param path Path of the node to create + * @param session Used to create nodes + * @param nodeType Node type of created nodes, can be + * overridden via {@link #getNodeType} + * @return The created node + * @throws RepositoryException In case of problems + */ + public Node deepCreateNode(String path, Session session, String nodeType) + throws RepositoryException { + Node result = null; + if (session.itemExists(path)) { + final Item it = session.getItem(path); + if (it.isNode()) { + result = (Node) it; + } + } else { + final int slashPos = path.lastIndexOf("/"); + String parentPath = path.substring(0, slashPos); + if(parentPath.length() == 0) { + parentPath = "/"; + } + final String childPath = path.substring(slashPos + 1); + final Node parent = deepCreateNode(parentPath, session, nodeType); + result = parent.addNode(childPath, getNodeType(parent, childPath, nodeType)); + nodeCreated(result); + session.save(); + } + return result; + } + + /** Can be overridden to return a specific nodetype to use at a given path. + * @param parent the parent of the node that is being created + * @param childPath the path of the child that is being created + * @param suggestedNodeType the nodeType value passed to {@link deepCreateNode} + * @return suggestedNodeType by default + */ + protected String getNodeType(Node parent, String childPath, String suggestedNodeType) + throws RepositoryException { + return suggestedNodeType; + } + + /** Can be overridden to customize the created nodes, add mixins etc. */ + protected void nodeCreated(Node n) throws RepositoryException { + } +} Property changes on: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/DeepNodeCreator.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Rev URL Added: svn:eol-style + native Index: jackrabbit-jcr-commons/pom.xml =================================================================== --- jackrabbit-jcr-commons/pom.xml (revision 967083) +++ jackrabbit-jcr-commons/pom.xml (working copy) @@ -71,6 +71,12 @@ json test + + org.jmock + jmock-junit4 + 2.5.1 + test + - + \ No newline at end of file