Skip to content

Commit

Permalink
Merge pull request #540 from fcrepo4/mark-pairtree-objects
Browse files Browse the repository at this point in the history
Mark intermediate nodes as pairtree elements
  • Loading branch information
Andrew Woods committed Oct 15, 2014
2 parents 0206da1 + 14803df commit c515a0c
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 19 deletions.
Expand Up @@ -18,11 +18,65 @@
import org.fcrepo.kernel.services.Service;
import org.modeshape.jcr.api.JcrTools;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import static org.fcrepo.jcr.FedoraJcrTypes.FEDORA_PAIRTREE;
import static org.modeshape.jcr.api.JcrConstants.NT_FOLDER;


/**
* @author bbpennel
* @since Feb 20, 2014
*/
public abstract class AbstractService implements Service {
protected final static JcrTools jcrTools = new JcrTools();

protected Node findOrCreateNode(final Session session,
final String path,
final String finalNodeType) throws RepositoryException {

final Node preexistingNode = getClosestPreexistingNode(session, path);

final Node node = jcrTools.findOrCreateNode(session, path, NT_FOLDER, finalNodeType);

if (node.isNew()) {
tagHierarchyWithPairtreeMixin(preexistingNode, node);
}

return node;
}

private void tagHierarchyWithPairtreeMixin(final Node baseNode,
final Node createdNode) throws RepositoryException {
Node parent = createdNode.getParent();

while (parent.isNew() && !parent.equals(baseNode)) {
parent.addMixin(FEDORA_PAIRTREE);
parent = parent.getParent();
}
}

private Node getClosestPreexistingNode(final Session session,
final String path) throws RepositoryException {
final String[] pathSegments = path.replaceAll("^/+", "").replaceAll("/+$", "").split("/");

Node node = session.getRootNode();

final int len = pathSegments.length;
for (int i = 0; i != len; ++i) {
final String pathSegment = pathSegments[i];

if (node.hasNode(pathSegment)) {
// Find the existing node ...
node = node.getNode(pathSegment);
} else {
return node;
}

}

return node;
}
}
Expand Up @@ -32,7 +32,6 @@
import static org.fcrepo.jcr.FedoraJcrTypes.FEDORA_RESOURCE;
import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT;
import static org.modeshape.jcr.api.JcrConstants.NT_FILE;
import static org.modeshape.jcr.api.JcrConstants.NT_FOLDER;
import static org.modeshape.jcr.api.JcrConstants.NT_RESOURCE;
import static org.slf4j.LoggerFactory.getLogger;

