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