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