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