Navigation Menu

Skip to content

Commit

Permalink
Add capability to map node-types to RDF triples
Browse files Browse the repository at this point in the history
  • Loading branch information
ajs6f authored and Andrew Woods committed Oct 25, 2013
1 parent d9b2b2f commit e18ddb8
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 40 deletions.
Expand Up @@ -37,7 +37,6 @@
import javax.jcr.RepositoryException;

import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.rdf.NodeRdfContext;
import org.fcrepo.kernel.services.LowLevelStorageService;
import org.fcrepo.kernel.utils.FixityResult;

Expand Down
Expand Up @@ -44,7 +44,6 @@
import javax.jcr.RepositoryException;

import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.rdf.NodeRdfContext;
import org.fcrepo.kernel.services.LowLevelStorageService;
import org.fcrepo.kernel.utils.JcrRdfTools;
import org.fcrepo.kernel.utils.iterators.NodeIterator;
Expand Down
Expand Up @@ -14,21 +14,38 @@
* limitations under the License.
*/

package org.fcrepo.kernel.rdf;
package org.fcrepo.kernel.rdf.impl;

import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterators.forArray;
import static com.google.common.collect.Iterators.transform;
import static com.hp.hpl.jena.graph.NodeFactory.createURI;
import static com.hp.hpl.jena.graph.Triple.create;
import static com.hp.hpl.jena.vocabulary.RDF.type;
import static org.fcrepo.kernel.utils.JcrRdfTools.getRDFNamespaceForJcrNamespace;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.Iterator;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeType;

import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.services.LowLevelStorageService;
import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.slf4j.Logger;

import com.google.common.base.Function;
import com.hp.hpl.jena.graph.Triple;

