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