001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.camel;
019
020import static org.apache.commons.lang3.StringUtils.normalizeSpace;
021import static org.apache.camel.Exchange.CONTENT_TYPE;
022import static org.apache.camel.Exchange.HTTP_METHOD;
023import static org.fcrepo.camel.FcrepoHeaders.FCREPO_NAMED_GRAPH;
024import static org.fcrepo.camel.FcrepoHeaders.FCREPO_URI;
025import static org.fcrepo.camel.integration.FcrepoTestUtils.getFcrepoEndpointUri;
026import static org.fcrepo.camel.integration.FcrepoTestUtils.getN3Document;
027import static org.fcrepo.camel.integration.FcrepoTestUtils.getTurtleDocument;
028import static java.net.URLEncoder.encode;
029
030import java.io.IOException;
031import java.util.HashMap;
032import java.util.Map;
033
034import org.apache.camel.EndpointInject;
035import org.apache.camel.Exchange;
036import org.apache.camel.Processor;
037import org.apache.camel.Produce;
038import org.apache.camel.ProducerTemplate;
039import org.apache.camel.builder.RouteBuilder;
040import org.apache.camel.component.mock.MockEndpoint;
041import org.apache.camel.test.junit4.CamelTestSupport;
042import org.fcrepo.camel.processor.SparqlUpdateProcessor;
043import org.junit.Test;
044
045/**
046 * Test adding a non-RDF resource
047 * @author Aaron Coburn
048 * @since November 7, 2014
049 */
050public class SparqlUpdateProcessorTest extends CamelTestSupport {
051
052    @EndpointInject(uri = "mock:result")
053    protected MockEndpoint resultEndpoint;
054
055    @Produce(uri = "direct:start")
056    protected ProducerTemplate template;
057
058    @Test
059    public void testNamedGraph() throws IOException, InterruptedException {
060        final String uri = "http://localhost/rest/path/a/b/c";
061        final String graph = "foo";
062        final String document = getN3Document();
063        // Reverse the lines as the RDF may be serialized in opposite order
064
065        final String responsePrefix =
066              "DELETE WHERE { GRAPH <" + graph + "> { <" + uri + "> ?p ?o } };\n" +
067              "INSERT DATA { GRAPH <" + graph + "> { ";
068        final String responseSuffix = "\n} }";
069
070        // Assertions
071        resultEndpoint.allMessages().body().startsWith("update=" + encode(responsePrefix, "UTF-8"));
072        resultEndpoint.allMessages().body().endsWith(encode(responseSuffix, "UTF-8"));
073        for (final String s : document.split("\n")) {
074            resultEndpoint.expectedBodyReceived().body().contains(encode(s, "UTF-8"));
075        }
076        resultEndpoint.expectedBodyReceived().body().contains(
077                encode("<" + uri + "> dc:title \"some title\" .", "UTF-8"));
078        resultEndpoint.expectedHeaderReceived("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
079        resultEndpoint.expectedHeaderReceived(HTTP_METHOD, "POST");
080
081        // Test
082        final Map<String, Object> headers = new HashMap<>();
083        headers.put(FCREPO_URI, uri);
084        headers.put(FCREPO_NAMED_GRAPH, graph);
085        headers.put(CONTENT_TYPE, "application/n-triples");
086        template.sendBodyAndHeaders(document, headers);
087
088        // Confirm that assertions passed
089        resultEndpoint.expectedMessageCount(1);
090        resultEndpoint.assertIsSatisfied();
091    }
092
093    @Test
094    public void testUpdate() throws IOException, InterruptedException {
095        final String uri = "http://localhost/rest/path/a/b/c";
096        final String document = getTurtleDocument();
097        // Reverse the lines as the RDF may be serialized in opposite order
098
099        final String responsePrefix =
100                  "DELETE WHERE { <" + uri + "> ?p ?o };\n" +
101                  "INSERT DATA { ";
102        final String responseSuffix = "\n}";
103
104        // Assertions
105        resultEndpoint.allMessages().body().startsWith("update=" + encode(responsePrefix, "UTF-8"));
106        resultEndpoint.allMessages().body().endsWith(encode(responseSuffix, "UTF-8"));
107        for (final String s : document.split("\n")) {
108            resultEndpoint.expectedBodyReceived().body().contains(encode(s, "UTF-8"));
109        }
110        resultEndpoint.expectedBodyReceived().body().contains(
111                encode("<" + uri + "> dc:title \"some title\" .", "UTF-8"));
112        resultEndpoint.expectedHeaderReceived("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
113        resultEndpoint.expectedHeaderReceived(HTTP_METHOD, "POST");
114
115        // Test
116        final Map<String, Object> headers = new HashMap<>();
117        headers.put(FCREPO_URI, uri);
118        headers.put(CONTENT_TYPE, "text/turtle");
119        template.sendBodyAndHeaders(document, headers);
120
121        // Confirm that assertions passed
122        resultEndpoint.expectedMessageCount(1);
123        resultEndpoint.assertIsSatisfied();
124    }
125
126    @Override
127    protected RouteBuilder createRouteBuilder() {
128        return new RouteBuilder() {
129            @Override
130            public void configure() throws IOException {
131
132                final String fcrepo_uri = getFcrepoEndpointUri();
133
134                from("direct:start")
135                    .process(new SparqlUpdateProcessor())
136                    // Normalize the whitespace to make it easier to compare
137                    .process(new Processor() {
138                        public void process(final Exchange exchange) throws Exception {
139                           final String payload = exchange.getIn().getBody(String.class);
140                           exchange.getIn().setBody(normalizeSpace(payload));
141                       }
142                    })
143                    .to("mock:result");
144            }
145        };
146    }
147}