Skip to content

Commit

Permalink
poke object graph through the REST API
Browse files Browse the repository at this point in the history
  • Loading branch information
cbeer committed May 3, 2013
1 parent ce3bc7e commit 89e0e3d
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 6 deletions.
24 changes: 18 additions & 6 deletions fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraNodes.java
Expand Up @@ -5,9 +5,7 @@
import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
import static javax.ws.rs.core.MediaType.TEXT_HTML;
import static javax.ws.rs.core.MediaType.TEXT_XML;
import static javax.ws.rs.core.Response.created;
import static javax.ws.rs.core.Response.noContent;
import static javax.ws.rs.core.Response.ok;
import static javax.ws.rs.core.Response.*;
import static org.slf4j.LoggerFactory.getLogger;

import java.io.IOException;
Expand All @@ -31,7 +29,9 @@
import javax.ws.rs.core.PathSegment;
import javax.ws.rs.core.Response;

import com.hp.hpl.jena.update.UpdateAction;
import com.yammer.metrics.annotation.Timed;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpStatus;
import org.fcrepo.AbstractResource;
import org.fcrepo.Datastream;
Expand Down Expand Up @@ -170,12 +170,21 @@ public DescribeRepository getRepositoryProfile() throws RepositoryException {
@PUT
@Timed
public Response modifyObject(@PathParam("path")
final List<PathSegment> pathList) throws RepositoryException {
final List<PathSegment> pathList, final InputStream requestBodyStream) throws RepositoryException, IOException {
final Session session = getAuthenticatedSession();
String path = toPath(pathList);
logger.debug("Modifying object with path: {}", path);

try {
// TODO do something with awful mess of fcrepo3 query params

final FedoraObject result =
objectService.getObject(session, path);

UpdateAction.parseExecute(IOUtils.toString(requestBodyStream), result.getGraphStore());

session.save();
return created(uriInfo.getRequestUri()).build();

return temporaryRedirect(uriInfo.getRequestUri()).build();
} finally {
session.logout();
}
Expand Down Expand Up @@ -217,6 +226,9 @@ public Response createObject(
if (label != null && !"".equals(label)) {
result.setLabel(label);
}

UpdateAction.parseExecute(IOUtils.toString(requestBodyStream), result.getGraphStore());

}
if (FedoraJcrTypes.FEDORA_DATASTREAM.equals(mixin)){
final MediaType contentType =
Expand Down
9 changes: 9 additions & 0 deletions fcrepo-kernel/pom.xml
Expand Up @@ -49,6 +49,13 @@
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>apache-jena-libs</artifactId>
<type>pom</type>
<version>2.10.0</version>
</dependency>

<!-- Logging: we'll use LogBack (which implements the SLF4J API); ModeShape
knows what to do. -->
<dependency>
Expand All @@ -75,6 +82,8 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>


</dependencies>

<build>
Expand Down
164 changes: 164 additions & 0 deletions fcrepo-kernel/src/main/java/org/fcrepo/FedoraObject.java
Expand Up @@ -13,17 +13,32 @@
import static org.modeshape.jcr.api.JcrConstants.NT_FOLDER;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import javax.jcr.NamespaceRegistry;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.nodetype.NodeType;

import com.hp.hpl.jena.rdf.listeners.StatementListener;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.update.GraphStore;
import com.hp.hpl.jena.update.GraphStoreFactory;
import org.fcrepo.utils.FedoraJcrTypes;
import org.modeshape.jcr.api.JcrTools;
import org.modeshape.jcr.api.Namespaced;
import org.slf4j.Logger;

import com.yammer.metrics.Timer;
Expand Down Expand Up @@ -222,4 +237,153 @@ public static boolean hasMixin(Node node) throws RepositoryException {
return false;
}

public Model getPropertiesModel() throws RepositoryException {

final Resource subject = getGraphSubject();

final Model model = ModelFactory.createDefaultModel();

final PropertyIterator properties = node.getProperties();

while (properties.hasNext()) {
final Property property = properties.nextProperty();

Namespaced nsProperty = (Namespaced)property;
if (property.isMultiple()) {
final Value[] values = (Value[]) property.getValues();

for(Value v : values) {
model.add(subject, ResourceFactory.createProperty(nsProperty.getNamespaceURI(), nsProperty.getLocalName()), v.getString());
}

} else {
final Value value = property.getValue();
model.add(subject, ResourceFactory.createProperty(nsProperty.getNamespaceURI(), nsProperty.getLocalName()), value.getString());
}

}

model.register(new JcrPropertyStatementUpdater(this));

return model;


}

public Resource getGraphSubject() throws RepositoryException {
return ResourceFactory.createResource("info:" + node.getPath());
}

public GraphStore getGraphStore() throws RepositoryException {
GraphStore graphStore = GraphStoreFactory.create(getPropertiesModel());

return graphStore;
}

public void setGraphStore() {

}

class JcrPropertyStatementUpdater extends StatementListener {
private FedoraObject fedoraObject;

public JcrPropertyStatementUpdater(FedoraObject fedoraObject) {

this.fedoraObject = fedoraObject;
}

@Override
public void addedStatement( Statement s ) {
System.out.println(">> added statement " + s);

try {
if(!s.getSubject().equals(fedoraObject.getGraphSubject())) {
return;
}

final String prefix = getNamespaceRegistry().getPrefix(s.getPredicate().getNameSpace());

String propertyName = prefix + ":" + s.getPredicate().getLocalName();

if (fedoraObject.node.hasProperty(propertyName)) {

final Property property = fedoraObject.node.getProperty(propertyName);

if (property.isMultiple()) {

List<Value> newValues = new ArrayList<Value>();

final Value[] oldValues = fedoraObject.node.getProperty(propertyName).getValues();

Collections.addAll(newValues, oldValues);

Value newValue = fedoraObject.node.getSession().getValueFactory().createValue(s.getObject().toString(), property.getType());

newValues.add(newValue);

fedoraObject.node.setProperty(propertyName, (Value[])newValues.toArray());


} else {
property.setValue(s.getObject().toString());
}
} else {
fedoraObject.node.setProperty(propertyName, s.getObject().toString());
}
} catch (RepositoryException e) {
throw new RuntimeException(e);
}

}

@Override
public void removedStatement( Statement s ) {
System.out.println(">> removed statement " + s);

try {
if(!s.getSubject().equals(fedoraObject.getGraphSubject())) {
return;
}

final String prefix = getNamespaceRegistry().getPrefix(s.getPredicate().getNameSpace());

String propertyName = prefix + ":" + s.getPredicate().getLocalName();

if (fedoraObject.node.hasProperty(propertyName)) {

final Property property = fedoraObject.node.getProperty(propertyName);

if (property.isMultiple()) {

List<Value> newValues = new ArrayList<Value>();

Value valueToRemove = fedoraObject.node.getSession().getValueFactory().createValue(s.getObject().toString(), property.getType());

final Value[] currentValues = fedoraObject.node.getProperty(propertyName).getValues();

for ( Value v : currentValues ) {
if ( !v.equals(valueToRemove) ) {
newValues.add(v);
}
}

fedoraObject.node.setProperty(propertyName, (Value[])newValues.toArray());

} else {
property.setValue((Value)null);
}
}
} catch (RepositoryException e) {
throw new RuntimeException(e);
}

}

private NamespaceRegistry getNamespaceRegistry() throws RepositoryException {
return fedoraObject.node.getSession().getWorkspace().getNamespaceRegistry();

}

}

}
Expand Up @@ -6,12 +6,18 @@
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.Iterator;

import javax.inject.Inject;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import com.hp.hpl.jena.sparql.core.Quad;
import com.hp.hpl.jena.update.GraphStore;
import com.hp.hpl.jena.update.UpdateAction;
import org.fcrepo.FedoraObject;
import org.fcrepo.services.ObjectService;
import org.junit.Test;
Expand Down Expand Up @@ -63,4 +69,36 @@ public void testGetSizeWhenInATree() throws Exception {
assertTrue(objectService.getObject(session, "/parentObject").getSize() > originalSize);

}

@Test
public void testObjectGraph() throws Exception {
final Session session = repo.login();
final FedoraObject object = objectService.createObject(session, "/graphObject");
object.setLabel("my-object-label");
final GraphStore graphStore = object.getGraphStore();

assertEquals("info:/graphObject", object.getGraphSubject().toString());

UpdateAction.parseExecute("PREFIX dc: <http://purl.org/dc/terms/>\n" +
"INSERT { <http://example/egbook> dc:title \"This is an example of an update that will be ignored\" } WHERE {}", graphStore);


UpdateAction.parseExecute("PREFIX dc: <http://purl.org/dc/terms/>\n" +
"INSERT { <" + object.getGraphSubject().toString() + "> dc:title \"This is an example title\" } WHERE {}", graphStore);

assertTrue(object.getNode().getProperty("dc:title").getString(), object.getNode().getProperty("dc:title").getString().equals("This is an example title"));
final PropertyIterator properties = object.getNode().getProperties();

while (properties.hasNext()) {
final Property property = properties.nextProperty();

if (property.isMultiple()) {
logger.info(property.getValues().toString());
} else {
logger.info(property.getString());
}

}

}
}
@@ -0,0 +1,67 @@
package org.fcrepo.integration;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.RDFReader;
import com.hp.hpl.jena.rdf.model.ResIterator;
import com.hp.hpl.jena.update.GraphStore;
import com.hp.hpl.jena.update.GraphStoreFactory;
import com.hp.hpl.jena.update.UpdateAction;
import org.apache.jena.riot.RDFDataMgr;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

public class ObjectRelationshipsIT {


protected Logger logger;

@Before
public void setLogger() {
logger = LoggerFactory.getLogger(this.getClass());
}

@Test
public void testSparqlUpdate() throws IOException {
final Model model = ModelFactory.createDefaultModel();

RDFReader arp = model.getReader();

String str =
"<rdf:RDF\n" +
"\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n" +
"\n" +
"<rdf:Description rdf:about=\"info:fedora/druid:xz144dc9157\">\n" +
"\t<lastModifiedDate xmlns=\"info:fedora/fedora-system:def/view#\" rdf:datatype=\"http://www.w3.org/2001/XMLSchema#dateTime\">2013-04-24T05:28:36.664Z</lastModifiedDate>\n" +
"\t<disseminates xmlns=\"info:fedora/fedora-system:def/view#\" rdf:resource=\"info:fedora/druid:xz144dc9157/technicalMetadata\"/>\n" +
"\t<disseminates xmlns=\"info:fedora/fedora-system:def/view#\" rdf:resource=\"info:fedora/druid:xz144dc9157/provenanceMetadata\"/>\n" +
"</rdf:Description>\n" +
"\n" +
"</rdf:RDF>";

InputStream in = new ByteArrayInputStream(str.getBytes());

arp.read(model, in, "info:triples");

in.close();

GraphStore graphStore = GraphStoreFactory.create(model);
UpdateAction.parseExecute("PREFIX dc: <http://purl.org/dc/elements/1.1/>\n" +
"INSERT { <http://example/egbook> dc:title \"This is an example title\" } WHERE {}", graphStore);

final ResIterator iterator = model.listSubjects();

logger.info("Subjects:");
while(iterator.hasNext()) {
logger.info(iterator.next().toString());

}

}
}

0 comments on commit 89e0e3d

Please sign in to comment.