001/*
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.integration.rdf;
017
018import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
019import com.hp.hpl.jena.graph.Graph;
020import com.hp.hpl.jena.graph.Node;
021import com.hp.hpl.jena.graph.NodeFactory;
022import com.hp.hpl.jena.graph.Triple;
023import com.hp.hpl.jena.rdf.model.Model;
024import com.hp.hpl.jena.rdf.model.ModelFactory;
025import com.hp.hpl.jena.sparql.graph.GraphFactory;
026import com.hp.hpl.jena.update.GraphStore;
027import com.hp.hpl.jena.util.iterator.ExtendedIterator;
028import org.apache.commons.io.IOUtils;
029import org.apache.http.HttpResponse;
030import org.apache.http.client.methods.HttpGet;
031import org.apache.http.client.methods.HttpPut;
032import org.apache.http.entity.BasicHttpEntity;
033import org.apache.jena.riot.RDFDataMgr;
034import org.apache.jena.riot.RDFLanguages;
035import org.fcrepo.integration.http.api.AbstractResourceIT;
036
037import javax.ws.rs.core.Response;
038import java.io.ByteArrayOutputStream;
039import java.io.IOException;
040import java.util.HashMap;
041import java.util.Map;
042
043import static javax.ws.rs.core.Response.Status.CREATED;
044import static org.junit.Assert.assertEquals;
045import static org.junit.Assert.assertFalse;
046import static org.junit.Assert.assertTrue;
047
048/**
049 * @author cabeer
050 * @author ajs6f
051 */
052public abstract class AbstractIntegrationRdfIT extends AbstractResourceIT {
053
054    protected HttpResponse createLDPRSAndCheckResponse(final String pid, final String body) {
055        try {
056            final HttpPut httpPut = new HttpPut(serverAddress + pid);
057            httpPut.addHeader("Slug", pid);
058            httpPut.addHeader("Content-Type", "text/turtle");
059            final BasicHttpEntity e = new BasicHttpEntity();
060            e.setContent(IOUtils.toInputStream(body));
061            httpPut.setEntity(e);
062            final HttpResponse response = client.execute(httpPut);
063            checkResponse(response, CREATED);
064
065            final String location = response.getFirstHeader("Location").getValue();
066
067            final HttpGet httpGet = new HttpGet(location);
068            httpGet.addHeader("Prefer", "return=representation; " +
069                    "include=\"http://www.w3.org/ns/ldp#PreferMinimalContainer\"; " +
070                    "omit=\"http://fedora.info/definitions/v4/repository#ServerManaged\"");
071            final GraphStore graphStore = getGraphStore(httpGet);
072
073            assertFalse(graphStore.isEmpty());
074
075            final Graph tidiedGraph = getTidiedGraph(graphStore);
076            final Model expected = ModelFactory.createDefaultModel().read(IOUtils.toInputStream(body), location, "TTL");
077
078            final boolean isomorphicWith = tidiedGraph.isIsomorphicWith(getTidiedGraph(expected.getGraph()));
079
080            final String description;
081
082            if (!isomorphicWith) {
083                final ByteArrayOutputStream o = new ByteArrayOutputStream();
084
085                final Model tidiedModel = ModelFactory.createModelForGraph(tidiedGraph);
086                tidiedModel.setNsPrefixes(expected.getNsPrefixMap());
087                o.write("Expected: ".getBytes());
088                RDFDataMgr.write(o, expected, RDFLanguages.TTL);
089                o.write("to be isomorphic with: ".getBytes());
090                RDFDataMgr.write(o, tidiedModel, RDFLanguages.TTL);
091                description = IOUtils.toString(o.toByteArray(), "UTF-8");
092            } else {
093                description = "";
094            }
095
096
097            assertTrue(description, isomorphicWith);
098
099            return response;
100        } catch (final IOException e) {
101            assertTrue("Got IOException " + e, false);
102            return null;
103        }
104    }
105
106    private static Graph getTidiedGraph(final GraphStore graphStore) {
107        return getTidiedGraph(graphStore.getDefaultGraph());
108    }
109
110    private static Graph getTidiedGraph(final Graph graph) {
111        final Graph betterGraph = GraphFactory.createDefaultGraph();
112        final ExtendedIterator<Triple> triples = graph.find(Node.ANY, Node.ANY, Node.ANY);
113        final Map<Node, Node> bnodeMap = new HashMap<>();
114
115        while (triples.hasNext()) {
116            final Triple next = triples.next();
117
118            Triple replacement = next;
119
120            if (replacement.getSubject().toString().contains(".well-known")) {
121                if (!bnodeMap.containsKey(replacement.getSubject())) {
122                    bnodeMap.put(replacement.getSubject(), NodeFactory.createAnon());
123                }
124
125                replacement = new Triple(bnodeMap.get(replacement.getSubject()),
126                        replacement.getPredicate(),
127                        replacement.getObject());
128            }
129
130            if (replacement.getObject().toString().contains(".well-known")) {
131
132                if (!bnodeMap.containsKey(replacement.getObject())) {
133                    bnodeMap.put(replacement.getObject(), NodeFactory.createAnon());
134                }
135
136                replacement = new Triple(replacement.getSubject(),
137                        replacement.getPredicate(),
138                        bnodeMap.get(replacement.getObject()));
139            }
140
141            if (replacement.getObject().isLiteral()
142                    && replacement.getObject().getLiteral().getDatatype() != null
143                    && replacement.getObject().getLiteral().getDatatype().equals(XSDDatatype.XSDstring)) {
144                replacement = new Triple(replacement.getSubject(),
145                        replacement.getPredicate(),
146                        NodeFactory.createLiteral(replacement.getObject().getLiteral().getLexicalForm()));
147            }
148
149            betterGraph.add(replacement);
150        }
151        return betterGraph;
152    }
153
154    protected void checkResponse(final HttpResponse response, final Response.StatusType expected) {
155        final int actual = response.getStatusLine().getStatusCode();
156        assertEquals("Didn't get a CREATED response!", expected.getStatusCode(), actual);
157    }
158
159    protected String getContentFromClasspath(final String path) throws IOException {
160        return IOUtils.toString(this.getClass().getResourceAsStream(path));
161    }
162
163
164}