Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Support Hash URIs within resources
  • Loading branch information
cbeer committed Oct 10, 2014
1 parent 633f72c commit 4e83a74
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 4 deletions.
Expand Up @@ -1873,6 +1873,23 @@ public void testLdpContainerInteraction() throws Exception {

}

@Test
public void testWithHashUris() throws IOException {
final HttpPost method = postObjMethod("");
method.addHeader("Content-Type", "text/turtle");
final BasicHttpEntity entity = new BasicHttpEntity();
final String rdf = "<> <info:some-predicate> <#abc> .\n" +
"<#abc> <info:rubydora#label> \"asdfg\" .";
entity.setContent(new ByteArrayInputStream(rdf.getBytes()));
method.setEntity(entity);
final HttpResponse response = client.execute(method);
final String content = EntityUtils.toString(response.getEntity());
final int status = response.getStatusLine().getStatusCode();
assertEquals("Didn't get a CREATED response! Got content:\n" + content,
CREATED.getStatusCode(), status);

}

private Date getDateFromModel( final Model model, final Resource subj, final Property pred ) throws Exception {
final StmtIterator stmts = model.listStatements( subj, pred, (String)null );
if ( stmts.hasNext() ) {
Expand Down
1 change: 1 addition & 0 deletions fcrepo-http-api/src/test/resources/spring-test/rest.xml
Expand Up @@ -13,6 +13,7 @@

<!-- Identifier translation chain -->
<util:list id="translationChain" value-type="org.fcrepo.kernel.identifiers.InternalIdentifierConverter">
<bean class="org.fcrepo.kernel.impl.identifiers.HashConverter"/>
<bean class="org.fcrepo.kernel.impl.identifiers.NamespaceConverter"/>
</util:list>

Expand Down
Expand Up @@ -25,6 +25,7 @@
import org.fcrepo.kernel.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.identifiers.IdentifierConverter;
import org.fcrepo.kernel.impl.DatastreamImpl;
import org.fcrepo.kernel.impl.identifiers.HashConverter;
import org.fcrepo.kernel.impl.identifiers.NamespaceConverter;
import org.fcrepo.kernel.impl.services.functions.GetDefaultWorkspace;
import org.glassfish.jersey.uri.UriTemplate;
Expand Down Expand Up @@ -371,8 +372,10 @@ private void setTranslationChain(final List<Converter<String, String>> chained)
}


private static final List<Converter<String,String>> minimalTranslationChain =
singletonList((Converter<String,String>) new NamespaceConverter());
private static final List<Converter<String,String>> minimalTranslationChain
= Lists.newArrayList(
(Converter<String, String>) new NamespaceConverter(),
(Converter<String, String>) new HashConverter());

protected List<Converter<String,String>> getTranslationChain() {
final ApplicationContext context = getApplicationContext();
Expand Down
@@ -0,0 +1,21 @@
package org.fcrepo.kernel.impl.identifiers;

import org.fcrepo.kernel.identifiers.InternalIdentifierConverter;

/**
* @author cabeer
* @since 10/9/14
*/
public class HashConverter extends InternalIdentifierConverter {

@Override
protected String doForward(final String externalId) {
return externalId.replace("#", "/#");
}

@Override
protected String doBackward(final String internalId) {
return internalId.replace("/#", "#");

}
}
Expand Up @@ -42,7 +42,9 @@
import org.fcrepo.kernel.exception.ServerManagedPropertyException;
import org.fcrepo.kernel.identifiers.IdentifierConverter;
import org.fcrepo.kernel.impl.rdf.converters.ValueConverter;
import org.fcrepo.kernel.impl.services.ObjectServiceImpl;
import org.fcrepo.kernel.impl.utils.NodePropertiesTools;
import org.fcrepo.kernel.services.ObjectService;
import org.slf4j.Logger;

import com.google.common.collect.BiMap;
Expand Down Expand Up @@ -79,6 +81,8 @@ public class JcrRdfTools {
private Session session;
private NodePropertiesTools nodePropertiesTools = new NodePropertiesTools();

private final static ObjectService objectService = new ObjectServiceImpl();

/**
* Constructor with even more context.
*
Expand Down Expand Up @@ -154,7 +158,17 @@ public Value createValue(final ValueFactory valueFactory, final RDFNode data, fi
&& (type == REFERENCE || type == WEAKREFERENCE)) {
// reference to another node (by path)
try {
final Node nodeFromGraphSubject = graphSubjects.convert(data.asResource());
final Node nodeFromGraphSubject;
final String absPath = graphSubjects.asString(data.asResource());

if (objectService.exists(session, absPath)) {
nodeFromGraphSubject = session.getNode(absPath);
} else if (absPath.contains("/#")) {
nodeFromGraphSubject = objectService.findOrCreateObject(session, absPath).getNode();
} else {
throw new RepositoryRuntimeException("Unable to find object to operate on");
}

return valueFactory.createValue(nodeFromGraphSubject,
type == WEAKREFERENCE);
} catch (final RepositoryRuntimeException e) {
Expand Down
@@ -0,0 +1,46 @@
package org.fcrepo.kernel.impl.rdf.impl;

import com.google.common.base.Function;
import com.google.common.collect.Iterators;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.rdf.model.Resource;
import org.fcrepo.kernel.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.identifiers.IdentifierConverter;
import org.fcrepo.kernel.utils.iterators.NodeIterator;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import java.util.Collection;
import java.util.Iterator;

/**
* @author cabeer
* @since 10/9/14
*/
public class HashRdfContext extends NodeRdfContext {


/**
* Default constructor.
*
* @param node
* @param graphSubjects
* @throws javax.jcr.RepositoryException
*/
public HashRdfContext(final Node node, final IdentifierConverter<Resource, Node> graphSubjects)
throws RepositoryException {
super(node, graphSubjects);


concat(Iterators.concat(Iterators.transform(new NodeIterator(node().getNodes("#*")), new Function<Node, Iterator<Triple>>() {
@Override
public Iterator<Triple> apply(final Node input) {
try {
return new PropertiesRdfContext(node, graphSubjects);
} catch (final RepositoryException e) {
throw new RepositoryRuntimeException(e);
}
}
})));
}
}
Expand Up @@ -107,6 +107,8 @@ private void putPropertiesIntoContext() throws RepositoryException {
concat(new RootRdfContext(node(), graphSubjects()));
}

concat(new HashRdfContext(node(), graphSubjects()));

}

private Iterator<Triple> triplesFromProperties(final javax.jcr.Node n)
Expand Down
Expand Up @@ -27,6 +27,8 @@
import org.fcrepo.kernel.exception.MalformedRdfException;
import org.fcrepo.kernel.identifiers.IdentifierConverter;
import org.fcrepo.kernel.impl.rdf.JcrRdfTools;
import org.fcrepo.kernel.impl.services.ObjectServiceImpl;
import org.fcrepo.kernel.services.ObjectService;
import org.modeshape.jcr.api.JcrTools;
import org.slf4j.Logger;

Expand Down Expand Up @@ -63,6 +65,8 @@ public class JcrPropertyStatementListener extends StatementListener {

private final List<String> exceptions;

private static final ObjectService objectService = new ObjectServiceImpl();

/**
* Construct a statement listener within the given session
*
Expand Down Expand Up @@ -117,6 +121,9 @@ public void addedStatement(final Statement s) {
subjectNode.addMixin("fedora:blanknode");
skolemizedBnodeMap.put(subject.getId(), subjectNode);
}
} else if (subject.getURI().contains("#")) {
final String absPath = subjects.asString(subject);
subjectNode = objectService.findOrCreateObject(session, absPath).getNode();
} else {
subjectNode = subjects.convert(subject);
}
Expand Down
Expand Up @@ -31,6 +31,8 @@

import com.hp.hpl.jena.rdf.model.AnonId;
import org.fcrepo.kernel.impl.rdf.JcrRdfTools;
import org.fcrepo.kernel.impl.services.ObjectServiceImpl;
import org.fcrepo.kernel.services.ObjectService;
import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.fcrepo.kernel.utils.iterators.RdfStreamConsumer;
import org.modeshape.jcr.api.JcrTools;
Expand Down Expand Up @@ -73,6 +75,8 @@ public abstract class PersistingRdfStreamConsumer implements RdfStreamConsumer {

private static final Logger LOGGER = getLogger(PersistingRdfStreamConsumer.class);

private static final ObjectService objectService = new ObjectServiceImpl();

/**
* Ordinary constructor.
*
Expand Down Expand Up @@ -147,7 +151,17 @@ private Resource getSkolemizedResource(final RDFNode resource) throws Repository
protected void operateOnTriple(final Statement t) {
try {
final Resource subject = t.getSubject();
final Node subjectNode = idTranslator().convert(subject);
final String absPath = idTranslator().asString(subject);

final Node subjectNode;

if (objectService.exists(session, absPath)) {
subjectNode = session.getNode(absPath);
} else if (absPath.contains("/#")) {
subjectNode = objectService.findOrCreateObject(session, absPath).getNode();
} else {
throw new RepositoryRuntimeException("Unable to find subject to operate on");
}

// if this is a user-managed RDF type assertion, update the node's
// mixins. If it isn't, treat it as a "data" property.
Expand Down
1 change: 1 addition & 0 deletions fcrepo-webapp/src/main/resources/spring/rest.xml
Expand Up @@ -20,6 +20,7 @@

<!-- Identifier translation chain -->
<util:list id="translationChain" value-type="org.fcrepo.kernel.identifiers.InternalIdentifierConverter">
<bean class="org.fcrepo.kernel.impl.identifiers.HashConverter"/>
<bean class="org.fcrepo.kernel.impl.identifiers.NamespaceConverter"/>
</util:list>

Expand Down

0 comments on commit 4e83a74

Please sign in to comment.