001/* 002 * The contents of this file are subject to the license and copyright 003 * detailed in the LICENSE and NOTICE files at the root of the source 004 * tree. 005 */ 006package org.fcrepo.http.commons.responses; 007 008import static com.google.common.collect.ImmutableMap.of; 009import static org.apache.jena.graph.NodeFactory.createBlankNode; 010import static org.apache.jena.graph.NodeFactory.createLiteral; 011import static org.apache.jena.graph.NodeFactory.createURI; 012import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel; 013import static org.apache.jena.rdf.model.ResourceFactory.createResource; 014import static org.apache.jena.rdf.model.ResourceFactory.createTypedLiteral; 015import static org.apache.jena.vocabulary.DC.title; 016import static org.apache.jena.vocabulary.RDF.type; 017import static org.apache.jena.vocabulary.RDFS.label; 018import static org.apache.jena.vocabulary.SKOS.prefLabel; 019import static org.fcrepo.http.commons.test.util.TestHelpers.getUriInfoImpl; 020import static org.fcrepo.kernel.api.RdfLexicon.CONTAINS; 021import static org.fcrepo.kernel.api.RdfLexicon.CREATED_DATE; 022import static org.fcrepo.kernel.api.RdfLexicon.MEMENTO_TYPE; 023import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_NAMESPACE; 024import static org.fcrepo.kernel.api.RdfLexicon.BASIC_CONTAINER; 025import static org.fcrepo.kernel.api.FedoraTypes.FCR_VERSIONS; 026import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_ROOT; 027import static org.fcrepo.kernel.api.services.VersionService.MEMENTO_LABEL_FORMATTER; 028import static org.fcrepo.kernel.api.services.VersionService.MEMENTO_RFC_1123_FORMATTER; 029import static org.junit.Assert.assertEquals; 030import static org.junit.Assert.assertFalse; 031import static org.junit.Assert.assertTrue; 032import java.time.Instant; 033import java.util.Iterator; 034import java.util.List; 035import java.util.Map; 036 037import javax.ws.rs.core.UriInfo; 038 039import org.apache.jena.graph.Graph; 040import org.apache.jena.graph.Triple; 041import org.junit.Before; 042import org.junit.Test; 043 044import org.apache.jena.graph.Node; 045import org.apache.jena.graph.NodeFactory; 046import org.apache.jena.rdf.model.Literal; 047import org.apache.jena.rdf.model.Model; 048import org.apache.jena.rdf.model.Property; 049import org.apache.jena.rdf.model.Resource; 050import org.apache.jena.rdf.model.ResourceFactory; 051import org.apache.jena.vocabulary.DCTerms; 052 053/** 054 * <p>ViewHelpersTest class.</p> 055 * 056 * @author awoods 057 */ 058public class ViewHelpersTest { 059 060 private ViewHelpers testObj; 061 062 @Before 063 public void setUp() { 064 testObj = ViewHelpers.getInstance(); 065 } 066 067 @Test 068 public void testGetVersions() { 069 final Graph mem = createDefaultModel().getGraph(); 070 final String resource_version = "http://localhost/fcrepo/abc/" + FCR_VERSIONS; 071 final Instant recent = Instant.now(); 072 final Node version = createURI(resource_version + "/" + MEMENTO_LABEL_FORMATTER.format(recent)); 073 mem.add(new Triple(createURI(resource_version), CONTAINS.asNode(), version)); 074 mem.add(new Triple(version, CREATED_DATE.asNode(), createLiteral(MEMENTO_RFC_1123_FORMATTER.format(recent)))); 075 assertEquals("Version should be available.", 076 version, testObj.getVersions(mem, createURI(resource_version)).next()); 077 } 078 079 @Test 080 public void testGetOrderedVersions() { 081 final Node resource_version = createURI("http://localhost/fcrepo/abc/" + FCR_VERSIONS); 082 final Instant recent = Instant.now(); 083 final Instant past = recent.minus(3, java.time.temporal.ChronoUnit.DAYS); 084 final Instant way_past = recent.minus(60, java.time.temporal.ChronoUnit.DAYS); 085 final Node v1 = 086 createURI("http://localhost/fcrepo/abc/" + FCR_VERSIONS + "/" + MEMENTO_LABEL_FORMATTER.format(recent)); 087 final Node v2 = 088 createURI("http://localhost/fcrepo/abc/" + FCR_VERSIONS + "/" + MEMENTO_LABEL_FORMATTER.format(past)); 089 final Node v3 = 090 createURI("http://localhost/fcrepo/abc/" + FCR_VERSIONS + "/" + MEMENTO_LABEL_FORMATTER.format(way_past)); 091 092 final Graph mem = createDefaultModel().getGraph(); 093 mem.add(new Triple(resource_version, CONTAINS.asNode(), v1)); 094 mem.add(new Triple(resource_version, CONTAINS.asNode(), v2)); 095 mem.add(new Triple(resource_version, CONTAINS.asNode(), v3)); 096 mem.add(new Triple(v1, CREATED_DATE.asNode(), createLiteral(MEMENTO_RFC_1123_FORMATTER.format(recent)))); 097 mem.add(new Triple(v2, CREATED_DATE.asNode(), createLiteral(MEMENTO_RFC_1123_FORMATTER.format(past)))); 098 mem.add(new Triple(v3, CREATED_DATE.asNode(), createLiteral(MEMENTO_RFC_1123_FORMATTER.format(way_past)))); 099 100 final Iterator<Node> versions = testObj.getOrderedVersions(mem, resource_version, CONTAINS); 101 assertTrue(versions.hasNext()); 102 final Node r1 = versions.next(); 103 assertEquals("Version is out of order", v3, r1); 104 final Node r2 = versions.next(); 105 assertEquals("Version is out of order", v2, r2); 106 final Node r3 = versions.next(); 107 assertEquals("Latest version should be last.", v1, r3); 108 } 109 110 @Test 111 public void shouldConvertAUriToNodeBreadcrumbs() { 112 113 final UriInfo mockUriInfo = getUriInfoImpl(); 114 115 final Map<String, String> nodeBreadcrumbs = 116 testObj.getNodeBreadcrumbs(mockUriInfo, createResource( 117 "http://localhost/fcrepo/a/b/c").asNode()); 118 119 assertEquals(of("http://localhost/fcrepo/a", "a", 120 "http://localhost/fcrepo/a/b", "b", 121 "http://localhost/fcrepo/a/b/c", "c"), nodeBreadcrumbs); 122 } 123 124 @Test 125 public void shouldRefuseToConvertAForeignUriToNodeBreadcrumbs() { 126 127 final UriInfo mockUriInfo = getUriInfoImpl(); 128 129 final Map<String, String> nodeBreadcrumbs = 130 testObj.getNodeBreadcrumbs(mockUriInfo, createResource( 131 "http://somewhere/else/a/b/c").asNode()); 132 133 assertTrue(nodeBreadcrumbs.isEmpty()); 134 } 135 136 @Test 137 public void testIsVersionedNode() { 138 final Graph mem = createDefaultModel().getGraph(); 139 mem.add(new Triple(createURI("a/b/c"), type.asNode(), createURI(MEMENTO_TYPE))); 140 assertTrue("Node is a versioned node.", testObj.isVersionedNode(mem, createURI("a/b/c"))); 141 } 142 143 144 @Test 145 public void testRdfResource() { 146 final String ns = "http://any/namespace#"; 147 final String rdfType = "anyType"; 148 final Graph mem = createDefaultModel().getGraph(); 149 mem.add(new Triple(createURI("a/b"), type.asNode(), 150 createResource(ns + rdfType).asNode())); 151 152 assertTrue("Node is a " + rdfType + " node.", 153 testObj.isRdfResource(mem, createURI("a/b"), ns, rdfType)); 154 assertFalse("Node is not a " + rdfType + " node.", 155 testObj.isRdfResource(mem, createURI("a/b"), ns, "otherType")); 156 } 157 158 @Test 159 public void shouldFindVersionRoot() { 160 161 final UriInfo mockUriInfo = getUriInfoImpl(); 162 163 final String nodeUri = testObj.getVersionSubjectUrl(mockUriInfo, createResource( 164 "http://localhost/fcrepo/a/b/fcr:versions/c").asNode()); 165 assertEquals("http://localhost/fcrepo/a/b", nodeUri); 166 } 167 168 @Test 169 public void testGetVersionDate() { 170 final Graph mem = createDefaultModel().getGraph(); 171 final String date_str = "20011231050505"; 172 final Node subject = createURI("a/b/c/" + date_str); 173 final Instant date = Instant.from(MEMENTO_LABEL_FORMATTER.parse(date_str)); 174 mem.add(new Triple(subject, CREATED_DATE.asNode(), 175 createLiteral(MEMENTO_RFC_1123_FORMATTER.format(date)))); 176 177 assertEquals("Date should be available.", date, testObj.getVersionDate(mem, subject)); 178 } 179 180 @Test 181 public void shouldExtractTitleFromNode() { 182 shouldExtractTitleFromNode(title); 183 shouldExtractTitleFromNode(DCTerms.title); 184 shouldExtractTitleFromNode(label); 185 shouldExtractTitleFromNode(prefLabel); 186 } 187 188 private void shouldExtractTitleFromNode( final Property property ) { 189 final Graph mem = createDefaultModel().getGraph(); 190 mem.add(new Triple(createURI("a/b/c"), property.asNode(), createLiteral("abc"))); 191 assertEquals("abc", testObj.getObjectTitle(mem, createURI("a/b/c"))); 192 } 193 194 @Test 195 public void shouldUseTheObjectUriIfATitleIsNotAvailable() { 196 final Graph mem = createDefaultModel().getGraph(); 197 mem.add(new Triple(createURI("a/b/c"), title.asNode(), createURI("d/e/f"))); 198 199 assertEquals("a/b/c", testObj.getObjectTitle(mem, createURI("a/b/c"))); 200 201 } 202 203 @Test 204 public void shouldUsetheBNodeIdIfItIsABNode() { 205 final Graph mem = createDefaultModel().getGraph(); 206 final Node anon = createBlankNode(); 207 assertEquals(anon.getBlankNodeLabel(), testObj 208 .getObjectTitle(mem, anon)); 209 } 210 211 @Test 212 public void shouldJustUseTheStringIfItIsALiteral() { 213 final Graph mem = createDefaultModel().getGraph(); 214 final Node lit = createLiteral("xyz"); 215 assertEquals("\"xyz\"", testObj.getObjectTitle(mem, lit)); 216 } 217 218 @Test 219 public void shouldConvertRdfObjectsToStrings() { 220 221 final Graph mem = createDefaultModel().getGraph(); 222 mem.add(new Triple(createURI("subject"), createURI("a/b/c"), 223 NodeFactory.createLiteral("abc"))); 224 mem.add(new Triple(createURI("subject"), 225 createURI("a-numeric-type"), createTypedLiteral(0).asNode())); 226 mem.add(new Triple(createURI("subject"), 227 createURI("an-empty-string"), createLiteral(""))); 228 mem.add(new Triple( createURI("subject"), createURI("a-uri"), 229 createURI("some-uri"))); 230 231 assertEquals("abc", testObj.getObjectsAsString(mem, 232 createURI("subject"), createResource("a/b/c"), true)); 233 assertEquals("0", testObj.getObjectsAsString(mem, createURI("subject"), 234 createResource("a-numeric-type"), true)); 235 assertEquals("<empty>", testObj.getObjectsAsString(mem, 236 createURI("subject"), createResource("an-empty-string"), true)); 237 assertEquals("<<a href=\"some-uri\">some-uri</a>>", testObj 238 .getObjectsAsString(mem, createURI("subject"), 239 createResource("a-uri"), true)); 240 241 assertEquals("some-uri", testObj 242 .getObjectsAsString(mem, createURI("subject"), 243 createResource("a-uri"), false)); 244 assertEquals("", testObj.getObjectsAsString(mem, createURI("subject"), 245 createResource("a-nonexistent-uri"), true)); 246 247 } 248 249 @Test 250 public void shouldExtractNamespaceAndPrefix() { 251 final Model model = createDefaultModel(); 252 model.setNsPrefix("prefix", "namespace"); 253 254 assertEquals("prefix:", testObj.getNamespacePrefix(model, "namespace", false)); 255 assertEquals("some-other-namespace", testObj.getNamespacePrefix(model, 256 "some-other-namespace", false)); 257 } 258 259 @Test 260 public void shouldSortTriplesForDisplay() { 261 final Model model = createDefaultModel(); 262 263 model.setNsPrefix("prefix", "namespace"); 264 final Property propertyA = model.createProperty("namespace", "a"); 265 final Property propertyB = model.createProperty("namespace", "b"); 266 final Property propertyC = model.createProperty("c"); 267 final Literal literalA = model.createLiteral("a"); 268 final Literal literalB = model.createLiteral("b"); 269 final Resource resourceB = model.createResource("b"); 270 model.add(resourceB, propertyA, literalA); 271 272 final Resource a = model.createResource("a"); 273 model.add(a, propertyC, literalA); 274 275 model.add(a, propertyB, literalA); 276 277 model.add(a, propertyA, literalA); 278 model.add(a, propertyA, literalB); 279 280 final Iterator<Triple> iterator = model.getGraph().find(null, null, null); 281 282 final List<Triple> sortedTriples = 283 testObj.getSortedTriples(model, iterator); 284 285 sortedTriples.get(0).matches(a.asNode(), propertyA.asNode(), 286 literalA.asNode()); 287 sortedTriples.get(1).matches(a.asNode(), propertyA.asNode(), 288 literalB.asNode()); 289 sortedTriples.get(2).matches(a.asNode(), propertyB.asNode(), 290 literalA.asNode()); 291 sortedTriples.get(3).matches(a.asNode(), propertyC.asNode(), 292 literalA.asNode()); 293 sortedTriples.get(4).matches(resourceB.asNode(), 294 propertyC.asNode(), literalA.asNode()); 295 296 } 297 298 @Test 299 public void shouldConvertPrefixMappingToSparqlUpdatePrefixPreamble() { 300 301 final Model model = createDefaultModel(); 302 303 model.setNsPrefix("prefix", "namespace"); 304 305 final String prefixPreamble = testObj.getPrefixPreamble(model); 306 307 assertEquals("PREFIX prefix: <namespace>\n\n", prefixPreamble); 308 } 309 310 @Test 311 public void shouldConvertStringLiteralsToNodes() { 312 final String uri = "fedora:resource"; 313 final Literal URIRES = ResourceFactory.createPlainLiteral(uri); 314 assertEquals(URIRES.asNode(), testObj.asLiteralStringNode(uri)); 315 } 316 317 @Test 318 public void testGetNumChildren() { 319 final Graph mem = createDefaultModel().getGraph(); 320 mem.add(new Triple(createURI("a/b/c"), CONTAINS.asNode(), createResource("a/b/c/1").asNode())); 321 mem.add(new Triple(createURI("a/b/c"), CONTAINS.asNode(), createResource("a/b/c/2").asNode())); 322 mem.add(new Triple(createURI("a/b/c"), CONTAINS.asNode(), createResource("a/b/c/3").asNode())); 323 mem.add(new Triple(createURI("a/b/c"), CONTAINS.asNode(), createResource("a/b/c/4").asNode())); 324 assertEquals(4, testObj.getNumChildren(mem, createURI("a/b/c"))); 325 } 326 327 @Test 328 public void testGetNumChildrenEmpty() { 329 final Graph mem = createDefaultModel().getGraph(); 330 assertEquals(0, testObj.getNumChildren(mem, createURI("a/b/c"))); 331 } 332 333 @Test 334 public void testIsRepositoryRoot() { 335 final Model model = createDefaultModel(); 336 model.setNsPrefix("fedora", REPOSITORY_NAMESPACE); 337 final Graph mem = model.getGraph(); 338 final Node root = createURI("http://localhost/root"); 339 final Node child = createURI("http://localhost/not_root"); 340 341 mem.add(new Triple(root, type.asNode(), BASIC_CONTAINER.asNode())); 342 mem.add(new Triple(root, type.asNode(), REPOSITORY_ROOT.asNode())); 343 mem.add(new Triple(child, type.asNode(), BASIC_CONTAINER.asNode())); 344 345 assertTrue("Root should be a Repository Root", testObj.isRootResource(mem, root)); 346 assertFalse("Child should not be a Repository Root", testObj.isRootResource(mem, child)); 347 } 348}