Skip to content

Commit

Permalink
FS projections with the fcrepo api
Browse files Browse the repository at this point in the history
  • Loading branch information
barmintor committed Apr 24, 2013
1 parent 95dcaa5 commit 7fbef1f
Show file tree
Hide file tree
Showing 18 changed files with 190 additions and 33 deletions.
Expand Up @@ -61,8 +61,9 @@ public class FedoraChildren extends AbstractResource {
public Response getObjects(@PathParam("path")
final List<PathSegment> pathList) throws RepositoryException {

logger.trace("children of {}", toPath(pathList));
return ok(objectService.getObjectNames(toPath(pathList.subList(0, pathList.size()-1))).toString()).build();
final String path = toPath(pathList);
logger.info("getting children of {}", path);
return ok(objectService.getObjectNames(path).toString()).build();

}

Expand Down
Expand Up @@ -92,11 +92,13 @@ public class FedoraDatastreams extends AbstractResource {
public ObjectDatastreams getDatastreams(@PathParam("path")
final List<PathSegment> pathList) throws RepositoryException, IOException {

final String path = toPath(pathList);
logger.info("getting datastreams of {}", path);
final ObjectDatastreams objectDatastreams = new ObjectDatastreams();

objectDatastreams.datastreams =
copyOf(transform(datastreamService
.getDatastreamsForPath(toPath(pathList)), ds2dsElement));
.getDatastreamsForPath(path), ds2dsElement));

return objectDatastreams;

Expand Down
Expand Up @@ -146,11 +146,12 @@ public Response ingest(@PathParam("path")
@Path("")
@Produces({TEXT_XML, APPLICATION_JSON, TEXT_HTML})
public ObjectProfile getObject(@PathParam("path")
final List<PathSegment> path) throws RepositoryException, IOException {
final List<PathSegment> pathList) throws RepositoryException, IOException {

logger.trace("getting object profile {}", toPath(path));
final String path = toPath(pathList);
logger.trace("getting object profile {}", path);
final ObjectProfile objectProfile = new ObjectProfile();
final FedoraObject obj = objectService.getObjectByPath(toPath(path));
final FedoraObject obj = objectService.getObjectByPath(path);
objectProfile.pid = obj.getName();
objectProfile.objLabel = obj.getLabel();
objectProfile.objOwnerId = obj.getOwnerId();
Expand Down
12 changes: 10 additions & 2 deletions fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraSitemap.java
Expand Up @@ -7,8 +7,11 @@
import static org.fcrepo.utils.FedoraJcrTypes.FEDORA_OBJECT;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.Calendar;

import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
Expand Down Expand Up @@ -113,10 +116,15 @@ public SitemapUrlSet getSitemap(@PathParam("page")

private SitemapEntry getSitemapEntry(final Row r)
throws RepositoryException {
Value lkDateValue = r.getValue("jcr:lastModified");
if (lkDateValue == null) {
logger.warn("no value for jcr:lastModified on {}", r.getNode().getPath());
lkDateValue = r.getValue("jcr:created");
}
Calendar lastKnownDate = (lkDateValue != null) ? lkDateValue.getDate() : null;
return new SitemapEntry(uriInfo.getBaseUriBuilder().path(
FedoraObjects.class).path(FedoraObjects.class, "getObject")
.build(r.getNode().getName()), r.getValue("jcr:lastModified")
.getDate());
.build(r.getNode().getName()), lastKnownDate);
}


Expand Down
Expand Up @@ -82,7 +82,7 @@ public void testGetObjects() throws RepositoryException {
final Response actual = testObj.getObjects(createPathList("objects"));
assertNotNull(actual);
assertEquals(Status.OK.getStatusCode(), actual.getStatus());
verify(mockObjects).getObjectNames("");
verify(mockObjects).getObjectNames("/objects");
verify(mockSession, never()).save();
}

Expand Down
Expand Up @@ -75,4 +75,5 @@ public void testIngestWithLabel() throws Exception {
final ObjectProfile obj = getObject("FedoraObjectsTest4");
assertEquals("Wrong label!", "Awesome_Object", obj.objLabel);
}

}
Expand Up @@ -7,11 +7,25 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Matcher;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.fcrepo.jaxb.responses.access.ObjectDatastreams;
import org.fcrepo.jaxb.responses.access.ObjectDatastreams.DatastreamElement;
import org.fcrepo.jaxb.responses.management.DatastreamFixity;
import org.junit.Test;

public class FedoraRepositoryIT extends AbstractResourceIT {
Expand Down Expand Up @@ -91,4 +105,57 @@ public void testDescribeSize() throws Exception {
assertTrue("No increment in size occurred when we expected one!",
oldSize < newSize);
}

/**
* Given a directory at:
* test-objects/FileSystem1/
* /ds1
* /ds2
* /TestSubdir/
* and a projection of test-objects as fedora:/files,
* then I should be able to retrieve an object from fedora:/files/FileSystem1
* that lists a child object at fedora:/files/FileSystem1/TestSubdir
* and lists datastreams ds1 and ds2
*/
@Test
public void testGetProjectedNode() throws Exception {
HttpGet method = new HttpGet(serverAddress + "files/FileSystem1/fcr:children");
HttpResponse response = execute(method);
assertEquals(200, response.getStatusLine().getStatusCode());
Collection<String> childNames = parseChildren(response.getEntity());
assertEquals(1, childNames.size());
assertEquals("TestSubdir", childNames.iterator().next());
method = new HttpGet(serverAddress + "files/FileSystem1/fcr:datastreams");
response = execute(method);
childNames = parseDatastreams(response.getEntity());
assertEquals(2, childNames.size());
assertTrue(childNames.contains("ds1"));
assertTrue(childNames.contains("ds2"));
}

static Collection<String> parseChildren(HttpEntity entity) throws IOException {
String body = EntityUtils.toString(entity);
System.err.println(body);
String [] names = body.replace("[","").replace("]", "").trim().split(",\\s?");
return Arrays.asList(names);
}

static Collection<String> parseDatastreams(HttpEntity entity) throws Exception {
String body = EntityUtils.toString(entity);
System.err.println(body);
final JAXBContext context =
JAXBContext.newInstance(ObjectDatastreams.class);
final Unmarshaller um = context.createUnmarshaller();
final ObjectDatastreams objectDs =
(ObjectDatastreams) um.unmarshal(new java.io.StringReader(
body));
Set<DatastreamElement> dss = objectDs.datastreams;
ArrayList<String> result = new ArrayList<String>(dss.size());
for (DatastreamElement ds: dss) {
result.add(ds.dsid);
}
return result;

}

}
@@ -0,0 +1,39 @@
{
"properties": {
"http://www.jcp.org/jcr/1.0": {
"createdBy": "<anonymous>",
"uuid": "b0e430beaa9871/testfedobj",
"isCheckedOut": true,
"lastModifiedBy": "<anonymous>",
"predecessors": {
"$ref": "b0e430beaa9871b0e430beaa9871b0e430beaa9871b0e430beaa9871b0e430beaa9871b0e430beaa987187a0a8c317f1e72fcebfb9-33f3-410f-93ad-35e2d9461112",
"$foreign": true
},
"baseVersion": {
"$ref": "b0e430beaa9871b0e430beaa9871b0e430beaa9871b0e430beaa9871b0e430beaa9871b0e430beaa987187a0a8c317f1e72fcebfb9-33f3-410f-93ad-35e2d9461112",
"$foreign": true
},
"mixinTypes": [
{
"$name": "{info:fedora/}object"
},
{
"$name": "{info:fedora/}owned"
}
],
"versionHistory": {
"$ref": "b0e430beaa9871b0e430beaa9871b0e430beaa9871b0e430beaa9871b0e430beaa9871b0e430beaa987187a0a8c317f1e7/testfedobj",
"$foreign": true
}
},
"http://purl.org/dc/terms/": {
"identifier": [
"b0e430beaa9871/testfedobj",
"testfedobj"
]
},
"info:fedora/": {
"ownerId": "<anonymous>"
}
}
}
Empty file.
@@ -0,0 +1 @@
This is a test datastream
@@ -0,0 +1 @@
asdf
10 changes: 10 additions & 0 deletions fcrepo-http-api/src/test/resources/test_repository.json
Expand Up @@ -15,6 +15,16 @@
"metadataCacheName" : "FedoraRepository"
}
},
"externalSources" : {
"fileSystem" : {
"classname" : "org.modeshape.connector.filesystem.FileSystemConnector",
"directoryPath" : "target/test-classes/test-objects",
"readonly" : false,
"extraPropertiesStorage": "json",
"cacheTtlSeconds" : 5,
"projections" : [ "fedora:/files => /" ]
}
},
"security" : {
"anonymous" : {
"roles" : ["readonly","readwrite","admin"],
Expand Down
1 change: 1 addition & 0 deletions fcrepo-kernel/src/main/java/org/fcrepo/Datastream.java
Expand Up @@ -461,6 +461,7 @@ private void decorateContentNode(Node contentNode) throws RepositoryException {

public static boolean hasMixin(Node node) throws RepositoryException {
NodeType[] nodeTypes = node.getMixinNodeTypes();
if (nodeTypes == null) return false;
for (NodeType nodeType: nodeTypes) {
if (FEDORA_DATASTREAM.equals(nodeType.getName())) {
return true;
Expand Down
22 changes: 19 additions & 3 deletions fcrepo-kernel/src/main/java/org/fcrepo/FedoraObject.java
Expand Up @@ -52,10 +52,24 @@ public class FedoraObject extends JcrTools implements FedoraJcrTypes {
* @param n an existing JCR node to treat as an fcrepo object
*/
public FedoraObject(final Node n) {
if (node != null) {
logger.debug("Supporting a FedoraObject with null backing Node!");
}
node = n;
try {
if (node.isNew() || !hasMixin(node)) {
logger.debug("Setting fedora:object properties on a nt:folder node {}...", node.getPath());
node.addMixin(FEDORA_OBJECT);
node.addMixin(FEDORA_OWNED);
node.setProperty(FEDORA_OWNERID, "System");
node.setProperty(JCR_LASTMODIFIED, Calendar.getInstance());
node.setProperty(DC_IDENTIFIER, new String[] {
node.getIdentifier(), node.getName()});
}
} catch(RepositoryException e) {
try {
logger.error("Could not add fedora:object mixin properties on {}", node.getPath());
} catch (RepositoryException e1) {
e1.printStackTrace();
}
}
}

/**
Expand All @@ -75,6 +89,7 @@ public FedoraObject(final Session session, final String path)
try {
node = findOrCreateNode(session, path, NT_FOLDER);
if (node.isNew() || !hasMixin(node)) {
logger.debug("Setting fedora:object properties on a nt:folder node {}...", node.getPath());
node.addMixin(FEDORA_OBJECT);
node.addMixin(FEDORA_OWNED);
node.setProperty(FEDORA_OWNERID, session.getUserID());
Expand Down Expand Up @@ -198,6 +213,7 @@ public Collection<String> getModels() throws RepositoryException {

public static boolean hasMixin(Node node) throws RepositoryException {
NodeType[] nodeTypes = node.getMixinNodeTypes();
if (nodeTypes == null) return false;
for (NodeType nodeType: nodeTypes) {
if (FEDORA_OBJECT.equals(nodeType.getName())) {
return true;
Expand Down
Expand Up @@ -118,8 +118,11 @@ public Set<String> getObjectNames(String path) throws RepositoryException {

final Node objects = readOnlySession.getNode(getObjectJcrNodePath(path));
final Builder<String> b = builder();
for (final NodeIterator i = objects.getNodes(); i.hasNext();) {
b.add(i.nextNode().getName());
final NodeIterator i = objects.getNodes();
while (i.hasNext()) {
Node n = i.nextNode();
logger.info("child of type {} is named {} at {}", n.getPrimaryNodeType(), n.getName(), n.getPath());
if (n.isNodeType("nt:folder")) b.add(n.getName());
}
return b.build();

Expand Down
Expand Up @@ -3,47 +3,50 @@

import java.util.Iterator;

import javax.jcr.Node;
import javax.jcr.NodeIterator;

import org.fcrepo.Datastream;

public class DatastreamIterator implements Iterator<Datastream> {

private final NodeIterator nodes;


private Node nextNode;

public DatastreamIterator(final NodeIterator nodes) {
this.nodes = nodes;
}

public Datastream nextDatastream() {
return new Datastream(nodes.nextNode());
if (nodes != null) lookAhead();
}

@Override
public boolean hasNext() {
return nodes.hasNext();
return nextNode != null;
}

@Override
public Datastream next() {
return new Datastream(nodes.nextNode());
Datastream result = new Datastream(nextNode);
lookAhead();
return result;
}

@Override
public void remove() {
nodes.remove();
}

public void skip(final long skipNum) {
nodes.skip(skipNum);
}

public long getSize() {
return nodes.getSize();
}

public long getPosition() {
return nodes.getPosition();

private void lookAhead() {
nextNode = null;
while (nextNode == null && nodes.hasNext()) {
try {
Node n = nodes.nextNode();
if (n.isNodeType("nt:file")) nextNode = n;
else System.out.println("rejected node of type " + n.getPrimaryNodeType());
} catch (Exception e) {
e.printStackTrace();
}
}
}

}
1 change: 0 additions & 1 deletion fcrepo-kernel/src/test/java/org/fcrepo/TestHelpers.java
Expand Up @@ -45,7 +45,6 @@ public static DatastreamIterator mockDatastreamIterator(final String pid,
final Datastream mockDs = mockDatastream(pid, dsId, content);
when(mockIter.hasNext()).thenReturn(true, false);
when(mockIter.next()).thenReturn(mockDs);
when(mockIter.nextDatastream()).thenReturn(mockDs);
return mockIter;
}

Expand Down
Expand Up @@ -72,7 +72,10 @@ public void testCreateObject() throws Exception {
public void testGetObject() throws RepositoryException {
final Session mockSession = mock(Session.class);
final Session mockROSession = mock(Session.class);
final Node mockNode = mock(Node.class);
final String testPath = getObjectJcrNodePath("foo");
when(mockSession.getNode(testPath)).thenReturn(mockNode);
when(mockROSession.getNode(testPath)).thenReturn(mockNode);
final ObjectService testObj = new ObjectService();
testObj.readOnlySession = mockROSession;
testObj.getObject("foo");
Expand Down Expand Up @@ -102,6 +105,7 @@ public void testGetObjectNames() throws RepositoryException {
final Node mockRoot = mock(Node.class);
final Node mockObj = mock(Node.class);
when(mockObj.getName()).thenReturn("foo");
when(mockObj.isNodeType("nt:folder")).thenReturn(true);
final NodeIterator mockIter = mock(NodeIterator.class);
when(mockIter.hasNext()).thenReturn(true, false);
when(mockIter.nextNode()).thenReturn(mockObj).thenThrow(
Expand Down

0 comments on commit 7fbef1f

Please sign in to comment.