Expand All @@ -55,7 +54,7 @@ public class BinaryServiceImpl extends AbstractService implements BinaryService
@Override
public FedoraBinary findOrCreateBinary(final Session session, final String path) {
try {
final Node dsNode = jcrTools.findOrCreateNode(session, path, NT_FOLDER, NT_FILE);
final Node dsNode = findOrCreateNode(session, path, NT_FILE);

if (dsNode.isNew()) {
initializeNewDatastreamProperties(dsNode);
Expand Down
Expand Up @@ -54,7 +54,7 @@ public FedoraObject findOrCreateObject(final Session session, final String path)
LOGGER.trace("Executing findOrCreateObject() with path: {}", path);

try {
final Node node = jcrTools.findOrCreateNode(session, path, NT_FOLDER, NT_FOLDER);
final Node node = findOrCreateNode(session, path, NT_FOLDER);

if (node.isNew()) {
initializeNewObjectProperties(node);
Expand Down
2 changes: 2 additions & 0 deletions fcrepo-kernel-impl/src/main/resources/fedora-node-types.cnd
Expand Up @@ -124,3 +124,5 @@
- fedora:digest (URI) COPY

[fedora:blanknode] > mix:referenceable mixin

[fedora:pairtree] mixin
Expand Up @@ -55,6 +55,8 @@ public void setUp() throws RepositoryException {
testObj = new BinaryServiceImpl();
when(mockSession.getRootNode()).thenReturn(mockRoot);
when(mockDsNode.getNode(JCR_CONTENT)).thenReturn(mockNode);
when(mockDsNode.getParent()).thenReturn(mockRoot);
when(mockRoot.isNew()).thenReturn(false);
}

@Test
Expand Down
Expand Up @@ -16,7 +16,8 @@
package org.fcrepo.kernel.impl.services;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.modeshape.jcr.api.JcrConstants.NT_FOLDER;
Expand Down Expand Up @@ -50,6 +51,9 @@ public class ObjectServiceImplTest implements FedoraJcrTypes {
@Mock
private Node mockNode;

@Mock
private Node mockParent;

@Mock
private NodeType mockNodeType;

Expand All @@ -66,32 +70,48 @@ public void setUp() throws RepositoryException {
testObj = new ObjectServiceImpl();
when(mockSession.getRootNode()).thenReturn(mockRoot);
when(mockRoot.getNode(testPath.substring(1))).thenReturn(mockNode);
when(mockNode.getParent()).thenReturn(mockRoot);
when(mockRoot.isNew()).thenReturn(false);
}

@Test
public void testCreateObject() throws Exception {
when(mockNodeType.getName()).thenReturn(FEDORA_OBJECT);
final NodeType mockNodeType = mock(NodeType.class);
when(mockNodeType.getName()).thenReturn("nt:folder");
when(mockNode.getPrimaryNodeType()).thenReturn(mockNodeType);
when(mockNode.getMixinNodeTypes()).thenReturn(
new NodeType[] {mockNodeType});
final Node actual = testObj.findOrCreateObject(mockSession, testPath).getNode();
assertEquals(mockNode, actual);
}

@Test
public void testCreateObjectWithHierarchy() throws Exception {
when(mockNode.getParent()).thenReturn(mockParent);
when(mockParent.getParent()).thenReturn(mockRoot);
when(mockParent.isNew()).thenReturn(true);
when(mockRoot.getNode("foo/bar")).thenReturn(mockNode);
when(mockNode.isNew()).thenReturn(true);

final Node actual =
testObj.findOrCreateObject(mockSession, testPath).getNode();
testObj.findOrCreateObject(mockSession, "/foo/bar").getNode();
assertEquals(mockNode, actual);
verify(mockParent).addMixin(FedoraJcrTypes.FEDORA_PAIRTREE);
}

@Test
public void testGetObject() throws RepositoryException {
when(mockNodeType.getName()).thenReturn(FEDORA_OBJECT);
final NodeType mockNodeType = mock(NodeType.class);
when(mockNodeType.getName()).thenReturn("nt:folder");
when(mockNode.isNew()).thenReturn(false);
when(mockNode.getPrimaryNodeType()).thenReturn(mockNodeType);
when(mockNode.getMixinNodeTypes()).thenReturn(
new NodeType[] {mockNodeType});
public void testCreateObjectWithExistingHierarchy() throws Exception {
when(mockNode.getParent()).thenReturn(mockParent);
when(mockParent.getParent()).thenReturn(mockRoot);
when(mockParent.isNew()).thenReturn(false);
when(mockRoot.hasNode("foo")).thenReturn(true);
when(mockRoot.getNode("foo")).thenReturn(mockParent);
when(mockRoot.getNode("foo/bar")).thenReturn(mockNode);
when(mockNode.isNew()).thenReturn(true);

final Node actual = testObj.findOrCreateObject(mockSession, "/foo/bar").getNode();
assertEquals(mockNode, actual);
verify(mockParent, never()).addMixin(FedoraJcrTypes.FEDORA_PAIRTREE);
}


@Test
public void testGetObject() throws RepositoryException {
final String testPath = "/foo";
when(mockSession.getNode(testPath)).thenReturn(mockNode);
when(mockJcrTools.findOrCreateNode(mockSession, "/foo", NT_FOLDER, NT_FOLDER)).thenReturn(mockNode);
Expand Down
Expand Up @@ -31,6 +31,8 @@ public interface FedoraJcrTypes {

String FEDORA_BINARY = "fedora:binary";

String FEDORA_PAIRTREE = "fedora:pairtree";

String LDP_CONTAINER = "ldp:Container";

String JCR_LASTMODIFIED = "jcr:lastModified";
Expand Down

0 comments on commit c515a0c

Please sign in to comment.