Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
refactoring; depends on the unreleaed marmotta snapshot.
  • Loading branch information
cbeer committed Jul 15, 2013
1 parent f10c7bf commit dfad68b
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 93 deletions.
4 changes: 2 additions & 2 deletions fcrepo-transform/pom.xml
Expand Up @@ -43,13 +43,13 @@
<dependency>
<groupId>org.apache.marmotta</groupId>
<artifactId>ldpath-core</artifactId>
<version>3.0.0-incubating</version>
<version>3.1.0-incubating-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>org.apache.marmotta</groupId>
<artifactId>ldpath-backend-jena</artifactId>
<version>3.0.0-incubating</version>
<version>3.1.0-incubating-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.apache.jena</groupId>
Expand Down
Expand Up @@ -17,7 +17,10 @@
package org.fcrepo.transform.http;

import com.codahale.metrics.annotation.Timed;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.hp.hpl.jena.query.Dataset;
import org.apache.marmotta.ldpath.exception.LDPathParseException;
import org.fcrepo.AbstractResource;
Expand All @@ -28,7 +31,6 @@
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.ws.rs.Consumes;
Expand All @@ -39,13 +41,10 @@
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.PathSegment;
import javax.ws.rs.core.Response;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

Expand All @@ -56,12 +55,16 @@
@Path("/{path: .*}/fcr:transform")
public class FedoraTransform extends AbstractResource {

// TODO: this mime type was made up
public static final String APPLICATION_RDF_LDPATH = "application/rdf+ldpath";

@InjectedSession
protected Session session;

private final Logger logger = getLogger(FedoraTransform.class);

/**
*
*
* @param pathList
* @return Binary blob
Expand All @@ -71,87 +74,101 @@ public class FedoraTransform extends AbstractResource {
@Path("{program}")
@Produces({MediaType.APPLICATION_JSON})
@Timed
public List<Map<String, List<String>>> getLdpathResource(@PathParam("path")
final List<PathSegment> pathList, @PathParam("program") final String program) throws RepositoryException, LDPathParseException {
public List<Map<String, Collection<String>>> evaluateLdpathProgram(
@PathParam("path") final List<PathSegment> pathList,
@PathParam("program") final String program)
throws RepositoryException, LDPathParseException {

try {
final String path = toPath(pathList);

final FedoraResource object = nodeService.getObject(session, path);

final InputStream ldpathProgram = LDPathService.getLdpathProgram(session, program, object.getNode());

if (ldpathProgram == null) {
throw new PathNotFoundException("Unable to find LDPath program " + program);
}

final Dataset propertiesDataset = object.getPropertiesDataset();

logger.info("Evaluating LDPath Program for object {}", object);
final Map<String,Collection<?>> collectionMap = LDPathService.programQuery(session, propertiesDataset, new InputStreamReader(ldpathProgram));
final InputStream ldpathProgram = LDPathService.getLdpathProgram(object.getNode(), program);

List<Map<String, List<String>>> result = transformLdpathOutputToSomethingSerializable(collectionMap);

logger.info("LDPath result {}", result);
return result;
return evaluateLdpathProgram(object, ldpathProgram);
} finally {
session.logout();
}
}

/**
* Get the LDPath output as a JSON stream appropriate for e.g. Solr
*
* @param pathList
* @param requestBodyStream
* @return
* @throws RepositoryException
* @throws LDPathParseException
*/
@POST
@Consumes({"application/rdf+ldpath"})
@Consumes({APPLICATION_RDF_LDPATH})
@Produces({MediaType.APPLICATION_JSON})
@Timed
public List<Map<String, List<String>>> evaluateLdpathProgram(@PathParam("path")
final List<PathSegment> pathList, final InputStream requestBodyStream) throws RepositoryException, LDPathParseException {
public List<Map<String, Collection<String>>> evaluateLdpathProgram(
@PathParam("path") final List<PathSegment> pathList,
final InputStream requestBodyStream)
throws RepositoryException, LDPathParseException {

try {
final String path = toPath(pathList);

final FedoraResource object = nodeService.getObject(session, path);

final Dataset propertiesDataset = object.getPropertiesDataset();

logger.info("Evaluating LDPath Program for object {}", object);
final Map<String,Collection<?>> collectionMap = LDPathService.programQuery(session, propertiesDataset, new InputStreamReader(requestBodyStream));

List<Map<String, List<String>>> result = transformLdpathOutputToSomethingSerializable(collectionMap);

logger.info("LDPath result {}", result);
return result;

return evaluateLdpathProgram(object, requestBodyStream);
} finally {
session.logout();
}

}

private List<Map<String, List<String>>> transformLdpathOutputToSomethingSerializable(Map<String, Collection<?>> collectionMap) {
private List<Map<String, Collection<String>>> evaluateLdpathProgram(
final FedoraResource object,
final InputStream programStream)
throws RepositoryException, LDPathParseException {

Map<String, List<String>> result = new HashMap<String, List<String>>();
final Dataset propertiesDataset = object.getPropertiesDataset();

for (Map.Entry<String, Collection<?>> e : collectionMap.entrySet()) {
logger.info("Evaluating LDPath Program for object {}", object);
final Map<String,Collection<?>> collectionMap =
LDPathService.programQuery(
propertiesDataset,
new InputStreamReader(programStream));

List<String> s = new ArrayList<String>();
List<Map<String, Collection<String>>> result = transformLdpathOutputToSomethingSerializable(collectionMap);

logger.info("LDPath result {}", result);
return result;
}

for (Object o : e.getValue()) {
s.add(o.toString());
}
/**
* In order for the JAX-RS serialization magic to work, we have to turn the map
* @param collectionMap
* @return
*/
private List<Map<String, Collection<String>>> transformLdpathOutputToSomethingSerializable(Map<String, Collection<?>> collectionMap) {

result.put(e.getKey(), s);
}
Map<String, Collection<String>> result =
Maps.transformValues(collectionMap, WILDCARD_COLLECTION_TO_STRING_COLLECTION);

return ImmutableList.of(result);
}

private static final Function<Collection<?>,Collection<String>> WILDCARD_COLLECTION_TO_STRING_COLLECTION =
new Function<Collection<?>, Collection<String>>() {

@Override
public Collection<String> apply(Collection<?> input) {
return Collections2.transform(input, ANYTHING_TO_STRING_FUNCTION);
}
};


private static final Function<Object,String> ANYTHING_TO_STRING_FUNCTION =
new Function<Object, String>() {
@Override
public String apply(Object input) {
return input.toString();
}
};


}
Expand Up @@ -17,7 +17,7 @@
package org.fcrepo.transform.services;

import com.google.common.collect.ImmutableList;
import com.hp.hpl.jena.graph.Node;
import com.google.common.collect.Iterables;
import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.RDFNode;
Expand All @@ -26,15 +26,13 @@
import org.apache.marmotta.ldpath.LDPath;
import org.apache.marmotta.ldpath.backend.jena.GenericJenaBackend;
import org.apache.marmotta.ldpath.exception.LDPathParseException;
import org.apache.marmotta.ldpath.parser.Configuration;
import org.apache.marmotta.ldpath.parser.DefaultConfiguration;
import org.fcrepo.session.SessionFactory;
import org.fcrepo.utils.JcrRdfTools;
import org.modeshape.jcr.api.JcrTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.nodetype.NodeType;
Expand All @@ -47,9 +45,13 @@
import static org.fcrepo.rdf.SerializationUtils.getDatasetSubject;
import static org.fcrepo.rdf.SerializationUtils.unifyDatasetModel;

/**
* Utilities for working with LDPath
*/
@Component
public class LDPathService {

public static final String CONFIGURATION_FOLDER = "/fedora:system/fedora:transform/fedora:ldpath/";
@Autowired
protected SessionFactory sessions;

Expand All @@ -68,95 +70,81 @@ public class LDPathService {
public void initialize() throws RepositoryException, IOException {

final Session session = sessions.getSession();

// register our CND
jcrTools.registerNodeTypes(session, "ldpath.cnd");

// create the configuration base path
jcrTools.findOrCreateNode(session, "/fedora:system/fedora:transform", "fedora:configuration", "fedora:node_type_configuration");
final javax.jcr.Node node = jcrTools.findOrCreateNode(session, "/fedora:system/fedora:transform/fedora:ldpath/default", NodeType.NT_FOLDER, NodeType.NT_FOLDER);
final Node node = jcrTools.findOrCreateNode(session, CONFIGURATION_FOLDER + "default", NodeType.NT_FOLDER, NodeType.NT_FOLDER);

if (node.isNew()) {
final javax.jcr.Node base_config = node.addNode(NodeType.NT_BASE, NodeType.NT_FILE);
// register an initial demo program
if (!node.hasNode(NodeType.NT_BASE)) {
final Node base_config = node.addNode(NodeType.NT_BASE, NodeType.NT_FILE);
jcrTools.uploadFile(session, base_config.getPath(), getClass().getResourceAsStream("/ldpath/default/nt_base_ldpath_program.txt") );
}

session.save();
session.logout();
}

public static InputStream getLdpathProgram(final Session session, final String program, final javax.jcr.Node node) throws RepositoryException {
/**
* Get the LDPath program to execute for a node type
* @param node
* @param program
* @return
* @throws RepositoryException
*/
public static InputStream getLdpathProgram(final Node node, final String program) throws RepositoryException {

final javax.jcr.Node programNode = session.getNode("/fedora:system/fedora:transform/fedora:ldpath/" + program);
final Node programNode = node.getSession().getNode(CONFIGURATION_FOLDER + program);

final NodeType primaryNodeType = node.getPrimaryNodeType();

if (programNode.hasNode(primaryNodeType.toString())) {

return programNode.getNode(primaryNodeType.toString()).getNode("jcr:content").getProperty("jcr:data").getBinary().getStream();

} else {
final NodeType[] supertypes = primaryNodeType.getSupertypes();
final NodeType[] supertypes = primaryNodeType.getSupertypes();

final Iterable<NodeType> nodeTypes = Iterables.concat(ImmutableList.of(primaryNodeType), ImmutableList.copyOf(supertypes));

for (NodeType supertype : supertypes) {
if (programNode.hasNode(supertype.toString())) {
return programNode.getNode(supertype.toString()).getNode("jcr:content").getProperty("jcr:data").getBinary().getStream();
}
for (NodeType nodeType : nodeTypes) {
if (programNode.hasNode(nodeType.toString())) {
return programNode.getNode(nodeType.toString()).getNode("jcr:content").getProperty("jcr:data").getBinary().getStream();
}

}

return null;
}

/**
* Execute an LDPath Program against a Dataset
* @param session
* @param dataset
* @param reader
* @return
* @throws RepositoryException
* @throws LDPathParseException
*/
public static Map<String, Collection<?>> programQuery(final Session session, final Dataset dataset, final Reader reader) throws RepositoryException, LDPathParseException {
final LDPath<RDFNode> ldpathForResource = getLdpathForResource(session, dataset);
public static Map<String, Collection<?>> programQuery(final Dataset dataset, final Reader reader) throws RepositoryException, LDPathParseException {
final LDPath<RDFNode> ldpathForResource = getLdpathForResource(dataset);

final Node node = getDatasetSubject(dataset);
final Resource context = ResourceFactory.createResource(node.getURI());
final Resource context = ResourceFactory.createResource(getDatasetSubject(dataset).getURI());

return ldpathForResource.programQuery(context, reader);
}

/**
* Get the LDPath resource for an object
* @param session
* @param dataset
* @return
* @throws RepositoryException
*/
public static LDPath<RDFNode> getLdpathForResource(final Session session, final Dataset dataset) throws RepositoryException {
private static LDPath<RDFNode> getLdpathForResource(final Dataset dataset) throws RepositoryException {

final Model model = unifyDatasetModel(dataset);

final GenericJenaBackend genericJenaBackend = new GenericJenaBackend(model);

LDPath<RDFNode> ldpath = new LDPath<RDFNode>(genericJenaBackend, getDefaultConfiguration(session));
LDPath<RDFNode> ldpath = new LDPath<RDFNode>(genericJenaBackend);

return ldpath;
}

/**
* Get the LDPath Configuration with defaults for JCR
* @param session
* @return
* @throws RepositoryException
*/
private static Configuration<RDFNode> getDefaultConfiguration(final Session session) throws RepositoryException {

final Configuration<RDFNode> config = new DefaultConfiguration<RDFNode>();
final Model namespaceModel = JcrRdfTools.getJcrNamespaceModel(session);

for ( Map.Entry<String, String> e : namespaceModel.getNsPrefixMap().entrySet()) {
config.addNamespace(e.getKey(), e.getValue());
}

return config;
}
}
Expand Up @@ -53,11 +53,12 @@ public void shouldDoStuff() throws RepositoryException, LDPathParseException {

final FedoraObject object = objectService.createObject(session, "/testObject");

String s = "id = . :: xsd:string ;\n" +
String s = "@prefix fedora-internal : <info:fedora/fedora-system:def/internal#>\n" +
"id = . :: xsd:string ;\n" +
"uuid = fedora-internal:uuid :: xsd:string;";
final StringReader stringReader = new StringReader(s);

final Map<String, Collection<?>> stuff = LDPathService.programQuery(session, object.getPropertiesDataset(), stringReader);
final Map<String, Collection<?>> stuff = LDPathService.programQuery(object.getPropertiesDataset(), stringReader);

assertTrue(stuff.containsKey("id"));
assertTrue(stuff.containsKey("uuid"));
Expand Down

0 comments on commit dfad68b

Please sign in to comment.