001/* 002 * The contents of this file are subject to the license and copyright 003 * detailed in the LICENSE and NOTICE files at the root of the source 004 * tree. 005 */ 006package org.fcrepo.http.commons.responses; 007 008import static java.util.stream.Stream.of; 009import static com.google.common.util.concurrent.Futures.addCallback; 010import static javax.ws.rs.core.MediaType.valueOf; 011import static org.apache.jena.datatypes.xsd.XSDDatatype.XSDdateTime; 012import static org.apache.jena.graph.NodeFactory.createLiteral; 013import static org.apache.jena.graph.NodeFactory.createURI; 014import static org.apache.jena.graph.Triple.create; 015import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel; 016import static org.apache.jena.rdf.model.ResourceFactory.createProperty; 017import static org.apache.jena.rdf.model.ResourceFactory.createResource; 018import static org.apache.jena.rdf.model.ResourceFactory.createTypedLiteral; 019import static org.fcrepo.http.commons.domain.RDFMediaType.TURTLE_TYPE; 020import static org.junit.Assert.assertTrue; 021import static org.mockito.Mockito.mock; 022import static org.slf4j.LoggerFactory.getLogger; 023 024import java.io.ByteArrayInputStream; 025import java.io.ByteArrayOutputStream; 026import java.io.IOException; 027import java.io.InputStream; 028import java.io.OutputStream; 029import java.util.HashMap; 030import java.util.Map; 031import java.util.stream.Stream; 032 033import javax.ws.rs.WebApplicationException; 034import javax.ws.rs.core.MediaType; 035 036import com.google.common.util.concurrent.FutureCallback; 037import com.google.common.util.concurrent.MoreExecutors; 038 039import org.apache.jena.rdf.model.RDFNode; 040import org.apache.jena.riot.RiotException; 041import org.fcrepo.kernel.api.rdf.DefaultRdfStream; 042import org.fcrepo.kernel.api.RdfStream; 043import org.junit.Before; 044import org.junit.Test; 045import org.mockito.Mock; 046import org.mockito.stubbing.Answer; 047import org.slf4j.Logger; 048 049import org.apache.jena.graph.Node; 050import org.apache.jena.graph.Triple; 051import org.apache.jena.rdf.model.Model; 052 053import org.junit.runner.RunWith; 054import org.mockito.junit.MockitoJUnitRunner; 055 056/** 057 * <p>RdfStreamStreamingOutputTest class.</p> 058 * 059 * @author ajs6f 060 */ 061@RunWith(MockitoJUnitRunner.class) 062public class RdfStreamStreamingOutputTest { 063 064 private RdfStreamStreamingOutput testRdfStreamStreamingOutput; 065 066 private static final Triple triple = create(createURI("info:testSubject"), 067 createURI("info:testPredicate"), createURI("info:testObject")); 068 069 @Mock 070 private Node mockNode; 071 072 private final RdfStream testRdfStream = new DefaultRdfStream(triple.getSubject(), of(triple)); 073 074 private final Map<String, String> testNamespaces = new HashMap<>(); 075 076 @Mock 077 private RdfStream mockRdfStream; 078 079 private final MediaType testMediaType = valueOf("application/rdf+xml"); 080 081 private static final Logger LOGGER = 082 getLogger(RdfStreamStreamingOutputTest.class); 083 084 @Before 085 public void setUp() { 086 testRdfStreamStreamingOutput = 087 new RdfStreamStreamingOutput(testRdfStream, testNamespaces, testMediaType); 088 } 089 090 @Test 091 public void testWrite() throws IOException { 092 assertOutputContainsTriple(triple); 093 } 094 095 public void assertOutputContainsTriple(final Triple expected) throws IOException { 096 try (final RdfStream input = new DefaultRdfStream(expected.getSubject(), of(expected)); 097 final ByteArrayOutputStream output = new ByteArrayOutputStream()) { 098 new RdfStreamStreamingOutput(input, testNamespaces, testMediaType).write(output); 099 try ( final InputStream resultStream = new ByteArrayInputStream(output.toByteArray())) { 100 final Model result = createDefaultModel().read(resultStream, null); 101 assertTrue("Didn't find our test triple!", result.contains(result.asStatement(expected))); 102 } 103 } 104 } 105 106 @Test 107 public void testWriteWithNamespace() throws IOException { 108 final Map<String, String> namespaces = new HashMap<>(); 109 namespaces.put("a", "info:"); 110 try (final RdfStream input = new DefaultRdfStream(triple.getSubject(), of(triple)); 111 final ByteArrayOutputStream output = new ByteArrayOutputStream()) { 112 new RdfStreamStreamingOutput(input, namespaces, TURTLE_TYPE).write(output); 113 final String s = output.toString("UTF-8"); 114 assertTrue(s.replaceAll("\\s+", " ").contains("@prefix a: <info:>")); 115 } 116 } 117 118 @Test 119 public void testWriteWithTypedObject() throws IOException { 120 assertOutputContainsTriple(create(createURI("info:testSubject"), 121 createURI("info:testPredicate"), 122 createTypedLiteral(0).asNode())); 123 } 124 125 @Test 126 public void testWriteWithBlankSubject() throws IOException { 127 try (final RdfStream input = new DefaultRdfStream(createResource().asNode(), of(create(createResource() 128 .asNode(), createURI("info:testPredicate"), createTypedLiteral(0).asNode()))); 129 final ByteArrayOutputStream output = new ByteArrayOutputStream()) { 130 new RdfStreamStreamingOutput(input, testNamespaces, testMediaType).write(output); 131 try (final InputStream resultStream = new ByteArrayInputStream(output.toByteArray())) { 132 final Model result = createDefaultModel().read(resultStream, null); 133 assertTrue(result.contains(null, createProperty("info:testPredicate"), createTypedLiteral(0))); 134 } 135 } 136 } 137 138 139 @Test 140 public void testWriteWithBlankObject() throws IOException { 141 final Stream<Triple> triples = 142 of(create(createResource().asNode(), createURI("info:testPredicate"), createResource().asNode())); 143 try (final RdfStream input = new DefaultRdfStream(createResource().asNode(), triples); 144 final ByteArrayOutputStream output = new ByteArrayOutputStream()) { 145 new RdfStreamStreamingOutput(input, testNamespaces, testMediaType).write(output); 146 try (final InputStream resultStream = new ByteArrayInputStream(output.toByteArray())) { 147 final Model result = createDefaultModel().read(resultStream, null); 148 assertTrue(result.contains(null, createProperty("info:testPredicate"), (RDFNode) null)); 149 } 150 } 151 } 152 153 @Test 154 public void testWriteWithDatetimeObject() throws IOException { 155 assertOutputContainsTriple(create(createURI("info:testSubject"), 156 createURI("info:testPredicate"), createLiteral("2014-01-01T01:02:03Z", XSDdateTime))); 157 } 158 159 @Test 160 public void testWriteWithLanguageLiteral() throws IOException { 161 assertOutputContainsTriple(create(createURI("info:testSubject"), 162 createURI("info:testPredicate"), 163 createLiteral("french string", "fr"))); 164 } 165 166 @Test(expected = WebApplicationException.class) 167 public void testWriteWithException() throws IOException { 168 169 final FutureCallback<Void> callback = new FutureCallback<Void>() { 170 171 @Override 172 public void onSuccess(final Void v) { 173 throw new AssertionError("Should never happen!"); 174 } 175 176 @Override 177 public void onFailure(final Throwable e) { 178 LOGGER.debug("Got exception:", e.getMessage()); 179 assertTrue("Got wrong kind of exception!", e instanceof RiotException); 180 } 181 }; 182 addCallback(testRdfStreamStreamingOutput, callback, MoreExecutors.directExecutor()); 183 try (final OutputStream mockOutputStream = mock(OutputStream.class, (Answer<Object>) invocation -> { 184 throw new RiotException("Expected."); 185 })) { 186 testRdfStreamStreamingOutput.write(mockOutputStream); 187 } 188 } 189}