diff --git a/pom.xml b/pom.xml
index 21453b1..a4959e0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,6 +22,7 @@
UTF-8
4.0.0-beta-05-SNAPSHOT
2.14.0
+ 3.3.2
4.3.5
1.1.0
2.12.1
@@ -136,6 +137,19 @@
org.apache.httpcomponents
httpclient
+ ${httpclient.version}
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons.lang3.version}
+
+
+
+ org.glassfish.jersey.core
+ jersey-common
+ ${jersey.version}
@@ -153,6 +167,18 @@
+
+
+ org.apache.jena
+ jena-arq
+ ${jena.version}
+
+
+
+ org.apache.jena
+ jena-core
+ ${jena.version}
+
javax.ws.rs
@@ -212,20 +238,6 @@
test
-
- org.apache.jena
- jena-arq
- ${jena.version}
- test
-
-
-
- org.apache.jena
- jena-core
- ${jena.version}
- test
-
-
javax.jcr
jcr
@@ -259,6 +271,8 @@
**/src/main/java/**
**/src/test/java/**
+ **/examples/fcrepo-camel-solr/src/main/java/**
+ **/examples/fcrepo-camel-solr-scala/src/main/scala/**
target/**
diff --git a/src/main/java/org/fcrepo/camel/FedoraEndpoint.java b/src/main/java/org/fcrepo/camel/FedoraEndpoint.java
index 8840ed7..9733ca4 100644
--- a/src/main/java/org/fcrepo/camel/FedoraEndpoint.java
+++ b/src/main/java/org/fcrepo/camel/FedoraEndpoint.java
@@ -34,7 +34,7 @@
@UriEndpoint(scheme = "fcrepo")
public class FedoraEndpoint extends DefaultEndpoint {
- public static final String FCREPO_BASEURL = "FCREPO_BASEURL";
+ public static final String FCREPO_BASE_URL = "FCREPO_BASE_URL";
public static final String FCREPO_IDENTIFIER = "FCREPO_IDENTIFIER";
diff --git a/src/main/java/org/fcrepo/camel/processor/SparqlDeleteProcessor.java b/src/main/java/org/fcrepo/camel/processor/SparqlDeleteProcessor.java
new file mode 100644
index 0000000..3cdef86
--- /dev/null
+++ b/src/main/java/org/fcrepo/camel/processor/SparqlDeleteProcessor.java
@@ -0,0 +1,116 @@
+/**
+ * Copyright 2014 DuraSpace, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.fcrepo.camel.processor;
+
+import static org.apache.camel.Exchange.HTTP_METHOD;
+import static org.apache.camel.Exchange.CONTENT_TYPE;
+import static org.fcrepo.camel.FedoraEndpoint.FCREPO_BASE_URL;
+import static org.fcrepo.camel.FedoraEndpoint.FCREPO_IDENTIFIER;
+import static org.fcrepo.jms.headers.DefaultMessageFactory.BASE_URL_HEADER_NAME;
+import static org.fcrepo.jms.headers.DefaultMessageFactory.IDENTIFIER_HEADER_NAME;
+import static com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel;
+
+import org.apache.camel.Processor;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.commons.lang3.StringUtils;
+
+import com.hp.hpl.jena.graph.Node_URI;
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.StmtIterator;
+
+import java.io.InputStream;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Represends a message processor that deletes objects from an
+ * external triplestore.
+ *
+ * @author Aaron Coburn
+ * @since Nov 8, 2014
+ */
+public class SparqlDeleteProcessor implements Processor {
+ /**
+ * Define how the message should be processed.
+ */
+ public void process(final Exchange exchange) throws Exception {
+
+ final Message in = exchange.getIn();
+ final Model model = createDefaultModel().read(in.getBody(InputStream.class), null);
+ final StmtIterator triples = model.listStatements();
+ String subject = null;
+
+ if (in.getHeader(FCREPO_BASE_URL) != null) {
+ subject = in.getHeader(FCREPO_BASE_URL, String.class);
+ } else if (in.getHeader(BASE_URL_HEADER_NAME) != null) {
+ subject = in.getHeader(BASE_URL_HEADER_NAME, String.class);
+ } else {
+ throw new Exception("No baseURL header available!");
+ }
+
+ if (in.getHeader(FCREPO_IDENTIFIER) != null) {
+ subject += in.getHeader(FCREPO_IDENTIFIER);
+ } else if (in.getHeader(IDENTIFIER_HEADER_NAME) != null) {
+ subject += in.getHeader(IDENTIFIER_HEADER_NAME);
+ }
+
+ // build list of triples to delete
+ final Set uris = new HashSet();
+ while ( triples.hasNext() ) {
+ final Triple triple = triples.next().asTriple();
+
+ // add subject uri, if it is part of this object
+ if ( triple.getSubject().isURI() ) {
+ final String uri = ((Node_URI)triple.getSubject()).getURI();
+
+ if (uriMatches(subject, uri) ) {
+ uris.add(uri);
+ }
+ }
+
+ // add object uri, if it is part of this object
+ if ( triple.getObject().isURI() ) {
+ final String uri = ((Node_URI)triple.getObject()).getURI();
+ if (uriMatches(subject, uri) ) {
+ uris.add(uri);
+ }
+ }
+ }
+
+ // build delete commands
+ final List commands = new ArrayList();
+ for (final String uri : uris) {
+ commands.add("DELETE WHERE { <" + uri + "> ?p ?o }");
+ }
+
+ exchange.getIn().setBody(StringUtils.join(commands, ";\n"));
+ exchange.getIn().setHeader(HTTP_METHOD, "POST");
+ exchange.getIn().setHeader(CONTENT_TYPE, "application/sparql-update");
+ }
+
+ private static boolean uriMatches(final String resource, final String candidate) {
+ // All triples that will match this logic are ones that:
+ // - have a candidate subject or object that equals the target resource of removal, or
+ // - have a candidate subject or object that is prefixed with the resource of removal
+ // (therefore catching all children).
+ return resource.equals(candidate) || candidate.startsWith(resource + "/")
+ || candidate.startsWith(resource + "#");
+ }
+}
diff --git a/src/main/java/org/fcrepo/camel/processor/SparqlDescribeProcessor.java b/src/main/java/org/fcrepo/camel/processor/SparqlDescribeProcessor.java
new file mode 100644
index 0000000..d034206
--- /dev/null
+++ b/src/main/java/org/fcrepo/camel/processor/SparqlDescribeProcessor.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright 2014 DuraSpace, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.fcrepo.camel.processor;
+
+import static org.apache.camel.Exchange.HTTP_METHOD;
+import static org.apache.camel.Exchange.CONTENT_TYPE;
+import static org.apache.camel.Exchange.ACCEPT_CONTENT_TYPE;
+import static org.fcrepo.camel.FedoraEndpoint.FCREPO_BASE_URL;
+import static org.fcrepo.camel.FedoraEndpoint.FCREPO_IDENTIFIER;
+import static org.fcrepo.jms.headers.DefaultMessageFactory.BASE_URL_HEADER_NAME;
+import static org.fcrepo.jms.headers.DefaultMessageFactory.IDENTIFIER_HEADER_NAME;
+
+import org.apache.camel.Processor;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+
+/**
+ * Represents a Processor class that formulates a Sparql DESCRIBE query
+ * that is ready to be POSTed to a Sparql endpoint.
+ *
+ * The processor expects the following headers:
+ * org.fcrepo.jms.identifier
+ * org.fcrepo.jms.baseURL
+ * each of which can be overridden with the following:
+ * FCREPO_IDENTIFIER
+ * FCREPO_BASE_URL
+ *
+ * @author Aaron Coburn
+ * @since November 6, 2014
+ */
+public class SparqlDescribeProcessor implements Processor {
+ /**
+ * Define how this message should be processed
+ */
+ public void process(final Exchange exchange) throws Exception {
+
+ final Message in = exchange.getIn();
+
+ String subject = null;
+
+ if (in.getHeader(FCREPO_BASE_URL) != null) {
+ subject = in.getHeader(FCREPO_BASE_URL, String.class);
+ } else if (in.getHeader(BASE_URL_HEADER_NAME) != null) {
+ subject = in.getHeader(BASE_URL_HEADER_NAME, String.class);
+ } else {
+ throw new Exception("No baseURL header available!");
+ }
+
+ if (in.getHeader(FCREPO_IDENTIFIER) != null) {
+ subject += in.getHeader(FCREPO_IDENTIFIER);
+ } else if (in.getHeader(IDENTIFIER_HEADER_NAME) != null) {
+ subject += in.getHeader(IDENTIFIER_HEADER_NAME);
+ }
+
+ exchange.getIn().setBody("query=DESCRIBE <" + subject + ">");
+ exchange.getIn().setHeader(HTTP_METHOD, "POST");
+ exchange.getIn().setHeader(ACCEPT_CONTENT_TYPE, "application/rdf+xml");
+ exchange.getIn().setHeader(CONTENT_TYPE, "application/x-www-form-urlencoded");
+ }
+}
diff --git a/src/main/java/org/fcrepo/camel/processor/SparqlInsertProcessor.java b/src/main/java/org/fcrepo/camel/processor/SparqlInsertProcessor.java
new file mode 100644
index 0000000..2b41002
--- /dev/null
+++ b/src/main/java/org/fcrepo/camel/processor/SparqlInsertProcessor.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright 2014 DuraSpace, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.fcrepo.camel.processor;
+
+import static org.apache.camel.Exchange.HTTP_METHOD;
+import static org.apache.camel.Exchange.CONTENT_TYPE;
+import static com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel;
+
+import org.apache.camel.Processor;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.StmtIterator;
+import com.hp.hpl.jena.sparql.modify.request.QuadDataAcc;
+import com.hp.hpl.jena.sparql.modify.request.UpdateDataInsert;
+import com.hp.hpl.jena.update.UpdateRequest;
+
+import java.io.InputStream;
+
+/**
+ * Represents a processor for creating the sparql-update message to
+ * be passed to an external triplestore.
+ *
+ * @author Aaron Coburn
+ * @since Nov 8, 2014
+ */
+public class SparqlInsertProcessor implements Processor {
+ /**
+ * Define how the message is processed.
+ */
+ public void process(final Exchange exchange) throws Exception {
+
+ final Message in = exchange.getIn();
+ final Model model = createDefaultModel().read(in.getBody(InputStream.class), null, "N-TRIPLE");
+ final StmtIterator triples = model.listStatements();
+ final QuadDataAcc add = new QuadDataAcc();
+ while (triples.hasNext()) {
+ add.addTriple(triples.nextStatement().asTriple());
+ }
+ final UpdateRequest request = new UpdateRequest(new UpdateDataInsert(add));
+
+ exchange.getIn().setBody(request.toString());
+ exchange.getIn().setHeader(HTTP_METHOD, "POST");
+ exchange.getIn().setHeader(CONTENT_TYPE, "application/sparql-update");
+ }
+}
diff --git a/src/test/java/org/fcrepo/camel/SparqlDeleteProcessorTest.java b/src/test/java/org/fcrepo/camel/SparqlDeleteProcessorTest.java
new file mode 100644
index 0000000..b210816
--- /dev/null
+++ b/src/test/java/org/fcrepo/camel/SparqlDeleteProcessorTest.java
@@ -0,0 +1,118 @@
+/**
+ * Copyright 2014 DuraSpace, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.fcrepo.camel.integration;
+
+import static org.apache.camel.Exchange.HTTP_METHOD;
+import static org.apache.camel.Exchange.CONTENT_TYPE;
+import static org.fcrepo.jms.headers.DefaultMessageFactory.IDENTIFIER_HEADER_NAME;
+import static org.fcrepo.jms.headers.DefaultMessageFactory.BASE_URL_HEADER_NAME;
+import static org.fcrepo.camel.FedoraEndpoint.FCREPO_IDENTIFIER;
+import static org.fcrepo.camel.FedoraEndpoint.FCREPO_BASE_URL;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.fcrepo.camel.processor.SparqlDeleteProcessor;
+import org.junit.Test;
+
+/**
+ * Test adding a non-RDF resource
+ * @author Aaron Coburn
+ * @since November 7, 2014
+ */
+public class SparqlDeleteProcessorTest extends CamelTestSupport {
+
+ @EndpointInject(uri = "mock:result")
+ protected MockEndpoint resultEndpoint;
+
+ @Produce(uri = "direct:start")
+ protected ProducerTemplate template;
+
+ @Test
+ public void testDelete() throws IOException, InterruptedException {
+ final String base = "http://localhost/rest";
+ final String path = "/path/book3";
+ final String incomingDoc =
+ "" +
+ " " +
+ " Middlemarch" +
+ " " +
+ " " +
+ " George Elliot" +
+ " " +
+ " Elliot" +
+ " George" +
+ " " +
+ " " +
+ " " +
+ "";
+
+ // Assertions
+ resultEndpoint.expectedBodiesReceived(
+ "DELETE WHERE { <" + base + path + "> ?p ?o };\n" +
+ "DELETE WHERE { <" + base + path + "/appendix> ?p ?o }");
+ resultEndpoint.expectedHeaderReceived(CONTENT_TYPE, "application/sparql-update");
+ resultEndpoint.expectedHeaderReceived(HTTP_METHOD, "POST");
+
+ // Test
+ final Map headers = new HashMap<>();
+ headers.put(FCREPO_BASE_URL, base);
+ headers.put(FCREPO_IDENTIFIER, path);
+ template.sendBodyAndHeaders(incomingDoc, headers);
+
+ headers.clear();
+ headers.put(BASE_URL_HEADER_NAME, base);
+ headers.put(IDENTIFIER_HEADER_NAME, path);
+ template.sendBodyAndHeaders(incomingDoc, headers);
+
+ headers.clear();
+ headers.put(BASE_URL_HEADER_NAME, base);
+ headers.put(FCREPO_IDENTIFIER, path);
+ template.sendBodyAndHeaders(incomingDoc, headers);
+
+ headers.clear();
+ headers.put(FCREPO_BASE_URL, base);
+ headers.put(IDENTIFIER_HEADER_NAME, path);
+ template.sendBodyAndHeaders(incomingDoc, headers);
+
+ // Confirm that assertions passed
+ resultEndpoint.expectedMessageCount(4);
+ resultEndpoint.assertIsSatisfied();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws IOException {
+ from("direct:start")
+ .process(new SparqlDeleteProcessor())
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git a/src/test/java/org/fcrepo/camel/SparqlDescribeProcessorTest.java b/src/test/java/org/fcrepo/camel/SparqlDescribeProcessorTest.java
new file mode 100644
index 0000000..ab19ed6
--- /dev/null
+++ b/src/test/java/org/fcrepo/camel/SparqlDescribeProcessorTest.java
@@ -0,0 +1,100 @@
+/**
+ * Copyright 2014 DuraSpace, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.fcrepo.camel.integration;
+
+import static org.apache.camel.Exchange.HTTP_METHOD;
+import static org.apache.camel.Exchange.CONTENT_TYPE;
+import static org.apache.camel.Exchange.ACCEPT_CONTENT_TYPE;
+import static org.fcrepo.camel.FedoraEndpoint.FCREPO_IDENTIFIER;
+import static org.fcrepo.camel.FedoraEndpoint.FCREPO_BASE_URL;
+import static org.fcrepo.jms.headers.DefaultMessageFactory.IDENTIFIER_HEADER_NAME;
+import static org.fcrepo.jms.headers.DefaultMessageFactory.BASE_URL_HEADER_NAME;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.fcrepo.camel.processor.SparqlDescribeProcessor;
+import org.junit.Test;
+
+/**
+ * Test adding a non-RDF resource
+ * @author Aaron Coburn
+ * @since November 7, 2014
+ */
+public class SparqlDescribeProcessorTest extends CamelTestSupport {
+
+ @EndpointInject(uri = "mock:result")
+ protected MockEndpoint resultEndpoint;
+
+ @Produce(uri = "direct:start")
+ protected ProducerTemplate template;
+
+ @Test
+ public void testDescribe() throws IOException, InterruptedException {
+ final String base = "http://localhost/rest";
+ final String path = "/path/a/b/c/d";
+
+ // Assertions
+ resultEndpoint.expectedBodiesReceived("query=DESCRIBE <" + base + path + ">");
+ resultEndpoint.expectedHeaderReceived(CONTENT_TYPE, "application/x-www-form-urlencoded");
+ resultEndpoint.expectedHeaderReceived(HTTP_METHOD, "POST");
+ resultEndpoint.expectedHeaderReceived(ACCEPT_CONTENT_TYPE, "application/rdf+xml");
+
+ // Test
+ final Map headers = new HashMap<>();
+ headers.put(FCREPO_BASE_URL, base);
+ headers.put(FCREPO_IDENTIFIER, path);
+ template.sendBodyAndHeaders(null, headers);
+
+ headers.clear();
+ headers.put(BASE_URL_HEADER_NAME, base);
+ headers.put(IDENTIFIER_HEADER_NAME, path);
+ template.sendBodyAndHeaders(null, headers);
+
+ headers.clear();
+ headers.put(BASE_URL_HEADER_NAME, base);
+ headers.put(FCREPO_IDENTIFIER, path);
+ template.sendBodyAndHeaders(null, headers);
+
+ headers.clear();
+ headers.put(FCREPO_BASE_URL, base);
+ headers.put(IDENTIFIER_HEADER_NAME, path);
+ template.sendBodyAndHeaders(null, headers);
+
+ // Confirm that assertions passed
+ resultEndpoint.expectedMessageCount(4);
+ resultEndpoint.assertIsSatisfied();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws IOException {
+ from("direct:start")
+ .process(new SparqlDescribeProcessor())
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git a/src/test/java/org/fcrepo/camel/SparqlInsertProcessorTest.java b/src/test/java/org/fcrepo/camel/SparqlInsertProcessorTest.java
new file mode 100644
index 0000000..fbca3cc
--- /dev/null
+++ b/src/test/java/org/fcrepo/camel/SparqlInsertProcessorTest.java
@@ -0,0 +1,119 @@
+/**
+ * Copyright 2014 DuraSpace, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.fcrepo.camel.integration;
+
+import static org.apache.camel.Exchange.HTTP_METHOD;
+import static org.apache.commons.lang3.StringUtils.normalizeSpace;
+import static org.apache.commons.lang3.StringUtils.join;
+import static org.apache.commons.lang3.ArrayUtils.reverse;
+import static org.fcrepo.camel.integration.FedoraTestUtils.getFcrepoEndpointUri;
+import static org.fcrepo.camel.integration.FedoraTestUtils.getN3Document;
+import static org.fcrepo.camel.FedoraEndpoint.FCREPO_BASE_URL;
+import static org.fcrepo.camel.FedoraEndpoint.FCREPO_IDENTIFIER;
+import static org.fcrepo.jms.headers.DefaultMessageFactory.BASE_URL_HEADER_NAME;
+import static org.fcrepo.jms.headers.DefaultMessageFactory.IDENTIFIER_HEADER_NAME;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.fcrepo.camel.processor.SparqlInsertProcessor;
+import org.junit.Test;
+
+/**
+ * Test adding a non-RDF resource
+ * @author Aaron Coburn
+ * @since November 7, 2014
+ */
+public class SparqlInsertProcessorTest extends CamelTestSupport {
+
+ @EndpointInject(uri = "mock:result")
+ protected MockEndpoint resultEndpoint;
+
+ @Produce(uri = "direct:start")
+ protected ProducerTemplate template;
+
+ @Test
+ public void testDescribe() throws IOException, InterruptedException {
+ final String base = "http://localhost/rest";
+ final String path = "/path/a/b/c/d";
+ final String document = getN3Document();
+
+ // Reverse the lines as the RDF is serialized in opposite order
+ final String[] lines = document.split("\n");
+ reverse(lines);
+
+ // Assertions
+ resultEndpoint.expectedBodiesReceived("INSERT DATA { " + join(lines, " ") + " }");
+ resultEndpoint.expectedHeaderReceived("Content-Type", "application/sparql-update");
+ resultEndpoint.expectedHeaderReceived(HTTP_METHOD, "POST");
+
+ // Test
+ final Map headers = new HashMap<>();
+ headers.put(FCREPO_BASE_URL, base);
+ headers.put(FCREPO_IDENTIFIER, path);
+ template.sendBodyAndHeaders(document, headers);
+
+ headers.clear();
+ headers.put(BASE_URL_HEADER_NAME, base);
+ headers.put(IDENTIFIER_HEADER_NAME, path);
+ template.sendBodyAndHeaders(document, headers);
+
+ headers.clear();
+ headers.put(BASE_URL_HEADER_NAME, base);
+ headers.put(FCREPO_IDENTIFIER, path);
+ template.sendBodyAndHeaders(document, headers);
+
+ headers.clear();
+ headers.put(FCREPO_BASE_URL, base);
+ headers.put(IDENTIFIER_HEADER_NAME, path);
+ template.sendBodyAndHeaders(document, headers);
+
+ // Confirm that assertions passed
+ resultEndpoint.expectedMessageCount(4);
+ resultEndpoint.assertIsSatisfied();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws IOException {
+
+ final String fcrepo_uri = getFcrepoEndpointUri();
+
+ from("direct:start")
+ .process(new SparqlInsertProcessor())
+ // Normalize the whitespace to make it easier to compare
+ .process(new Processor() {
+ public void process(final Exchange exchange) throws Exception {
+ final String payload = exchange.getIn().getBody(String.class);
+ exchange.getIn().setBody(normalizeSpace(payload));
+ }
+ })
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git a/src/test/java/org/fcrepo/camel/integration/FedoraSparqlIT.java b/src/test/java/org/fcrepo/camel/integration/FedoraSparqlIT.java
new file mode 100644
index 0000000..86ab1d8
--- /dev/null
+++ b/src/test/java/org/fcrepo/camel/integration/FedoraSparqlIT.java
@@ -0,0 +1,124 @@
+/**
+ * Copyright 2014 DuraSpace, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.fcrepo.camel.integration;
+
+import static org.apache.camel.Exchange.CONTENT_TYPE;
+import static org.apache.camel.Exchange.HTTP_METHOD;
+import static java.lang.System.getProperty;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.io.IOException;
+
+import org.fcrepo.camel.processor.SparqlInsertProcessor;
+import org.fcrepo.camel.processor.SparqlDescribeProcessor;
+import org.fcrepo.camel.processor.SparqlDeleteProcessor;
+
+import org.apache.camel.Produce;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.builder.xml.XPathBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * Represents an integration test for interacting with an external triplestore.
+ *
+ * @author Aaron Coburn
+ * @since Nov 8, 2014
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({"/spring-test/test-container.xml"})
+public class FedoraSparqlIT extends CamelTestSupport {
+
+ @EndpointInject(uri = "mock:result")
+ protected MockEndpoint resultEndpoint;
+
+ @Produce(uri = "direct:start")
+ protected ProducerTemplate template;
+
+ @Test
+ public void testSparql() throws Exception {
+ // Assertions
+ resultEndpoint.expectedMessageCount(1);
+
+ // Setup
+ final Map headers = new HashMap();
+ headers.put(HTTP_METHOD, "POST");
+ headers.put(CONTENT_TYPE, "text/turtle");
+
+ final String fullPath = template.requestBodyAndHeaders(
+ "direct:setup", FedoraTestUtils.getTurtleDocument(), headers, String.class);
+
+ final String identifier = fullPath.replaceAll(FedoraTestUtils.getFcrepoBaseUrl(), "");
+
+ // Test
+ final Map testHeaders = new HashMap();
+ testHeaders.put("FCREPO_IDENTIFIER", identifier);
+ testHeaders.put("org.fcrepo.jms.baseURL", "http://localhost:8080/fcrepo4/rest");
+ template.sendBodyAndHeaders(null, testHeaders);
+
+ // Teardown
+ final Map teardownHeaders = new HashMap();
+ teardownHeaders.put(Exchange.HTTP_METHOD, "DELETE");
+ teardownHeaders.put("FCREPO_IDENTIFIER", identifier);
+ template.sendBodyAndHeaders("direct:teardown", null, teardownHeaders);
+
+ // Confirm that the assertions passed
+ resultEndpoint.assertIsSatisfied();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ public void configure() throws IOException {
+
+ final String fcrepo_uri = FedoraTestUtils.getFcrepoEndpointUri();
+ final String fuseki_url = "localhost:" + getProperty("test.fuseki.port", "3030");
+ final Processor sparqlInsert = new SparqlInsertProcessor();
+ final XPathBuilder titleXpath = new XPathBuilder("/rdf:RDF/rdf:Description/dc:title/text()");
+ titleXpath.namespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
+ titleXpath.namespace("dc", "http://purl.org/dc/elements/1.1/");
+
+ from("direct:setup")
+ .to(fcrepo_uri);
+
+ from("direct:start")
+ .process(new SparqlDescribeProcessor())
+ .to("http4:" + fuseki_url + "/test/query")
+ //.log("${body}")
+ .process(new SparqlDeleteProcessor())
+ .to("http4:" + fuseki_url + "/test/update")
+ .setHeader(Exchange.HTTP_METHOD).constant("GET")
+ .to(fcrepo_uri + "?accept=application/n-triples")
+ .process(new SparqlInsertProcessor())
+ .to("http4:" + fuseki_url + "/test/update")
+ .to("mock:result");
+
+ from("direct:teardown")
+ .to(fcrepo_uri)
+ .to(fcrepo_uri + "?tombstone=true");
+ }
+ };
+ }
+}
diff --git a/src/test/java/org/fcrepo/camel/integration/FedoraTestUtils.java b/src/test/java/org/fcrepo/camel/integration/FedoraTestUtils.java
index 1d1c9c5..d89e919 100644
--- a/src/test/java/org/fcrepo/camel/integration/FedoraTestUtils.java
+++ b/src/test/java/org/fcrepo/camel/integration/FedoraTestUtils.java
@@ -62,6 +62,14 @@ public static String getTurtleDocument() {
"<> dc:title \"some title\" .";
}
+ /**
+ * Retrieve an N3 document
+ */
+ public static String getN3Document() {
+ return " \"Author\" .\n" +
+ " \"Title\" .";
+ }
+
/**
* Retrieve a simple text document
*/