/*
* Licensed to DuraSpace under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* DuraSpace licenses this file to you 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.http.commons.responses;
import static java.util.stream.Stream.of;
import static com.google.common.util.concurrent.Futures.addCallback;
import static javax.ws.rs.core.MediaType.valueOf;
import static org.apache.jena.datatypes.xsd.XSDDatatype.XSDdateTime;
import static org.apache.jena.graph.NodeFactory.createLiteral;
import static org.apache.jena.graph.NodeFactory.createURI;
import static org.apache.jena.graph.Triple.create;
import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel;
import static org.apache.jena.rdf.model.ResourceFactory.createProperty;
import static org.apache.jena.rdf.model.ResourceFactory.createResource;
import static org.apache.jena.rdf.model.ResourceFactory.createTypedLiteral;
import static org.fcrepo.http.commons.domain.RDFMediaType.TURTLE_TYPE;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.slf4j.LoggerFactory.getLogger;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import javax.jcr.Session;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import com.google.common.util.concurrent.FutureCallback;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.riot.RiotException;
import org.fcrepo.kernel.api.rdf.DefaultRdfStream;
import org.fcrepo.kernel.api.RdfStream;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.stubbing.Answer;
import org.slf4j.Logger;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.rdf.model.Model;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
/**
* <p>RdfStreamStreamingOutputTest class.</p>
*
* @author ajs6f
*/
@RunWith(MockitoJUnitRunner.class)
public class RdfStreamStreamingOutputTest {
private RdfStreamStreamingOutput testRdfStreamStreamingOutput;
private static final Triple triple = create(createURI("info:testSubject"),
createURI("info:testPredicate"), createURI("info:testObject"));
@Mock
private Node mockNode;
private final RdfStream testRdfStream = new DefaultRdfStream(triple.getSubject(), of(triple));
private final Map<String, String> testNamespaces = new HashMap<>();
@Mock
private RdfStream mockRdfStream;
@Mock
private Session mockSession;
private final MediaType testMediaType = valueOf("application/rdf+xml");
private static final Logger LOGGER =
getLogger(RdfStreamStreamingOutputTest.class);
@Before
public void setUp() {
testRdfStreamStreamingOutput =
new RdfStreamStreamingOutput(testRdfStream, testNamespaces, testMediaType);
}
@Test
public void testWrite() throws IOException {
assertOutputContainsTriple(triple);
}
public void assertOutputContainsTriple(final Triple expected) throws IOException {
try (final RdfStream input = new DefaultRdfStream(expected.getSubject(), of(expected));
final ByteArrayOutputStream output = new ByteArrayOutputStream()) {
new RdfStreamStreamingOutput(input, testNamespaces, testMediaType).write(output);
try ( final InputStream resultStream = new ByteArrayInputStream(output.toByteArray())) {
final Model result = createDefaultModel().read(resultStream, null);
assertTrue("Didn't find our test triple!", result.contains(result.asStatement(expected)));
}
}
}
@Test
public void testWriteWithNamespace() throws IOException {
final Map<String, String> namespaces = new HashMap<>();
namespaces.put("a", "info:a");
try (final RdfStream input = new DefaultRdfStream(triple.getSubject(), of(triple));
final ByteArrayOutputStream output = new ByteArrayOutputStream()) {
new RdfStreamStreamingOutput(input, namespaces, TURTLE_TYPE).write(output);
final String s = output.toString("UTF-8");
assertTrue(s.replaceAll("\\s+", " ").contains("@prefix a: <info:a>"));
}
}
@Test
public void testWriteWithTypedObject() throws IOException {
assertOutputContainsTriple(create(createURI("info:testSubject"),
createURI("info:testPredicate"),
createTypedLiteral(0).asNode()));
}
@Test
public void testWriteWithBlankSubject() throws IOException {
try (final RdfStream input = new DefaultRdfStream(createResource().asNode(), of(create(createResource()
.asNode(), createURI("info:testPredicate"), createTypedLiteral(0).asNode())));
final ByteArrayOutputStream output = new ByteArrayOutputStream()) {
new RdfStreamStreamingOutput(input, testNamespaces, testMediaType).write(output);
try (final InputStream resultStream = new ByteArrayInputStream(output.toByteArray())) {
final Model result = createDefaultModel().read(resultStream, null);
assertTrue(result.contains(null, createProperty("info:testPredicate"), createTypedLiteral(0)));
}
}
}
@Test
public void testWriteWithBlankObject() throws IOException {
final Stream<Triple> triples =
of(create(createResource().asNode(), createURI("info:testPredicate"), createResource().asNode()));
try (final RdfStream input = new DefaultRdfStream(createResource().asNode(), triples);
final ByteArrayOutputStream output = new ByteArrayOutputStream()) {
new RdfStreamStreamingOutput(input, testNamespaces, testMediaType).write(output);
try (final InputStream resultStream = new ByteArrayInputStream(output.toByteArray())) {
final Model result = createDefaultModel().read(resultStream, null);
assertTrue(result.contains(null, createProperty("info:testPredicate"), (RDFNode) null));
}
}
}
@Test
public void testWriteWithDatetimeObject() throws IOException {
assertOutputContainsTriple(create(createURI("info:testSubject"),
createURI("info:testPredicate"), createLiteral("2014-01-01T01:02:03Z", XSDdateTime)));
}
@Test
public void testWriteWithLanguageLiteral() throws IOException {
assertOutputContainsTriple(create(createURI("info:testSubject"),
createURI("info:testPredicate"),
createLiteral("french string", "fr")));
}
@Test(expected = WebApplicationException.class)
public void testWriteWithException() throws IOException {
final FutureCallback<Void> callback = new FutureCallback<Void>() {
@Override
public void onSuccess(final Void v) {
throw new AssertionError("Should never happen!");
}
@Override
public void onFailure(final Throwable e) {
LOGGER.info("Got exception:", e.getMessage());
assertTrue("Got wrong kind of exception!", e instanceof RiotException);
}
};
addCallback(testRdfStreamStreamingOutput, callback);
try (final OutputStream mockOutputStream = mock(OutputStream.class, (Answer<Object>) invocation -> {
throw new RiotException("Expected.");
})) {
testRdfStreamStreamingOutput.write(mockOutputStream);
}
}
}