Commits

Sam Adams  committed f05430f

Initial commit

  • Participants

Comments (0)

Files changed (6)

+
+# maven
+^target/
+/target/
+
+# intellij
+^.idea/
+\.iml$
+
+# eclipse
+^\.classpath$
+/\.classpath$
+^\.project$
+/\.project$
+^\.settings/
+/\.settings/
+
+# temp files
+~$
+\.old$
+^temp/
+/temp/
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>net.chempound</groupId>
+        <artifactId>chempound</artifactId>
+        <version>0.1-SNAPSHOT</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>net.chempound.ext</groupId>
+    <artifactId>chempound-4store</artifactId>
+    <name>Chempound : 4Store</name>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>net.chempound</groupId>
+            <artifactId>chempound-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.chempound</groupId>
+            <artifactId>chempound-app</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>uk.co.magus.fourstore</groupId>
+            <artifactId>4store-client</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+</project>

File src/main/java/net/chempound/ext/fourstore/FourStoreTripleStore.java

+package net.chempound.ext.fourstore;
+
+import com.hp.hpl.jena.rdf.model.Model;
+import net.chempound.datastore.RemoteTripleStore;
+import net.chempound.datastore.TripleStore;
+import net.chempound.rdf.RdfIO;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+import uk.co.magus.fourstore.client.Store;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.util.Collection;
+
+/**
+ * @author Sam Adams
+ */
+@Singleton
+public class FourStoreTripleStore extends RemoteTripleStore implements TripleStore {
+
+    private final Store store;
+    private SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
+
+    @Inject
+    public FourStoreTripleStore(final URI url) {
+        super(createSparqlUri(url));
+        try {
+            this.store = new Store(url.toURL());
+        } catch (final MalformedURLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static String createSparqlUri(final URI url) {
+        return url.resolve("sparql/").toString();
+    }
+
+    @Override
+    public boolean containsNamedModel(final URI uri) {
+        try {
+            final String result = store.query("SELECT ?s WHERE { GRAPH <" + uri.toString() + "> {?s ?p ?o} } LIMIT 1", Store.OutputFormat.SPARQL_XML);
+            final HasResultsHandler handler = new HasResultsHandler();
+            parseResult(result, handler);
+            return handler.hasResults();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public Model getModel(final URI uri) {
+        try {
+            final String result = store.query("SELECT ?s ?p ?o WHERE { GRAPH <" + uri.toString() + "> {?s ?p ?o} }", Store.OutputFormat.SPARQL_XML);
+            final ModelBuildingHandler handler = new ModelBuildingHandler();
+            parseResult(result, handler);
+            return handler.getModel().isEmpty() ? null : handler.getModel();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void parseResult(final String result, final DefaultHandler handler) throws ParserConfigurationException, SAXException, IOException {
+        final SAXParser parser = saxParserFactory.newSAXParser();
+        parser.parse(new ByteArrayInputStream(result.getBytes()), handler);
+    }
+
+    @Override
+    public void saveModel(final URI uri, final Model model) {
+        try {
+            store.add(uri.toString(), RdfIO.toString(model, "N3"), Store.InputFormat.N3);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void updateModel(final URI uri, final Model model) {
+        try {
+            store.append(uri.toString(), RdfIO.toString(model, "N3"), Store.InputFormat.N3);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void deleteModels(final Collection<URI> uris) {
+        for (final URI uri : uris) {
+            deleteModel(uri);
+        }
+    }
+
+    private void deleteModel(final URI uri) {
+        try {
+            store.delete(uri.toString());
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

File src/main/java/net/chempound/ext/fourstore/HasResultsHandler.java

+package net.chempound.ext.fourstore;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class HasResultsHandler extends DefaultHandler {
+
+    private static final String RESULT = "result";
+
+    private boolean hasResults = false;
+
+    @Override
+    public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) throws SAXException {
+        if (RESULT.equals(qName) || RESULT.equals(localName))
+        {
+            hasResults = true;
+        }
+    }
+
+    public boolean hasResults() {
+        return hasResults;
+    }
+}

File src/main/java/net/chempound/ext/fourstore/ModelBuildingHandler.java

+package net.chempound.ext.fourstore;
+
+import com.hp.hpl.jena.rdf.model.*;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ModelBuildingHandler extends DefaultHandler {
+
+    private static enum Binding {SUBJECT, PREDICATE, OBJECT}
+
+    private final ResultsHandler resultsHandler = new ResultsHandler();
+    private final ResultHandler resultHandler = new ResultHandler();
+    private final BindingHandler bindingHandler = new BindingHandler();
+    private final UriHandler uriHandler = new UriHandler();
+    private final BNodeHandler bNodeHandler = new BNodeHandler();
+    private final LiteralHandler literalHandler = new LiteralHandler();
+
+    private final Model model = ModelFactory.createDefaultModel();
+    private final Map<String, Resource> bnodes = new HashMap<String, Resource>();
+
+    private Resource subject;
+    private Property predicate;
+    private RDFNode object;
+
+    private Binding currentBinding;
+    private DefaultHandler delegate = resultsHandler;
+
+    public ModelBuildingHandler() {
+    }
+
+    public Model getModel() {
+        return model;
+    }
+
+    @Override
+    public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) throws SAXException {
+        delegate.startElement(uri, localName, qName, attributes);
+    }
+
+    @Override
+    public void endElement(final String uri, final String localName, final String qName) throws SAXException {
+        delegate.endElement(uri, localName, qName);
+    }
+
+    @Override
+    public void characters(final char[] ch, final int start, final int length) throws SAXException {
+        delegate.characters(ch, start, length);
+    }
+
+
+    private void handleResultStart() {
+        delegate = resultHandler;
+    }
+
+    private void handleResultEnd() {
+        delegate = resultsHandler;
+        model.add(subject, predicate, object);
+        subject = null;
+        predicate = null;
+        object = null;
+    }
+
+
+    private void handleBindingStart(final Attributes attributes) {
+        delegate = bindingHandler;
+        final String name = attributes.getValue("name");
+        if ("s".equals(name)) {
+            currentBinding = Binding.SUBJECT;
+        }
+        else if ("p".equals(name)) {
+            currentBinding = Binding.PREDICATE;
+        }
+        else if ("o".equals(name)) {
+            currentBinding = Binding.OBJECT;
+        }
+    }
+
+    private void handleBindingEnd() {
+        delegate = resultHandler;
+        currentBinding = null;
+    }
+
+
+    private void handleTypeStart(final String qName) {
+        if ("uri".equals(qName)) {
+            delegate = uriHandler;
+        }
+        else if ("bnode".equals(qName)) {
+            delegate = bNodeHandler;
+        }
+        else if ("literal".equals(qName)) {
+            delegate = literalHandler;
+        }
+    }
+
+
+    private void handleUriEnd(final String uri) {
+        delegate = bindingHandler;
+        switch (currentBinding) {
+            case SUBJECT:
+                subject = ResourceFactory.createResource(uri);
+                break;
+
+            case PREDICATE:
+                predicate = ResourceFactory.createProperty(uri);
+                break;
+
+            case OBJECT:
+                object = ResourceFactory.createResource(uri);
+                break;
+        }
+    }
+
+    private void handleBNodeEnd(final String uri) {
+        delegate = bindingHandler;
+        switch (currentBinding) {
+            case SUBJECT:
+                subject = getBNode(uri);
+                break;
+
+            case PREDICATE:
+                throw new IllegalStateException("Binding: " + currentBinding);
+
+            case OBJECT:
+                object = getBNode(uri);
+                break;
+        }
+    }
+
+    private Resource getBNode(final String uri) {
+        final Resource resource = ResourceFactory.createResource();
+        bnodes.put(uri, resource);
+        return resource;
+    }
+
+    private void handleLiteralEnd(final String value) {
+        delegate = bindingHandler;
+        switch (currentBinding) {
+            case SUBJECT:
+            case PREDICATE:
+                throw new IllegalStateException("Binding: " + currentBinding);
+
+            case OBJECT:
+                object = ResourceFactory.createPlainLiteral(value);
+                break;
+        }
+    }
+
+
+    private class ResultsHandler extends DefaultHandler {
+
+        @Override
+        public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) throws SAXException {
+            if ("result".equals(qName) || "result".equals(localName)) {
+                handleResultStart();
+            }
+        }
+    }
+
+    private class ResultHandler extends DefaultHandler {
+
+        @Override
+        public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) throws SAXException {
+            if ("binding".equals(qName) || "binding".equals(localName)) {
+                handleBindingStart(attributes);
+            }
+        }
+
+        @Override
+        public void endElement(final String uri, final String localName, final String qName) throws SAXException {
+            if ("result".equals(qName) || "result".equals(localName)) {
+                handleResultEnd();
+            }
+        }
+    }
+
+    private class BindingHandler extends DefaultHandler {
+
+        @Override
+        public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) throws SAXException {
+            handleTypeStart(qName);
+        }
+
+        @Override
+        public void endElement(final String uri, final String localName, final String qName) throws SAXException {
+            handleBindingEnd();
+        }
+    }
+
+    private class UriHandler extends DefaultHandler {
+
+        private final StringBuilder value = new StringBuilder();
+
+        @Override
+        public void endElement(final String uri, final String localName, final String qName) throws SAXException {
+            final String result = value.toString();
+            value.setLength(0);
+            handleUriEnd(result);
+        }
+
+        @Override
+        public void characters(final char[] ch, final int start, final int length) throws SAXException {
+            value.append(ch, start, length);
+        }
+    }
+
+    private class BNodeHandler extends DefaultHandler {
+
+        private final StringBuilder value = new StringBuilder();
+
+        @Override
+        public void endElement(final String uri, final String localName, final String qName) throws SAXException {
+            final String result = value.toString();
+            value.setLength(0);
+            handleBNodeEnd(result);
+        }
+
+        @Override
+        public void characters(final char[] ch, final int start, final int length) throws SAXException {
+            value.append(ch, start, length);
+        }
+    }
+
+    private class LiteralHandler extends DefaultHandler {
+
+        private final StringBuilder value = new StringBuilder();
+
+        @Override
+        public void endElement(final String uri, final String localName, final String qName) throws SAXException {
+            final String result = value.toString();
+            value.setLength(0);
+            handleLiteralEnd(result);
+        }
+
+        @Override
+        public void characters(final char[] ch, final int start, final int length) throws SAXException {
+            value.append(ch, start, length);
+        }
+    }
+}

File src/test/java/net/chempound/ext/fourstore/FourStoreTripleStoreIT.java

+package net.chempound.ext.fourstore;
+
+import com.hp.hpl.jena.rdf.model.Model;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.net.URI;
+import java.util.Collections;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class FourStoreTripleStoreIT {
+
+    private FourStoreTripleStore tripleStore;
+
+    @Before
+    public void setUp() throws Exception {
+        tripleStore = new FourStoreTripleStore(URI.create("http://localhost:9000"));
+    }
+
+    @Test
+    public void testDeleteModel() {
+        tripleStore.deleteModels(Collections.singleton(URI.create("http://example.com/data")));
+    }
+
+    @Test
+    public void testContainsModel() throws Exception {
+        assertTrue(tripleStore.containsNamedModel(URI.create("http://example.com/data")));
+    }
+
+    @Test
+    public void testDoesNotContainModel() throws Exception {
+        assertFalse(tripleStore.containsNamedModel(URI.create("http://example.com/otherData")));
+    }
+
+    @Test
+    public void testGetModel() throws Exception {
+        final Model model = tripleStore.getModel(URI.create("http://example.com/data"));
+        model.write(System.out, "N3");
+    }
+
+    @Test
+    public void testGetNotExistentModel() throws Exception {
+        assertNull(tripleStore.getModel(URI.create("http://example.com/otherData")));
+    }
+}