/* * 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.integration.rdf; import org.apache.jena.datatypes.xsd.XSDDatatype; import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; import org.apache.jena.query.Dataset; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.sparql.core.DatasetGraph; import org.apache.jena.sparql.graph.GraphFactory; import org.apache.jena.util.iterator.ExtendedIterator; import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.BasicHttpEntity; import org.apache.jena.riot.RDFDataMgr; import org.apache.jena.riot.RDFLanguages; import org.fcrepo.integration.http.api.AbstractResourceIT; import javax.ws.rs.core.Response; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URI; import java.util.HashMap; import java.util.Map; import static java.nio.charset.StandardCharsets.UTF_8; import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE; import static javax.ws.rs.core.Response.Status.CREATED; import static org.apache.jena.graph.NodeFactory.createBlankNode; import static org.apache.jena.graph.NodeFactory.createLiteral; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** * @author cabeer * @author ajs6f */ public abstract class AbstractIntegrationRdfIT extends AbstractResourceIT { protected HttpResponse createLDPRSAndCheckResponse(final String pid, final String body) { try { final HttpPut httpPut = new HttpPut(serverAddress + pid); httpPut.addHeader("Slug", pid); httpPut.addHeader(CONTENT_TYPE, "text/turtle"); final BasicHttpEntity e = new BasicHttpEntity(); e.setContent(IOUtils.toInputStream(body, UTF_8)); httpPut.setEntity(e); final HttpResponse response = client.execute(httpPut); checkResponse(response, CREATED); final String location = response.getFirstHeader("Location").getValue(); final HttpGet httpGet = new HttpGet(location); httpGet.addHeader("Prefer", "return=representation; " + "include=\"http://www.w3.org/ns/ldp#PreferMinimalContainer\"; " + "omit=\"http://fedora.info/definitions/v4/repository#ServerManaged\""); final Dataset dataset = getDataset(httpGet); final DatasetGraph graphStore = dataset.asDatasetGraph(); assertFalse(graphStore.isEmpty()); final Graph tidiedGraph = getTidiedGraph(graphStore); final Model expected = ModelFactory.createDefaultModel().read( IOUtils.toInputStream(body, UTF_8), location, "TTL"); final boolean isomorphicWith = tidiedGraph.isIsomorphicWith(getTidiedGraph(expected.getGraph())); final String description; if (!isomorphicWith) { final ByteArrayOutputStream o = new ByteArrayOutputStream(); final Model tidiedModel = ModelFactory.createModelForGraph(tidiedGraph); tidiedModel.setNsPrefixes(expected.getNsPrefixMap()); o.write("Expected: ".getBytes()); RDFDataMgr.write(o, expected, RDFLanguages.TTL); o.write("to be isomorphic with: ".getBytes()); RDFDataMgr.write(o, tidiedModel, RDFLanguages.TTL); description = IOUtils.toString(o.toByteArray(), "UTF-8"); } else { description = ""; } assertTrue(description, isomorphicWith); return response; } catch (final IOException e) { assertTrue("Got IOException " + e, false); return null; } } private static Graph getTidiedGraph(final DatasetGraph graph) { return getTidiedGraph(graph.getDefaultGraph()); } private static Graph getTidiedGraph(final Graph graph) { final Graph betterGraph = GraphFactory.createDefaultGraph(); final ExtendedIterator<Triple> triples = graph.find(Node.ANY, Node.ANY, Node.ANY); final Map<Node, Node> bnodeMap = new HashMap<>(); while (triples.hasNext()) { final Triple next = triples.next(); Triple replacement = next; if (isSkolemizedBnode(replacement.getSubject())) { if (!bnodeMap.containsKey(replacement.getSubject())) { bnodeMap.put(replacement.getSubject(), createBlankNode()); } replacement = new Triple(bnodeMap.get(replacement.getSubject()), replacement.getPredicate(), replacement.getObject()); } if (isSkolemizedBnode(replacement.getObject())) { if (!bnodeMap.containsKey(replacement.getObject())) { bnodeMap.put(replacement.getObject(), createBlankNode()); } replacement = new Triple(replacement.getSubject(), replacement.getPredicate(), bnodeMap.get(replacement.getObject())); } if (replacement.getObject().isLiteral() && replacement.getObject().getLiteral().getDatatype() != null && replacement.getObject().getLiteral().getDatatype().equals(XSDDatatype.XSDstring)) { replacement = new Triple(replacement.getSubject(), replacement.getPredicate(), createLiteral(replacement.getObject().getLiteral().getLexicalForm())); } betterGraph.add(replacement); } return betterGraph; } private static boolean isSkolemizedBnode(final Node node) { if (!node.isURI()) { return false; } final URI uri = URI.create(node.toString()); return uri.getFragment() != null && uri.getFragment().startsWith("genid"); } protected void checkResponse(final HttpResponse response, final Response.StatusType expected) { final int actual = response.getStatusLine().getStatusCode(); assertEquals("Didn't get a CREATED response!", expected.getStatusCode(), actual); } protected String getContentFromClasspath(final String path) throws IOException { return IOUtils.toString(this.getClass().getResourceAsStream(path), UTF_8); } }