Skip to content

Commit

Permalink
Pushed RDF mutation all the way through HTTP API, for replacement of …
Browse files Browse the repository at this point in the history
…properties
  • Loading branch information
ajs6f committed Oct 28, 2013
1 parent f679d4c commit 123aa78
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 73 deletions.
19 changes: 8 additions & 11 deletions fcrepo-http-api/src/main/java/org/fcrepo/http/api/FedoraNodes.java
Expand Up @@ -93,7 +93,6 @@
import org.fcrepo.http.commons.session.InjectedSession;
import org.fcrepo.kernel.Datastream;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.exception.InvalidChecksumException;
import org.fcrepo.kernel.rdf.GraphSubjects;
import org.modeshape.jcr.api.JcrConstants;
import org.slf4j.Logger;
Expand Down Expand Up @@ -317,7 +316,7 @@ public Response updateSparql(@PathParam("path")
* @param requestContentType
* @param requestBodyStream
* @return
* @throws RepositoryException
* @throws Exception
*/
@PUT
@Consumes({TURTLE, N3, N3_ALT1, N3_ALT2, RDF_XML, RDF_JSON, NTRIPLES})
Expand All @@ -328,7 +327,7 @@ public Response createOrReplaceObjectRdf(
@HeaderParam("Content-Type")
final MediaType requestContentType,
final InputStream requestBodyStream,
@Context final Request request) throws RepositoryException, URISyntaxException {
@Context final Request request) throws Exception {
final String path = toPath(pathList);
logger.debug("Attempting to replace path: {}", path);
try {
Expand All @@ -352,7 +351,7 @@ public Response createOrReplaceObjectRdf(
throw new WebApplicationException(builder.build());
}

final HttpGraphSubjects subjects = new HttpGraphSubjects(session, FedoraNodes.class, uriInfo);
final HttpGraphSubjects graphSubjects = new HttpGraphSubjects(session, FedoraNodes.class, uriInfo);

if (requestContentType != null && requestBodyStream != null) {
final String contentType = requestContentType.toString();
Expand All @@ -362,10 +361,10 @@ public Response createOrReplaceObjectRdf(

final Model inputModel = createDefaultModel()
.read(requestBodyStream,
subjects.getGraphSubject(resource.getNode()).toString(),
graphSubjects.getGraphSubject(resource.getNode()).toString(),
format);

resource.replacePropertiesDataset(subjects, inputModel);
resource.replaceProperties(graphSubjects, inputModel);
}

session.save();
Expand All @@ -381,9 +380,7 @@ public Response createOrReplaceObjectRdf(
*
* @param pathList
* @return 201
* @throws RepositoryException
* @throws InvalidChecksumException
* @throws IOException
* @throws Exception
*/
@POST
@Timed
Expand All @@ -399,7 +396,7 @@ public Response createObject(@PathParam("path")
final String slug,
@Context
final UriInfo uriInfo, final InputStream requestBodyStream)
throws RepositoryException, IOException, InvalidChecksumException, URISyntaxException {
throws Exception {

final String newObjectPath;
final String path = toPath(pathList);
Expand Down Expand Up @@ -494,7 +491,7 @@ public Response createObject(@PathParam("path")
subjects.getGraphSubject(result.getNode()).toString(),
format);

result.replacePropertiesDataset(subjects, inputModel);
result.replaceProperties(subjects, inputModel);
} else if (result instanceof Datastream) {

datastreamService.createDatastreamNode(session,
Expand Down
Expand Up @@ -65,7 +65,6 @@
import org.fcrepo.kernel.Datastream;
import org.fcrepo.kernel.FedoraObject;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.exception.InvalidChecksumException;
import org.fcrepo.kernel.identifiers.PidMinter;
import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.services.DatastreamService;
Expand Down Expand Up @@ -149,8 +148,7 @@ public void testIngestAndMint() throws RepositoryException {
}

@Test
public void testCreateObject() throws RepositoryException, IOException,
InvalidChecksumException, URISyntaxException {
public void testCreateObject() throws Exception {
final String pid = "testObject";
final String path = "/" + pid;
when(mockObjects.createObject(mockSession, path)).thenReturn(mockObject);
Expand All @@ -167,8 +165,7 @@ public void testCreateObject() throws RepositoryException, IOException,
}

@Test
public void testCreateChildObject() throws RepositoryException, IOException,
InvalidChecksumException, URISyntaxException, NoSuchFieldException {
public void testCreateChildObject() throws Exception {

setField(testObj, "pidMinter", mockPidMinter);
final String pid = "testObject";
Expand All @@ -189,8 +186,7 @@ public void testCreateChildObject() throws RepositoryException, IOException,
}

@Test
public void testCreateChildObjectWithSlug() throws RepositoryException, IOException,
InvalidChecksumException, URISyntaxException, NoSuchFieldException {
public void testCreateChildObjectWithSlug() throws Exception {
setField(testObj, "pidMinter", mockPidMinter);

final String pid = "testObject";
Expand All @@ -210,8 +206,7 @@ public void testCreateChildObjectWithSlug() throws RepositoryException, IOExcept
}

@Test
public void testCreateDatastream() throws RepositoryException, IOException,
InvalidChecksumException, URISyntaxException {
public void testCreateDatastream() throws Exception {
final String pid = "FedoraDatastreamsTest1";
final String dsId = "testDS";
final String dsContent = "asdf";
Expand Down Expand Up @@ -318,7 +313,7 @@ public void testSparqlUpdate() throws RepositoryException, IOException {
}

@Test
public void testReplaceRdf() throws RepositoryException, IOException, URISyntaxException {
public void testReplaceRdf() throws IllegalArgumentException, Exception {
final String pid = "FedoraObjectsRdfTest1";
final String path = "/" + pid;
when(mockObject.getLastModifiedDate()).thenReturn(Calendar.getInstance().getTime());
Expand All @@ -331,7 +326,7 @@ public void testReplaceRdf() throws RepositoryException, IOException, URISyntaxE
when(mockNodes.getObject(mockSession, path)).thenReturn(mockObject);

testObj.createOrReplaceObjectRdf(createPathList(pid), getUriInfoImpl(), MediaType.valueOf("application/n3"), mockStream, mockRequest);
verify(mockObject).replacePropertiesDataset(any(GraphSubjects.class), any(Model.class));
verify(mockObject).replaceProperties(any(GraphSubjects.class), any(Model.class));
}

@Test
Expand Down
Expand Up @@ -70,7 +70,6 @@
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.impl.client.cache.CachingHttpClient;
import org.apache.http.util.EntityUtils;
Expand Down Expand Up @@ -159,7 +158,8 @@ public void testIngestWithNewAndGraph() throws Exception {
final HttpPost method = postObjMethod("");
method.addHeader("Content-Type", "application/n3");
final BasicHttpEntity entity = new BasicHttpEntity();
entity.setContent(new ByteArrayInputStream("<> <http://purl.org/dc/terms/title> \"this is a title\"".getBytes()));
final String rdf = "<> <http://purl.org/dc/terms/title> \"this is a title\".";
entity.setContent(new ByteArrayInputStream(rdf.getBytes()));
method.setEntity(entity);
final HttpResponse response = client.execute(method);
final String content = EntityUtils.toString(response.getEntity());
Expand Down Expand Up @@ -820,15 +820,6 @@ private class HttpCopy extends HttpRequestBase {
public final static String METHOD_NAME = "COPY";


public HttpCopy() {
super();
}

public HttpCopy(final URI uri) {
super();
setURI(uri);
}

/**
* @throws IllegalArgumentException if the uri is invalid.
*/
Expand All @@ -850,15 +841,6 @@ private class HttpMove extends HttpRequestBase {
public final static String METHOD_NAME = "MOVE";


public HttpMove() {
super();
}

public HttpMove(final URI uri) {
super();
setURI(uri);
}

/**
* @throws IllegalArgumentException if the uri is invalid.
*/
Expand Down
Expand Up @@ -25,7 +25,6 @@
import static org.fcrepo.jcr.FedoraJcrTypes.FEDORA_OBJECT;
import static org.slf4j.LoggerFactory.getLogger;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.List;
Expand All @@ -49,7 +48,6 @@
import org.fcrepo.http.commons.session.SessionFactory;
import org.fcrepo.kernel.Datastream;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.exception.InvalidChecksumException;
import org.fcrepo.kernel.identifiers.PidMinter;
import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.services.DatastreamService;
Expand Down Expand Up @@ -180,8 +178,7 @@ protected FedoraResource createObjectOrDatastreamFromRequestContent(
final String path, final String mixin, final GraphSubjects subjects,
final InputStream requestBodyStream,
final MediaType requestContentType,
final URI checksum) throws RepositoryException,
InvalidChecksumException, IOException {
final URI checksum) throws Exception {

final FedoraResource result;

Expand Down Expand Up @@ -217,7 +214,7 @@ protected FedoraResource createObjectOrDatastreamFromRequestContent(
result.getNode()).toString(),
format);

result.replacePropertiesDataset(subjects, inputModel);
result.replaceProperties(subjects, inputModel);
}
}

Expand Down
54 changes: 41 additions & 13 deletions fcrepo-kernel/src/main/java/org/fcrepo/kernel/FedoraResource.java
Expand Up @@ -15,6 +15,7 @@
*/
package org.fcrepo.kernel;

import static com.google.common.collect.ImmutableSet.copyOf;
import static com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel;
import static com.hp.hpl.jena.update.UpdateAction.execute;
import static com.hp.hpl.jena.update.UpdateFactory.create;
Expand All @@ -34,6 +35,7 @@
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Set;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
Expand All @@ -44,10 +46,15 @@
import org.fcrepo.kernel.rdf.GraphSubjects;
import org.fcrepo.kernel.utils.JcrPropertyStatementListener;
import org.fcrepo.kernel.utils.JcrRdfTools;
import org.fcrepo.kernel.utils.iterators.DifferencingIterator;
import org.fcrepo.kernel.utils.iterators.RdfAdder;
import org.fcrepo.kernel.utils.iterators.RdfRemover;
import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.modeshape.jcr.api.JcrTools;
import org.slf4j.Logger;

import com.google.common.collect.Iterables;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.query.DatasetFactory;
import com.hp.hpl.jena.rdf.model.Model;
Expand Down Expand Up @@ -222,8 +229,7 @@ public Dataset updatePropertiesDataset(final GraphSubjects subjects,
}

/**
* Serialize the JCR properties as an RDF Dataset
*
* Return the JCR properties of this object as a Jena {@link Dataset}
*
* @param subjects
* @param offset
Expand Down Expand Up @@ -265,7 +271,7 @@ public Dataset getPropertiesDataset(final GraphSubjects graphSubjects,
}

/**
* Serialize the JCR properties of this object as an RDF Dataset
* Return the JCR properties of this object as a Jena {@link Dataset}
* @return
* @throws RepositoryException
*/
Expand All @@ -274,6 +280,20 @@ public Dataset getPropertiesDataset(final GraphSubjects subjects)
return getPropertiesDataset(subjects, 0, -1);
}

/**
* Return the JCR properties of this object as an {@link RdfStream}
* @return
* @throws RepositoryException
*/
public RdfStream getTriples(final GraphSubjects graphSubjects)
throws RepositoryException {

final JcrRdfTools jcrRdfTools =
JcrRdfTools.withContext(graphSubjects, getNode().getSession());

return jcrRdfTools.getJcrTriples(getNode());
}

/**
* Serialize the JCR versions information as an RDF dataset
* @param subjects
Expand Down Expand Up @@ -314,20 +334,28 @@ public boolean isNew() {
* @param subjects
* @param inputModel
* @return
* @throws RepositoryException
* @throws Exception
*/
public Dataset replacePropertiesDataset(final GraphSubjects subjects,
final Model inputModel) throws RepositoryException {
final Dataset propertiesDataset = getPropertiesDataset(subjects, 0, -2);
final Model model = propertiesDataset.getDefaultModel();
public RdfStream replaceProperties(final GraphSubjects graphSubjects,
final Model inputModel) throws Exception {
final RdfStream originalTriples = getTriples(graphSubjects);

final RdfStream replacementStream = RdfStream.fromModel(inputModel);

final Set<Triple> replacementTriples =
copyOf(replacementStream.iterator());

final DifferencingIterator<Triple> differencer =
new DifferencingIterator<>(replacementTriples, originalTriples);

final Model removed = model.difference(inputModel);
model.remove(removed.listStatements());
new RdfRemover(graphSubjects, getNode().getSession(), replacementStream
.withThisContext(differencer)).consume();

final Model created = inputModel.difference(model);
model.add(created.listStatements());
new RdfAdder(graphSubjects, getNode().getSession(), replacementStream
.withThisContext(differencer.notCommon())).consume();

return propertiesDataset;
return replacementStream.withThisContext(Iterables.concat(differencer
.common(), differencer.notCommon()));
}

/**
Expand Down
30 changes: 28 additions & 2 deletions fcrepo-kernel/src/main/java/org/fcrepo/kernel/RdfLexicon.java
Expand Up @@ -16,6 +16,7 @@
package org.fcrepo.kernel;

import static com.google.common.base.Predicates.in;
import static com.google.common.base.Predicates.or;
import static com.google.common.collect.ImmutableSet.of;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty;

Expand All @@ -38,6 +39,8 @@ public final class RdfLexicon {
public static final String REPOSITORY_NAMESPACE =
"http://fedora.info/definitions/v4/repository#";

public static final String JCR_NAMESPACE = "http://www.jcp.org/jcr/1.0";

/**
* REST API namespace "fedora", used for internal API links and node
* paths.
Expand Down Expand Up @@ -260,8 +263,31 @@ public final class RdfLexicon {
managedProperties = b.build();
}

public static final Predicate<Property> isManagedPredicate =
in(managedProperties);
private static Predicate<Property> hasJcrNamespace =
new Predicate<Property>() {

@Override
public boolean apply(final Property p) {
return p.getNameSpace() == JCR_NAMESPACE;

}
};

private static Predicate<Property> hasFedoraNamespace =
new Predicate<Property>() {

@Override
public boolean apply(final Property p) {
return p.getNameSpace() == REPOSITORY_NAMESPACE;

}
};

/**
* Detects whether an RDF property is managed by the repository.
*/
public static final Predicate<Property> isManagedPredicate = or(
in(managedProperties), hasJcrNamespace, hasFedoraNamespace);

private RdfLexicon() {

Expand Down

0 comments on commit 123aa78

Please sign in to comment.