Skip to content

Commit

Permalink
Add support for LDP IsMemberOfRelation
Browse files Browse the repository at this point in the history
  • Loading branch information
cbeer committed Oct 7, 2014
1 parent dd934f7 commit 8a0681a
Show file tree
Hide file tree
Showing 6 changed files with 309 additions and 0 deletions.
Expand Up @@ -33,6 +33,7 @@
import org.fcrepo.kernel.impl.rdf.impl.ChildrenRdfContext;
import org.fcrepo.kernel.impl.rdf.impl.ContainerRdfContext;
import org.fcrepo.kernel.impl.rdf.impl.LdpContainerRdfContext;
import org.fcrepo.kernel.impl.rdf.impl.LdpIsMemberOfRdfContext;
import org.fcrepo.kernel.impl.rdf.impl.ParentRdfContext;
import org.fcrepo.kernel.impl.rdf.impl.PropertiesRdfContext;
import org.fcrepo.kernel.impl.rdf.impl.ReferencesRdfContext;
Expand Down Expand Up @@ -167,6 +168,7 @@ protected RdfStream getResourceTriples(final PreferTag returnPreference) {

if (ldpPreferences.prefersMembership()) {
rdfStream.concat(getTriples(LdpContainerRdfContext.class));
rdfStream.concat(getTriples(LdpIsMemberOfRdfContext.class));
}

if (ldpPreferences.prefersEmbed()) {
Expand Down
Expand Up @@ -312,6 +312,7 @@ public String apply(final RDFNode input) {
});
assertTrue("Expected RDF contexts missing", rdfNodes.containsAll(ImmutableSet.of(
"class org.fcrepo.kernel.impl.rdf.impl.LdpContainerRdfContext",
"class org.fcrepo.kernel.impl.rdf.impl.LdpIsMemberOfRdfContext",
"class org.fcrepo.kernel.impl.rdf.impl.ReferencesRdfContext",
"class org.fcrepo.kernel.impl.rdf.impl.TypeRdfContext",
"class org.fcrepo.kernel.impl.rdf.impl.ContainerRdfContext",
Expand Down Expand Up @@ -344,6 +345,7 @@ public String apply(final RDFNode input) {
});
assertTrue("Expected RDF contexts missing", rdfNodes.containsAll(ImmutableSet.of(
"class org.fcrepo.kernel.impl.rdf.impl.LdpContainerRdfContext",
"class org.fcrepo.kernel.impl.rdf.impl.LdpIsMemberOfRdfContext",
"class org.fcrepo.kernel.impl.rdf.impl.ReferencesRdfContext",
"class org.fcrepo.kernel.impl.rdf.impl.TypeRdfContext",
"class org.fcrepo.kernel.impl.rdf.impl.ContainerRdfContext",
Expand Down Expand Up @@ -428,6 +430,8 @@ public String apply(final RDFNode input) {
});
assertFalse("Should not include membership contexts",
rdfNodes.contains("class org.fcrepo.kernel.impl.rdf.impl.LdpContainerRdfContext"));
assertFalse("Should not include membership contexts",
rdfNodes.contains("class org.fcrepo.kernel.impl.rdf.impl.LdpIsMemberOfRdfContext"));

assertTrue("Should include containment contexts",
rdfNodes.contains("class org.fcrepo.kernel.impl.rdf.impl.ChildrenRdfContext"));
Expand Down Expand Up @@ -500,6 +504,7 @@ public String apply(final RDFNode input) {
});
assertTrue("Expected RDF contexts missing", rdfNodes.containsAll(ImmutableSet.of(
"class org.fcrepo.kernel.impl.rdf.impl.LdpContainerRdfContext",
"class org.fcrepo.kernel.impl.rdf.impl.LdpIsMemberOfRdfContext",
"class org.fcrepo.kernel.impl.rdf.impl.ReferencesRdfContext",
"class org.fcrepo.kernel.impl.rdf.impl.TypeRdfContext",
"class org.fcrepo.kernel.impl.rdf.impl.ContainerRdfContext",
Expand Down
Expand Up @@ -37,6 +37,7 @@
import static com.hp.hpl.jena.graph.Triple.create;
import static org.fcrepo.jcr.FedoraJcrTypes.LDP_CONTAINER;
import static org.fcrepo.jcr.FedoraJcrTypes.LDP_HAS_MEMBER_RELATION;
import static org.fcrepo.jcr.FedoraJcrTypes.LDP_IS_MEMBER_OF_RELATION;
import static org.fcrepo.jcr.FedoraJcrTypes.LDP_MEMBER_RESOURCE;
import static org.fcrepo.kernel.RdfLexicon.LDP_MEMBER;
import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT;
Expand Down Expand Up @@ -103,6 +104,8 @@ private Iterator<Triple> memberRelations(final Node inputNode) throws Repository
if (inputNode.hasProperty(LDP_HAS_MEMBER_RELATION)) {
final Property property = inputNode.getProperty(LDP_HAS_MEMBER_RELATION);
memberRelation = NodeFactory.createURI(property.getString());
} else if (inputNode.hasProperty(LDP_IS_MEMBER_OF_RELATION)) {
return Collections.emptyIterator();
} else {
memberRelation = LDP_MEMBER.asNode();
}
Expand Down
@@ -0,0 +1,120 @@
/**
* Copyright 2014 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.impl.rdf.impl;

import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import org.fcrepo.kernel.identifiers.IdentifierConverter;
import org.fcrepo.kernel.impl.FedoraBinaryImpl;

import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;

import static com.hp.hpl.jena.graph.Triple.create;
import static javax.jcr.PropertyType.PATH;
import static javax.jcr.PropertyType.REFERENCE;
import static javax.jcr.PropertyType.WEAKREFERENCE;
import static org.fcrepo.jcr.FedoraJcrTypes.LDP_IS_MEMBER_OF_RELATION;
import static org.fcrepo.jcr.FedoraJcrTypes.LDP_MEMBER_RESOURCE;

/**
* @author cabeer
* @since 10/7/14
*/
public class LdpIsMemberOfRdfContext extends NodeRdfContext {
/**
* Default constructor.
*
* @param node
* @param graphSubjects
* @throws javax.jcr.RepositoryException
*/
public LdpIsMemberOfRdfContext(final Node node,
final IdentifierConverter<Resource, Node> graphSubjects) throws RepositoryException {
super(node, graphSubjects);

if (!isRoot(node)) {
final Node container = getContainer(node);

if (container.hasProperty(LDP_IS_MEMBER_OF_RELATION)) {
final Property property = container.getProperty(LDP_IS_MEMBER_OF_RELATION);

final Resource memberRelation = ResourceFactory.createResource(property.getString());

final Resource membershipResource = getMemberResource(graphSubjects, container);

if (membershipResource != null) {
concat(create(subject(), memberRelation.asNode(), membershipResource.asNode()));
}
}
}
}

/**
* Check if the node is the root resource (and therefore can't be within a container)
* @param node
* @return
* @throws RepositoryException
*/
private boolean isRoot(final Node node) throws RepositoryException {
return node.getDepth() == 0;
}

/**
* Get the LDP container for this node
* @param node
* @return
* @throws RepositoryException
*/
private Node getContainer(final Node node) throws RepositoryException {
final Node parent;

if (FedoraBinaryImpl.hasMixin(node)) {
parent = node.getParent().getParent();
} else {
parent = node.getParent();
}
return parent;
}

/**
* Get the membership resource relation asserted by the container
* @param graphSubjects
* @param parent
* @return
* @throws RepositoryException
*/
private Resource getMemberResource(final IdentifierConverter<Resource, Node> graphSubjects,
final Node parent) throws RepositoryException {
final Resource membershipResource;

if (parent.hasProperty(LDP_MEMBER_RESOURCE)) {
final Property memberResource = parent.getProperty(LDP_MEMBER_RESOURCE);

final int type = memberResource.getType();
if ( type == REFERENCE || type == WEAKREFERENCE || type == PATH) {
membershipResource = graphSubjects.reverse().convert(memberResource.getNode());
} else {
membershipResource = ResourceFactory.createResource(memberResource.getString());
}
} else {
membershipResource = graphSubjects.reverse().convert(parent);
}

return membershipResource;
}
}
@@ -0,0 +1,178 @@
/**
* Copyright 2014 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.impl.rdf.impl;

import com.google.common.base.Converter;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Resource;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;

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

import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
import static javax.jcr.PropertyType.REFERENCE;
import static javax.jcr.PropertyType.URI;
import static org.fcrepo.jcr.FedoraJcrTypes.FEDORA_BINARY;
import static org.fcrepo.jcr.FedoraJcrTypes.LDP_IS_MEMBER_OF_RELATION;
import static org.fcrepo.jcr.FedoraJcrTypes.LDP_MEMBER_RESOURCE;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

/**
* @author cabeer
*/
public class LdpIsMemberOfRdfContextTest {

private LdpIsMemberOfRdfContext testObj;

@Mock
private Node mockBinary;

@Mock
private Node mockNode;

@Mock
private Node mockContainer;

@Mock
private Node mockResource;

@Mock
private Property mockRelationProperty;

@Mock
private Property mockMembershipProperty;

@Mock
private Session mockSession;

private DefaultIdentifierTranslator subjects;

@Before
public void setUp() throws RepositoryException {
initMocks(this);
when(mockNode.getPath()).thenReturn("/a");
when(mockNode.getParent()).thenReturn(mockContainer);
when(mockNode.getDepth()).thenReturn(1);

when(mockContainer.getPath()).thenReturn("/");

when(mockResource.getPath()).thenReturn("/some/path");

when(mockBinary.getParent()).thenReturn(mockNode);
when(mockBinary.getDepth()).thenReturn(2);
when(mockBinary.isNodeType(FEDORA_BINARY)).thenReturn(true);
when(mockBinary.getPath()).thenReturn("/a/jcr:content");

subjects = new DefaultIdentifierTranslator(mockSession);
}

@Test
public void testIsMemberOfRelationWithRootResource() throws RepositoryException {
testObj = new LdpIsMemberOfRdfContext(mockContainer, subjects);

final Model model = testObj.asModel();

assertTrue("Expected stream to be empty", model.isEmpty());
}

@Test
public void testIsMemberOfRelationWithoutIsMemberOfResource() throws RepositoryException {
testObj = new LdpIsMemberOfRdfContext(mockNode, subjects);

final Model model = testObj.asModel();

assertTrue("Expected stream to be empty", model.isEmpty());
}

@Test
public void testIsMemberOfRelation() throws RepositoryException {
when(mockContainer.hasProperty(LDP_IS_MEMBER_OF_RELATION)).thenReturn(true);
when(mockContainer.getProperty(LDP_IS_MEMBER_OF_RELATION)).thenReturn(mockRelationProperty);
when(mockContainer.hasProperty(LDP_MEMBER_RESOURCE)).thenReturn(true);
when(mockContainer.getProperty(LDP_MEMBER_RESOURCE)).thenReturn(mockMembershipProperty);
when(mockMembershipProperty.getType()).thenReturn(REFERENCE);
when(mockMembershipProperty.getNode()).thenReturn(mockResource);

final String property = "some:uri";
when(mockRelationProperty.getString()).thenReturn(property);
testObj = new LdpIsMemberOfRdfContext(mockNode, subjects);

final Model model = testObj.asModel();

final Converter<Node, Resource> nodeSubjects = subjects.reverse();

assertTrue("Expected stream to contain triple",
model.contains(nodeSubjects.convert(mockNode),
createProperty(property),
nodeSubjects.convert(mockResource)));
}


@Test
public void testIsMemberOfRelationToExternalResource() throws RepositoryException {
when(mockContainer.hasProperty(LDP_IS_MEMBER_OF_RELATION)).thenReturn(true);
when(mockContainer.getProperty(LDP_IS_MEMBER_OF_RELATION)).thenReturn(mockRelationProperty);
when(mockContainer.hasProperty(LDP_MEMBER_RESOURCE)).thenReturn(true);
when(mockContainer.getProperty(LDP_MEMBER_RESOURCE)).thenReturn(mockMembershipProperty);
when(mockMembershipProperty.getType()).thenReturn(URI);
when(mockMembershipProperty.getString()).thenReturn("some:resource");

final String property = "some:uri";
when(mockRelationProperty.getString()).thenReturn(property);
testObj = new LdpIsMemberOfRdfContext(mockNode, subjects);

final Model model = testObj.asModel();

final Converter<Node, Resource> nodeSubjects = subjects.reverse();

assertTrue("Expected stream to contain triple",
model.contains(nodeSubjects.convert(mockNode),
createProperty(property),
createResource("some:resource")));
}

@Test
public void testIsMemberOfRelationForBinary() throws RepositoryException {
when(mockContainer.hasProperty(LDP_IS_MEMBER_OF_RELATION)).thenReturn(true);
when(mockContainer.getProperty(LDP_IS_MEMBER_OF_RELATION)).thenReturn(mockRelationProperty);
when(mockContainer.hasProperty(LDP_MEMBER_RESOURCE)).thenReturn(true);
when(mockContainer.getProperty(LDP_MEMBER_RESOURCE)).thenReturn(mockMembershipProperty);
when(mockMembershipProperty.getType()).thenReturn(REFERENCE);
when(mockMembershipProperty.getNode()).thenReturn(mockResource);

final String property = "some:uri";

when(mockRelationProperty.getString()).thenReturn(property);
testObj = new LdpIsMemberOfRdfContext(mockBinary, subjects);

final Model model = testObj.asModel();

final Converter<Node, Resource> nodeSubjects = subjects.reverse();

assertTrue("Expected stream to contain triple",
model.contains(nodeSubjects.convert(mockBinary),
createProperty(property),
nodeSubjects.convert(mockResource)));
}
}
Expand Up @@ -64,6 +64,7 @@ public interface FedoraJcrTypes {
String JCR_MIXIN_TYPES = "jcr:mixinTypes";

String LDP_HAS_MEMBER_RELATION = "ldp:hasMemberRelation";
String LDP_IS_MEMBER_OF_RELATION = "ldp:isMemberOfRelation";
String LDP_MEMBER_RESOURCE = "ldp:membershipResource";

String [] EXPOSED_PROTECTED_JCR_TYPES
Expand Down

0 comments on commit 8a0681a

Please sign in to comment.