/**
* {@link RdfStream} that holds contexts related to a specific {@link Node}.
*
* @author ajs6f
* @date Oct 10, 2013
*/
public abstract class NodeRdfContext extends RdfStream {
public class NodeRdfContext extends RdfStream {

private final Node node;

Expand All @@ -38,22 +55,29 @@ public abstract class NodeRdfContext extends RdfStream {

private final LowLevelStorageService lowLevelStorageService;

private static final Logger LOGGER = getLogger(NodeRdfContext.class);

/**
* Default constructor.
*
* @param node
* @param graphSubjects
* @throws RepositoryException
*/
public NodeRdfContext(final Node node, final GraphSubjects graphSubjects, final LowLevelStorageService lowLevelStorageService) throws RepositoryException {
public NodeRdfContext(final Node node, final GraphSubjects graphSubjects,
final LowLevelStorageService lowLevelStorageService)
throws RepositoryException {
super();
this.node = node;
this.graphSubjects = graphSubjects;
this.subject = graphSubjects.getGraphSubject(node).asNode();

// TODO fix GraphProperties to allow for LowLevelStorageServices to pass through it
// this is horribly ugly. LowLevelStorageServices are supposed to be managed beans.
// but the contract of GraphProperties isn't wide enough to pass one in, so rather than
// TODO fix GraphProperties to allow for LowLevelStorageServices to pass
// through it
// this is horribly ugly. LowLevelStorageServices are supposed to be
// managed beans.
// but the contract of GraphProperties isn't wide enough to pass one in,
// so rather than
// alter GraphProperties right now, I'm just spinning one on the fly.
if (lowLevelStorageService == null) {
this.lowLevelStorageService = new LowLevelStorageService();
Expand All @@ -62,6 +86,10 @@ public NodeRdfContext(final Node node, final GraphSubjects graphSubjects, final
} else {
this.lowLevelStorageService = lowLevelStorageService;
}

// add JCR mixins as rdf:type triples
final Iterator<NodeType> nodeTypes = forArray(node.getMixinNodeTypes());
concat(transform(nodeTypes, nodetype2triple()));
}

/**
Expand Down Expand Up @@ -92,4 +120,34 @@ public LowLevelStorageService lowLevelStorageService() {
return lowLevelStorageService;
}

private final Function<NodeType, Triple> nodetype2triple() {
return new Function<NodeType, Triple>() {

@Override
public Triple apply(final NodeType nodeType) {
try {
final String fullTypeName = nodeType.getName();
LOGGER.debug("Translating JCR mixin name: {}", fullTypeName);
final String prefix = fullTypeName.split(":")[0];
final String typeName = fullTypeName.split(":")[1];
final String namespace = getJcrUri(prefix);
LOGGER.debug("with JCR namespace: {}", namespace);
final com.hp.hpl.jena.graph.Node rdfType =
createURI(getRDFNamespaceForJcrNamespace(namespace)
+ typeName);
LOGGER.debug("into RDF resource: {}", rdfType);
return create(subject(), type.asNode(), rdfType);
} catch (final RepositoryException e) {
throw propagate(e);
}
}

};
}

private String getJcrUri(final String prefix) throws RepositoryException {
return node().getSession().getWorkspace().getNamespaceRegistry()
.getURI(prefix);
}

}
Expand Up @@ -34,7 +34,6 @@
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.rdf.NodeRdfContext;
import org.fcrepo.kernel.rdf.impl.mappings.PropertyToTriple;
import org.fcrepo.kernel.rdf.impl.mappings.ZippingIterator;
import org.fcrepo.kernel.services.LowLevelStorageService;
Expand Down
Expand Up @@ -44,7 +44,6 @@
import javax.jcr.nodetype.NodeTypeManager;

import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.rdf.NodeRdfContext;
import org.fcrepo.kernel.services.LowLevelStorageService;
import org.fcrepo.kernel.services.functions.GetClusterConfiguration;
import org.modeshape.jcr.JcrRepository;
Expand Down
Expand Up @@ -31,7 +31,6 @@
import javax.jcr.version.VersionManager;

import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.rdf.NodeRdfContext;
import org.fcrepo.kernel.services.LowLevelStorageService;
import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.fcrepo.kernel.utils.iterators.VersionIterator;
Expand Down
Expand Up @@ -182,7 +182,9 @@ public void setUp() throws RepositoryException {
when(mockParentNode.getPrimaryNodeType()).thenReturn(mockNodeType);
when(mockNodeType.getName()).thenReturn("not:root");
when(mockNode.getMixinNodeTypes()).thenReturn(new NodeType[] {});
when(mockParentNode.getMixinNodeTypes()).thenReturn(new NodeType[] {});
when(mockNode.getPath()).thenReturn(MOCK_NODE_PATH);
when(mockNode.getMixinNodeTypes()).thenReturn(new NodeType[]{});
when(mockParentNode.getPath()).thenReturn(MOCK_PARENT_NODE_PATH);
when(mockNode.getParent()).thenReturn(mockParentNode);
when(mockNode.getNodes()).thenReturn(mockNodes);
Expand Down
@@ -0,0 +1,125 @@
/**
* Copyright 2013 DuraSpace, Inc.
*
* Licensed 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.fcrepo.kernel.rdf.impl;

import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
import static com.hp.hpl.jena.vocabulary.RDF.type;
import static org.fcrepo.kernel.RdfLexicon.REPOSITORY_NAMESPACE;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.slf4j.LoggerFactory.getLogger;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;

import javax.jcr.NamespaceRegistry;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Workspace;
import javax.jcr.nodetype.NodeType;

import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.services.LowLevelStorageService;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.slf4j.Logger;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Resource;

public class NodeRdfContextTest {

@Mock
private Node mockNode;

@Mock
private NodeType mockNodeType;

@Mock
private GraphSubjects mockGraphSubjects;

@Mock
private Session mockSession;

@Mock
private Repository mockRepository;

@Mock
private LowLevelStorageService mockLowLevelStorageService;

@Mock
private NamespaceRegistry mockNamespaceRegistry;

@Mock
private Workspace mockWorkspace;

private static final String mockNodeName = "mockNode";

private static final String mockNodeTypePrefix = "jcr";

private static final String mockNodeTypeName = "someType";

private static final Resource mockNodeSubject = createResource();

private static final String jcrNamespace = "http://www.jcp.org/jcr/1.0";

@Before
public void setUp() throws RepositoryException {
initMocks(this);
when(mockNode.getPrimaryNodeType()).thenReturn(mockNodeType);
when(mockNodeType.getName()).thenReturn(
mockNodeTypePrefix + ":" + mockNodeTypeName);
when(mockNode.getName()).thenReturn(mockNodeName);
when(mockNode.getMixinNodeTypes()).thenReturn(
new NodeType[] {mockNodeType});
when(mockNode.getSession()).thenReturn(mockSession);
when(mockSession.getRepository()).thenReturn(mockRepository);
when(mockSession.getWorkspace()).thenReturn(mockWorkspace);
when(mockWorkspace.getNamespaceRegistry()).thenReturn(mockNamespaceRegistry);
when(mockNamespaceRegistry.getURI("jcr")).thenReturn(jcrNamespace);
when(mockGraphSubjects.getGraphSubject(mockNode)).thenReturn(
mockNodeSubject);
}

@Test
public void testIncludesMixinTriples() throws RepositoryException,
IOException {
final Model actual =
new NodeRdfContext(mockNode, mockGraphSubjects, mockLowLevelStorageService).asModel();
final Resource expectedRdfType =
createResource(REPOSITORY_NAMESPACE + mockNodeTypeName);
logRdf("Constructed RDF: ", actual);
assertTrue("Didn't find RDF type triple for mixin!", actual.contains(
mockNodeSubject, type, expectedRdfType));
}

private void logRdf(final String message, final Model model) throws IOException {
LOGGER.debug(message);
try (Writer w = new StringWriter()) {
model.write(w);
LOGGER.debug("\n" + w.toString());
}
}

private static final Logger LOGGER = getLogger(NodeRdfContextTest.class);

}
Expand Up @@ -74,6 +74,8 @@ public void setUp() throws RepositoryException {
when(mockNode.hasNode(JCR_CONTENT)).thenReturn(true);
when(mockNode.getNode(JCR_CONTENT)).thenReturn(mockContentNode);
when(mockNode.hasProperties()).thenReturn(false);
when(mockNode.getMixinNodeTypes()).thenReturn(new NodeType[] {});
when(mockContentNode.getMixinNodeTypes()).thenReturn(new NodeType[] {});
when(mockContentNode.hasProperties()).thenReturn(false);
when(
mockLowLevelStorageService
Expand Down

0 comments on commit e18ddb8

Please sign in to comment.