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.http.commons.responses;
017
018import static com.google.common.collect.ImmutableMap.of;
019import static com.hp.hpl.jena.graph.NodeFactory.createAnon;
020import static com.hp.hpl.jena.graph.NodeFactory.createLiteral;
021import static com.hp.hpl.jena.graph.NodeFactory.createURI;
022import static com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel;
023import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
024import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty;
025import static com.hp.hpl.jena.rdf.model.ResourceFactory.createTypedLiteral;
026import static org.fcrepo.http.commons.test.util.TestHelpers.getUriInfoImpl;
027import static org.fcrepo.kernel.api.RdfLexicon.CREATED_BY;
028import static org.fcrepo.kernel.api.RdfLexicon.CREATED_DATE;
029import static org.fcrepo.kernel.api.RdfLexicon.DC_TITLE;
030import static org.fcrepo.kernel.api.RdfLexicon.DCTERMS_TITLE;
031import static org.fcrepo.kernel.api.RdfLexicon.HAS_PRIMARY_TYPE;
032import static org.fcrepo.kernel.api.RdfLexicon.HAS_VERSION_LABEL;
033import static org.fcrepo.kernel.api.RdfLexicon.DC_NAMESPACE;
034import static org.fcrepo.kernel.api.RdfLexicon.HAS_VERSION;
035import static org.fcrepo.kernel.api.RdfLexicon.DESCRIBES;
036import static org.fcrepo.kernel.api.RdfLexicon.RDFS_LABEL;
037import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_NAMESPACE;
038import static org.fcrepo.kernel.api.RdfLexicon.SKOS_PREFLABEL;
039import static org.fcrepo.kernel.api.RdfLexicon.WRITABLE;
040import static org.fcrepo.kernel.api.RdfLexicon.RDF_NAMESPACE;
041import static org.junit.Assert.assertEquals;
042import static org.junit.Assert.assertFalse;
043import static org.junit.Assert.assertTrue;
044
045import java.util.Date;
046import java.util.Iterator;
047import java.util.List;
048import java.util.Map;
049
050import javax.ws.rs.core.UriInfo;
051
052import com.hp.hpl.jena.graph.Graph;
053import com.hp.hpl.jena.graph.Triple;
054import org.junit.Before;
055import org.junit.Test;
056
057import com.hp.hpl.jena.graph.Node;
058import com.hp.hpl.jena.graph.NodeFactory;
059import com.hp.hpl.jena.rdf.model.Literal;
060import com.hp.hpl.jena.rdf.model.Model;
061import com.hp.hpl.jena.rdf.model.Property;
062import com.hp.hpl.jena.rdf.model.Resource;
063import com.hp.hpl.jena.rdf.model.ResourceFactory;
064
065/**
066 * <p>ViewHelpersTest class.</p>
067 *
068 * @author awoods
069 */
070public class ViewHelpersTest {
071
072    private ViewHelpers testObj;
073
074    @Before
075    public void setUp() {
076        testObj = ViewHelpers.getInstance();
077    }
078
079    @Test
080    public void testGetVersions() {
081        final Graph mem = createDefaultModel().getGraph();
082        final Node version = createURI("http://localhost/fcrepo/abc/fcr:version/adcd");
083        final String date = new Date().toString();
084        mem.add(new Triple(createURI("http://localhost/fcrepo/abc"), HAS_VERSION.asNode(),
085                version));
086        mem.add(new Triple(version, CREATED_DATE.asNode(), createLiteral(date)));
087        assertEquals("Version should be available.",
088                     version, testObj.getVersions(mem, createURI("http://localhost/fcrepo/abc")).next());
089    }
090
091    @Test
092    public void testGetOrderedVersions() {
093        final Node resource = createURI("http://localhost/fcrepo/abc");
094        final Node v1 = createURI("http://localhost/fcrepo/abc/fcr:version/1");
095        final Node v2 = createURI("http://localhost/fcrepo/abc/fcr:version/2");
096        final Node v3 = createURI("http://localhost/fcrepo/abc/fcr:version/3");
097        final Date now = new Date();
098        final Date later = new Date();
099        later.setTime(later.getTime() + 10000l);
100
101        final Graph mem = createDefaultModel().getGraph();
102        mem.add(new Triple(resource, HAS_VERSION.asNode(), v1));
103        mem.add(new Triple(v1, CREATED_DATE.asNode(),
104                createLiteral(now.toString())));
105        mem.add(new Triple(resource, HAS_VERSION.asNode(), v2));
106        mem.add(new Triple(v2, CREATED_DATE.asNode(),
107                createLiteral(now.toString())));
108        mem.add(new Triple(resource, HAS_VERSION.asNode(), v3));
109        mem.add(new Triple(v3, CREATED_DATE.asNode(),
110                createLiteral(later.toString())));
111
112        final Iterator<Node> versions = testObj.getOrderedVersions(mem, resource, HAS_VERSION);
113        versions.next();
114        versions.next();
115        final Node r3 = versions.next();
116        assertEquals("Latest version should be last.", v3, r3);
117    }
118
119    @Test
120    public void shouldConvertAUriToNodeBreadcrumbs() {
121
122        final UriInfo mockUriInfo = getUriInfoImpl();
123
124        final Map<String, String> nodeBreadcrumbs =
125            testObj.getNodeBreadcrumbs(mockUriInfo, createResource(
126                    "http://localhost/fcrepo/a/b/c").asNode());
127
128        assertEquals(of("http://localhost/fcrepo/a", "a",
129                "http://localhost/fcrepo/a/b", "b",
130                "http://localhost/fcrepo/a/b/c", "c"), nodeBreadcrumbs);
131    }
132
133    @Test
134    public void shouldRefuseToConvertAForeignUriToNodeBreadcrumbs() {
135
136        final UriInfo mockUriInfo = getUriInfoImpl();
137
138        final Map<String, String> nodeBreadcrumbs =
139            testObj.getNodeBreadcrumbs(mockUriInfo, createResource(
140                    "http://somewhere/else/a/b/c").asNode());
141
142        assertTrue(nodeBreadcrumbs.isEmpty());
143    }
144
145    @Test
146    public void testIsWritable() {
147        final Graph mem = createDefaultModel().getGraph();
148        mem.add(new Triple(createURI("a/b/c"), WRITABLE.asNode(), createLiteral(Boolean.TRUE.toString())));
149        assertTrue("Node is should be writable.", testObj.isWritable(mem, createURI("a/b/c")));
150    }
151
152    @Test
153    public void testIsWritableFalse() {
154        final Graph mem = createDefaultModel().getGraph();
155        mem.add(new Triple(createURI("a/b/c"), WRITABLE.asNode(), createLiteral(Boolean.FALSE.toString())));
156        assertFalse("Node should not be writable.", testObj.isWritable(mem, createURI("a/b/c")));
157    }
158
159    @Test
160    public void testIsWritableFalseJunk() {
161        final Graph mem = createDefaultModel().getGraph();
162        mem.add(new Triple(createURI("a/b/c"), DESCRIBES.asNode(), createLiteral("junk")));
163        assertFalse("Node should not be writable.", testObj.isWritable(mem, createURI("a/b/c")));
164    }
165
166    @Test
167    public void testIsFrozenNode() {
168        final Graph mem = createDefaultModel().getGraph();
169        mem.add(new Triple(createURI("a/b/c"), HAS_PRIMARY_TYPE.asNode(), createLiteral("nt:frozenNode")));
170        assertTrue("Node is a frozen node.", testObj.isFrozenNode(mem, createURI("a/b/c")));
171    }
172
173    @Test
174    public void testIsNotFrozenNode() {
175        final Graph mem = createDefaultModel().getGraph();
176        mem.add(new Triple(createURI("a/b/c"), HAS_PRIMARY_TYPE.asNode(), createLiteral("nt:file")));
177        assertFalse("Node is not a frozen node.", testObj.isFrozenNode(mem, createURI("a/b/c")));
178    }
179
180    @Test
181    public void testRdfResource() {
182        final String ns = "http://any/namespace#";
183        final String type = "anyType";
184        final Graph mem = createDefaultModel().getGraph();
185        mem.add(new Triple(createURI("a/b"),
186                createResource(RDF_NAMESPACE + "type").asNode(),
187                createResource(ns + type).asNode()));
188
189        assertTrue("Node is a " + type + " node.",
190                testObj.isRdfResource(mem, createURI("a/b"), ns, type));
191        assertFalse("Node is not a " + type + " node.",
192                testObj.isRdfResource(mem, createURI("a/b"), ns, "otherType"));
193    }
194
195    @Test
196    public void shouldFindVersionRoot() {
197
198        final UriInfo mockUriInfo = getUriInfoImpl();
199
200        final String nodeUri = testObj.getVersionSubjectUrl(mockUriInfo, createResource(
201                        "http://localhost/fcrepo/a/b/fcr:versions/c").asNode());
202        assertEquals("http://localhost/fcrepo/a/b", nodeUri);
203    }
204
205    @Test
206    public void testGetLabeledVersion() {
207        final Graph mem = createDefaultModel().getGraph();
208        final String label = "testLabel";
209        mem.add(new Triple(createURI("a/b/c"), HAS_VERSION_LABEL.asNode(),
210                createLiteral(label)));
211        assertEquals("Version label should be available.", label, testObj.getVersionLabel(mem, createURI("a/b/c"), ""));
212    }
213
214    @Test
215    public void testGetUnlabeledVersion() {
216        final Graph mem = createDefaultModel().getGraph();
217        assertEquals("Default version label should be used.",
218                     "d", testObj.getVersionLabel(mem, createURI("a/b/c"), "d"));
219    }
220
221    @Test
222    public void testGetVersionDate() {
223        final Graph mem = createDefaultModel().getGraph();
224        final String date = new Date().toString();
225        mem.add(new Triple(createURI("a/b/c"), CREATED_DATE.asNode(),
226                createLiteral(date)));
227        assertEquals("Date should be available.", date, testObj.getVersionDate(mem, createURI("a/b/c")));
228    }
229
230    @Test
231    public void testGetMissingVersionDate() {
232        final Graph mem = createDefaultModel().getGraph();
233        assertEquals("Date should not be available.", testObj.getVersionDate(mem, createURI("a/b/c")), "");
234    }
235
236    @Test
237    public void shouldExtractTitleFromNode() {
238        shouldExtractTitleFromNode(DC_TITLE);
239        shouldExtractTitleFromNode(DCTERMS_TITLE);
240        shouldExtractTitleFromNode(RDFS_LABEL);
241        shouldExtractTitleFromNode(SKOS_PREFLABEL);
242    }
243
244    private void shouldExtractTitleFromNode( final Property property ) {
245        final Graph mem = createDefaultModel().getGraph();
246        mem.add(new Triple(createURI("a/b/c"), property.asNode(), createLiteral("abc")));
247        assertEquals("abc", testObj.getObjectTitle(mem, createURI("a/b/c")));
248    }
249
250    @Test
251    public void shouldUseTheObjectUriIfATitleIsNotAvailable() {
252        final Graph mem = createDefaultModel().getGraph();
253
254        assertEquals("a/b/c", testObj.getObjectTitle(mem, createURI("a/b/c")));
255
256    }
257
258    @Test
259    public void shouldUsetheBNodeIdIfItIsABNode() {
260        final Graph mem = createDefaultModel().getGraph();
261        final Node anon = createAnon();
262        assertEquals(anon.getBlankNodeLabel(), testObj
263                .getObjectTitle(mem, anon));
264    }
265
266    @Test
267    public void shouldJustUseTheStringIfItIsALiteral() {
268        final Graph mem = createDefaultModel().getGraph();
269        final Node lit = createLiteral("xyz");
270        assertEquals("\"xyz\"", testObj.getObjectTitle(mem, lit));
271    }
272
273    @Test
274    public void shouldGetSerializationFormat() {
275        final String serialKey = "jcr/xml";
276        final Node formatRDF = createLiteral(REPOSITORY_NAMESPACE + serialKey);
277        final Node subject = createLiteral("xyz");
278        final Graph mem = createDefaultModel().getGraph();
279        final Property dcFormat = createProperty(DC_NAMESPACE + "format");
280
281        mem.add(new Triple(formatRDF, RDFS_LABEL.asNode(), createLiteral(serialKey)));
282        mem.add(new Triple(subject, dcFormat.asNode(), formatRDF));
283
284        assertEquals("jcr/xml", testObj.getSerializationTitle(mem, subject));
285    }
286
287    @Test
288    public void shouldConvertRdfObjectsToStrings() {
289
290        final Graph mem = createDefaultModel().getGraph();
291        mem.add(new Triple(createURI("subject"), createURI("a/b/c"),
292                NodeFactory.createLiteral("abc")));
293        mem.add(new Triple(createURI("subject"),
294                createURI("a-numeric-type"), createTypedLiteral(0).asNode()));
295        mem.add(new Triple(createURI("subject"),
296                createURI("an-empty-string"), createLiteral("")));
297        mem.add(new Triple( createURI("subject"), createURI("a-uri"),
298                createURI("some-uri")));
299
300        assertEquals("abc", testObj.getObjectsAsString(mem,
301                createURI("subject"), createResource("a/b/c"), true));
302        assertEquals("0", testObj.getObjectsAsString(mem, createURI("subject"),
303                createResource("a-numeric-type"), true));
304        assertEquals("<empty>", testObj.getObjectsAsString(mem,
305                createURI("subject"), createResource("an-empty-string"), true));
306        assertEquals("&lt;<a href=\"some-uri\">some-uri</a>&gt;", testObj
307                .getObjectsAsString(mem, createURI("subject"),
308                        createResource("a-uri"), true));
309
310        assertEquals("some-uri", testObj
311                .getObjectsAsString(mem, createURI("subject"),
312                        createResource("a-uri"), false));
313        assertEquals("", testObj.getObjectsAsString(mem, createURI("subject"),
314                createResource("a-nonexistent-uri"), true));
315
316    }
317
318    @Test
319    public void shouldExtractNamespaceAndPrefix() {
320        final Model model = createDefaultModel();
321        model.setNsPrefix("prefix", "namespace");
322
323        assertEquals("prefix:", testObj.getNamespacePrefix(model, "namespace", false));
324        assertEquals("some-other-namespace", testObj.getNamespacePrefix(model,
325                "some-other-namespace", false));
326    }
327
328    @Test
329    public void shouldSortTriplesForDisplay() {
330        final Model model = createDefaultModel();
331
332        model.setNsPrefix("prefix", "namespace");
333        final Property propertyA = model.createProperty("namespace", "a");
334        final Property propertyB = model.createProperty("namespace", "b");
335        final Property propertyC = model.createProperty("c");
336        final Literal literalA = model.createLiteral("a");
337        final Literal literalB = model.createLiteral("b");
338        final Resource resourceB = model.createResource("b");
339        model.add(resourceB, propertyA, literalA);
340
341        final Resource a = model.createResource("a");
342        model.add(a, propertyC, literalA);
343
344        model.add(a, propertyB, literalA);
345
346        model.add(a, propertyA, literalA);
347        model.add(a, propertyA, literalB);
348
349        final Iterator<Triple> iterator = model.getGraph().find(null, null, null);
350
351        final List<Triple> sortedTriples =
352            testObj.getSortedTriples(model, iterator);
353
354        sortedTriples.get(0).matches(a.asNode(), propertyA.asNode(),
355                literalA.asNode());
356        sortedTriples.get(1).matches(a.asNode(), propertyA.asNode(),
357                literalB.asNode());
358        sortedTriples.get(2).matches(a.asNode(), propertyB.asNode(),
359                literalA.asNode());
360        sortedTriples.get(3).matches(a.asNode(), propertyC.asNode(),
361                literalA.asNode());
362        sortedTriples.get(4).matches(resourceB.asNode(),
363                propertyC.asNode(), literalA.asNode());
364
365    }
366
367    @Test
368    public void shouldConvertPrefixMappingToSparqlUpdatePrefixPreamble() {
369
370        final Model model = createDefaultModel();
371
372        model.setNsPrefix("prefix", "namespace");
373
374        final String prefixPreamble = testObj.getPrefixPreamble(model);
375
376        assertEquals("PREFIX prefix: <namespace>\n\n", prefixPreamble);
377    }
378
379    @Test
380    public void shouldConvertRdfResourcesToNodes() {
381        assertEquals(CREATED_BY.asNode(), testObj.asNode(CREATED_BY));
382    }
383
384    @Test
385    public void shouldConvertStringLiteralsToNodes() {
386        final String uri = "fedora:resource";
387        final Literal URIRES = ResourceFactory.createPlainLiteral(uri);
388        assertEquals(URIRES.asNode(), testObj.asLiteralStringNode(uri));
389    }
390}