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 com.google.common.collect.ImmutableMap.of;
021import static com.hp.hpl.jena.graph.NodeFactory.createAnon;
022import static com.hp.hpl.jena.graph.NodeFactory.createLiteral;
023import static com.hp.hpl.jena.graph.NodeFactory.createURI;
024import static com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel;
025import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
026import static com.hp.hpl.jena.rdf.model.ResourceFactory.createTypedLiteral;
027import static org.fcrepo.http.commons.test.util.TestHelpers.getUriInfoImpl;
028import static org.fcrepo.kernel.api.RdfLexicon.CONTAINS;
029import static org.fcrepo.kernel.api.RdfLexicon.CREATED_DATE;
030import static org.fcrepo.kernel.api.RdfLexicon.DC_TITLE;
031import static org.fcrepo.kernel.api.RdfLexicon.DCTERMS_TITLE;
032import static org.fcrepo.kernel.api.RdfLexicon.HAS_PRIMARY_TYPE;
033import static org.fcrepo.kernel.api.RdfLexicon.HAS_VERSION_LABEL;
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 shouldConvertRdfObjectsToStrings() {
278
279        final Graph mem = createDefaultModel().getGraph();
280        mem.add(new Triple(createURI("subject"), createURI("a/b/c"),
281                NodeFactory.createLiteral("abc")));
282        mem.add(new Triple(createURI("subject"),
283                createURI("a-numeric-type"), createTypedLiteral(0).asNode()));
284        mem.add(new Triple(createURI("subject"),
285                createURI("an-empty-string"), createLiteral("")));
286        mem.add(new Triple( createURI("subject"), createURI("a-uri"),
287                createURI("some-uri")));
288
289        assertEquals("abc", testObj.getObjectsAsString(mem,
290                createURI("subject"), createResource("a/b/c"), true));
291        assertEquals("0", testObj.getObjectsAsString(mem, createURI("subject"),
292                createResource("a-numeric-type"), true));
293        assertEquals("<empty>", testObj.getObjectsAsString(mem,
294                createURI("subject"), createResource("an-empty-string"), true));
295        assertEquals("&lt;<a href=\"some-uri\">some-uri</a>&gt;", testObj
296                .getObjectsAsString(mem, createURI("subject"),
297                        createResource("a-uri"), true));
298
299        assertEquals("some-uri", testObj
300                .getObjectsAsString(mem, createURI("subject"),
301                        createResource("a-uri"), false));
302        assertEquals("", testObj.getObjectsAsString(mem, createURI("subject"),
303                createResource("a-nonexistent-uri"), true));
304
305    }
306
307    @Test
308    public void shouldExtractNamespaceAndPrefix() {
309        final Model model = createDefaultModel();
310        model.setNsPrefix("prefix", "namespace");
311
312        assertEquals("prefix:", testObj.getNamespacePrefix(model, "namespace", false));
313        assertEquals("some-other-namespace", testObj.getNamespacePrefix(model,
314                "some-other-namespace", false));
315    }
316
317    @Test
318    public void shouldSortTriplesForDisplay() {
319        final Model model = createDefaultModel();
320
321        model.setNsPrefix("prefix", "namespace");
322        final Property propertyA = model.createProperty("namespace", "a");
323        final Property propertyB = model.createProperty("namespace", "b");
324        final Property propertyC = model.createProperty("c");
325        final Literal literalA = model.createLiteral("a");
326        final Literal literalB = model.createLiteral("b");
327        final Resource resourceB = model.createResource("b");
328        model.add(resourceB, propertyA, literalA);
329
330        final Resource a = model.createResource("a");
331        model.add(a, propertyC, literalA);
332
333        model.add(a, propertyB, literalA);
334
335        model.add(a, propertyA, literalA);
336        model.add(a, propertyA, literalB);
337
338        final Iterator<Triple> iterator = model.getGraph().find(null, null, null);
339
340        final List<Triple> sortedTriples =
341            testObj.getSortedTriples(model, iterator);
342
343        sortedTriples.get(0).matches(a.asNode(), propertyA.asNode(),
344                literalA.asNode());
345        sortedTriples.get(1).matches(a.asNode(), propertyA.asNode(),
346                literalB.asNode());
347        sortedTriples.get(2).matches(a.asNode(), propertyB.asNode(),
348                literalA.asNode());
349        sortedTriples.get(3).matches(a.asNode(), propertyC.asNode(),
350                literalA.asNode());
351        sortedTriples.get(4).matches(resourceB.asNode(),
352                propertyC.asNode(), literalA.asNode());
353
354    }
355
356    @Test
357    public void shouldConvertPrefixMappingToSparqlUpdatePrefixPreamble() {
358
359        final Model model = createDefaultModel();
360
361        model.setNsPrefix("prefix", "namespace");
362
363        final String prefixPreamble = testObj.getPrefixPreamble(model);
364
365        assertEquals("PREFIX prefix: <namespace>\n\n", prefixPreamble);
366    }
367
368    @Test
369    public void shouldConvertStringLiteralsToNodes() {
370        final String uri = "fedora:resource";
371        final Literal URIRES = ResourceFactory.createPlainLiteral(uri);
372        assertEquals(URIRES.asNode(), testObj.asLiteralStringNode(uri));
373    }
374
375    @Test
376    public void testGetNumChildren() {
377        final Graph mem = createDefaultModel().getGraph();
378        mem.add(new Triple(createURI("a/b/c"), CONTAINS.asNode(), createResource("a/b/c/1").asNode()));
379        mem.add(new Triple(createURI("a/b/c"), CONTAINS.asNode(), createResource("a/b/c/2").asNode()));
380        mem.add(new Triple(createURI("a/b/c"), CONTAINS.asNode(), createResource("a/b/c/3").asNode()));
381        mem.add(new Triple(createURI("a/b/c"), CONTAINS.asNode(), createResource("a/b/c/4").asNode()));
382        assertEquals(4, testObj.getNumChildren(mem, createURI("a/b/c")));
383    }
384
385    @Test
386    public void testGetNumChildrenEmpty() {
387        final Graph mem = createDefaultModel().getGraph();
388        assertEquals(0, testObj.getNumChildren(mem, createURI("a/b/c")));
389    }
390
391    @Test
392    public void testGetNumChildrenNone() {
393        final Graph mem = createDefaultModel().getGraph();
394        assertEquals(0, testObj.getNumChildren(mem, createURI("a/b/c")));
395    }
396
397}