Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle ldp:isMemberOfRelation on IndirectContainers #1080

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
import static org.fcrepo.kernel.api.RdfLexicon.HAS_PRIMARY_TYPE;
import static org.fcrepo.kernel.api.RdfLexicon.INBOUND_REFERENCES;
import static org.fcrepo.kernel.api.RdfLexicon.INDIRECT_CONTAINER;
import static org.fcrepo.kernel.api.RdfLexicon.IS_MEMBER_OF_RELATION;
import static org.fcrepo.kernel.api.RdfLexicon.JCR_NAMESPACE;
import static org.fcrepo.kernel.api.RdfLexicon.JCR_NT_NAMESPACE;
import static org.fcrepo.kernel.api.RdfLexicon.LAST_MODIFIED_DATE;
Expand Down Expand Up @@ -2037,6 +2038,72 @@ public void testLdpIndirectContainerInteraction() throws IOException {
}
}

@Test
public void testLdpIndirectContainerInteractionMemberOf() throws IOException {

// Create resource (object)
final String resourceId = getRandomUniqueId();
final String resource;
try (final CloseableHttpResponse createResponse = createObject(resourceId)) {
resource = getLocation(createResponse);
}
// Create container (c0)
final String containerId = getRandomUniqueId();
final String container;
try (final CloseableHttpResponse createResponse = createObject(containerId)) {
container = getLocation(createResponse);
}
// Create indirect container (c0/members)
final String indirectContainerId = containerId + "/t";
final String indirectContainer;
try (final CloseableHttpResponse createResponse = createObject(indirectContainerId)) {
indirectContainer = getLocation(createResponse);
}
addMixin(indirectContainerId, INDIRECT_CONTAINER.getURI());

// Add LDP properties to indirect container
final HttpPatch patch = patchObjMethod(indirectContainerId);
patch.addHeader("Content-Type", "application/sparql-update");
final String sparql = "INSERT DATA { "
+ "<> <" + MEMBERSHIP_RESOURCE + "> <" + container + "> .\n"
+ "<> <" + IS_MEMBER_OF_RELATION + "> <info:some/relation> .\n"
+ "<> <" + LDP_NAMESPACE + "insertedContentRelation> <info:proxy/for> .\n"
+ " }";
patch.setEntity(new StringEntity(sparql));
assertEquals("Expected patch to succeed", NO_CONTENT.getStatusCode(), getStatus(patch));

// Add indirect resource to indirect container
final HttpPost postIndirectResource = postObjMethod(indirectContainerId);
final String irRdf =
"<> <info:proxy/in> <" + container + "> ;\n" +
" <info:proxy/for> <" + resource + "> .";
postIndirectResource.setEntity(new StringEntity(irRdf));
postIndirectResource.setHeader("Content-Type", "text/turtle");

final String indirectResource;
try (final CloseableHttpResponse postResponse = execute(postIndirectResource)) {
indirectResource = getLocation(postResponse);
assertEquals("Expected post to succeed", CREATED.getStatusCode(), getStatus(postResponse));
}
// Ensure resource has been updated with relationship... indirectly
try (final CloseableHttpResponse getResponse = execute(new HttpGet(resource));
final CloseableGraphStore graphStore = getGraphStore(getResponse)) {
assertTrue("Expected to have triple on resource: " + createURI("info:some/relation") + " <"
+ createURI(container) + ">, graph: " + graphStore.toString(),
graphStore.contains(ANY, createURI(resource), createURI("info:some/relation"), createURI(container)));
}
// Remove indirect resource
assertEquals("Expected delete to succeed",
NO_CONTENT.getStatusCode(), getStatus(new HttpDelete(indirectResource)));

// Ensure resource has been updated with relationship... indirectly
try (final CloseableHttpResponse getResponse1 = execute(new HttpGet(resource));
final CloseableGraphStore graphStore1 = getGraphStore(getResponse1);) {
assertFalse("Expected NOT to have resource: " + graphStore1, graphStore1.contains(ANY,
createURI(resource), createURI("info:some/relation"), createURI(container)));
}
}

@Test
public void testWithHashUris() throws IOException {
final HttpPost method = postObjMethod();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ public final class RdfLexicon {
createProperty(LDP_NAMESPACE + "membershipResource");
public static final Property HAS_MEMBER_RELATION =
createProperty(LDP_NAMESPACE + "hasMemberRelation");
public static final Property IS_MEMBER_OF_RELATION =
createProperty(LDP_NAMESPACE + "isMemberOfRelation");
public static final Property CONTAINS =
createProperty(LDP_NAMESPACE + "contains");
public static final Property LDP_MEMBER =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import static org.fcrepo.kernel.modeshape.rdf.converters.PropertyConverter.getPropertyNameFromPredicate;
import static org.fcrepo.kernel.modeshape.rdf.impl.ReferencesRdfContext.REFERENCE_TYPES;
import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getJcrNode;
import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getReferencePropertyName;
import static org.fcrepo.kernel.modeshape.utils.StreamUtils.iteratorToStream;

/**
Expand Down Expand Up @@ -102,9 +103,14 @@ private Stream<Triple> concatIsMemberOfRelation(final FedoraResource container)
if (insertedContainerProperty.equals(MEMBER_SUBJECT.getURI())) {
return of(create(subject(), memberRelation.asNode(), membershipResource));
} else if (container.hasType(LDP_INDIRECT_CONTAINER)) {
final String insertedContentProperty = getPropertyNameFromPredicate(getJcrNode(resource()), createResource
String insertedContentProperty = getPropertyNameFromPredicate(getJcrNode(resource()), createResource
(insertedContainerProperty), null);

// The insertedContentProperty may be a pseudo reference property
if (resource().hasProperty(getReferencePropertyName(insertedContentProperty))) {
insertedContentProperty = getReferencePropertyName(insertedContentProperty);
}

if (resource().hasProperty(insertedContentProperty)) {
return iteratorToStream(new PropertyValueIterator(
getJcrNode(resource()).getProperty(insertedContentProperty)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import static org.fcrepo.kernel.api.FedoraTypes.LDP_MEMBER_RESOURCE;
import static org.fcrepo.kernel.api.RdfCollectors.toModel;
import static org.fcrepo.kernel.modeshape.identifiers.NodeResourceConverter.nodeToResource;
import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.REFERENCE_PROPERTY_SUFFIX;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
Expand Down Expand Up @@ -221,8 +222,9 @@ public void testIsMemberOfRelationWithIndirectContainer() throws RepositoryExcep
when(mockNamespaceRegistry.isRegisteredUri("some:")).thenReturn(true);
when(mockNamespaceRegistry.getPrefix("some:")).thenReturn("some");

when(mockResource.hasProperty("some:relation")).thenReturn(true);
when(mockResourceNode.getProperty("some:relation")).thenReturn(mockRelationProperty);
when(mockResource.hasProperty("some:relation" + REFERENCE_PROPERTY_SUFFIX)).thenReturn(true);
when(mockResourceNode.getProperty("some:relation" + REFERENCE_PROPERTY_SUFFIX))
.thenReturn(mockRelationProperty);
when(mockRelationProperty.isMultiple()).thenReturn(false);
when(mockRelationProperty.getValue()).thenReturn(mockRelationValue);
when(mockRelationValue.getType()).thenReturn(URI);
Expand Down