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.kernel.impl.operations; 007 008import static junit.framework.TestCase.assertTrue; 009import static org.fcrepo.kernel.api.RdfCollectors.toModel; 010import static org.fcrepo.kernel.api.RdfLexicon.CREATED_BY; 011import static org.fcrepo.kernel.api.RdfLexicon.CREATED_DATE; 012import static org.fcrepo.kernel.api.RdfLexicon.LAST_MODIFIED_BY; 013import static org.fcrepo.kernel.api.RdfLexicon.LAST_MODIFIED_DATE; 014import static org.fcrepo.kernel.api.RdfLexicon.RDF_SOURCE; 015import static org.fcrepo.kernel.api.rdf.DefaultRdfStream.fromModel; 016import static org.junit.Assert.assertEquals; 017import static org.junit.Assert.assertFalse; 018import static org.junit.Assert.assertNull; 019 020import java.io.ByteArrayOutputStream; 021import java.io.OutputStream; 022import java.time.Instant; 023import java.util.Calendar; 024import java.util.Date; 025 026import org.fcrepo.config.ServerManagedPropsMode; 027import org.fcrepo.kernel.api.RdfStream; 028import org.fcrepo.kernel.api.Transaction; 029import org.fcrepo.kernel.api.exception.MalformedRdfException; 030import org.fcrepo.kernel.api.identifiers.FedoraId; 031import org.fcrepo.kernel.api.operations.CreateRdfSourceOperation; 032import org.fcrepo.kernel.api.operations.CreateRdfSourceOperationBuilder; 033import org.fcrepo.kernel.api.operations.RdfSourceOperation; 034 035import org.apache.jena.datatypes.xsd.XSDDateTime; 036import org.apache.jena.graph.Node; 037import org.apache.jena.rdf.model.Model; 038import org.apache.jena.rdf.model.ModelFactory; 039import org.apache.jena.rdf.model.Property; 040import org.apache.jena.rdf.model.RDFNode; 041import org.apache.jena.rdf.model.Resource; 042import org.apache.jena.rdf.model.ResourceFactory; 043import org.junit.Before; 044import org.junit.Test; 045import org.junit.runner.RunWith; 046import org.mockito.Mock; 047import org.mockito.junit.MockitoJUnitRunner; 048 049/** 050 * @author bseeger 051 */ 052@RunWith(MockitoJUnitRunner.Silent.class) 053public class CreateRdfSourceOperationBuilderTest { 054 055 private CreateRdfSourceOperationBuilder builder; 056 057 private Model model; 058 059 private RdfStream stream; 060 061 private static final FedoraId PARENT_ID = FedoraId.create("info:fedora/parent"); 062 063 private static final FedoraId RESOURCE_ID = FedoraId.create("info:fedora/test-subject"); 064 065 private static final Resource id = ResourceFactory.createResource(RESOURCE_ID.getResourceId()); 066 private static final Node id_node = id.asNode(); 067 068 private static final String PROPERTY_ID = "http://example.org/isLinkedTo/"; 069 070 private static final Property prop = ResourceFactory.createProperty(PROPERTY_ID); 071 072 private static final String OBJECT_VALUE = "Somebody"; 073 074 private static final RDFNode object = ResourceFactory.createPlainLiteral(OBJECT_VALUE); 075 076 private final Instant CREATED_INSTANT = Instant.parse("2019-11-12T10:00:30.0Z"); 077 private XSDDateTime Created_xsddatetime; 078 079 private final Instant MODIFIED_INSTANT = Instant.parse("2019-11-12T14:11:05.0Z"); 080 private XSDDateTime Modified_xsddatetime; 081 082 private final String USER_PRINCIPAL = "fedoraUser"; 083 084 private final Calendar calendar = Calendar.getInstance(); 085 086 @Mock 087 private Transaction tx; 088 089 @Before 090 public void setUp() { 091 calendar.setTime(Date.from(CREATED_INSTANT)); 092 Created_xsddatetime = new XSDDateTime(calendar); 093 calendar.setTime(Date.from(MODIFIED_INSTANT)); 094 Modified_xsddatetime = new XSDDateTime(calendar); 095 builder = new CreateRdfSourceOperationBuilderImpl(tx, RESOURCE_ID, RDF_SOURCE.toString(), 096 ServerManagedPropsMode.STRICT); 097 model = ModelFactory.createDefaultModel(); 098 model.add( 099 ResourceFactory.createResource(RESOURCE_ID.getResourceId()), 100 ResourceFactory.createProperty(PROPERTY_ID), 101 ResourceFactory.createPlainLiteral(OBJECT_VALUE) 102 ); 103 final OutputStream outputStream = new ByteArrayOutputStream(); 104 model.write(outputStream, "TURTLE"); 105 stream = fromModel(id_node, model); 106 } 107 108 @Test 109 public void testStream() { 110 final RdfSourceOperation op = builder.triples(stream).build(); 111 assertEquals(CreateRdfSourceOperationImpl.class, op.getClass()); 112 final var newModel = op.getTriples().collect(toModel()); 113 assertTrue(newModel.contains(id, prop, object)); 114 assertModelsMatch(model, newModel); 115 } 116 117 private void assertModelsMatch(final Model expected, final Model test) { 118 final var stmtIter = expected.listStatements(); 119 while (stmtIter.hasNext()) { 120 final var testStmt = stmtIter.nextStatement(); 121 assertTrue(test.contains(testStmt)); 122 test.remove(testStmt); 123 } 124 assertTrue(test.isEmpty()); 125 } 126 127 @Test 128 public void testRelaxedPropertiesAllFields() { 129 final var resc = model.getResource(RESOURCE_ID.getResourceId()); 130 resc.addLiteral(LAST_MODIFIED_DATE, Modified_xsddatetime); 131 resc.addLiteral(LAST_MODIFIED_BY, USER_PRINCIPAL); 132 resc.addLiteral(CREATED_DATE, Created_xsddatetime); 133 resc.addLiteral(CREATED_BY, USER_PRINCIPAL); 134 135 final RdfSourceOperation op = buildOperationWithRelaxProperties(model); 136 137 assertEquals(USER_PRINCIPAL, op.getCreatedBy()); 138 assertEquals(USER_PRINCIPAL, op.getLastModifiedBy()); 139 assertEquals(CREATED_INSTANT, op.getCreatedDate()); 140 assertEquals(MODIFIED_INSTANT, op.getLastModifiedDate()); 141 } 142 143 @Test(expected = MalformedRdfException.class) 144 public void testRelaxedPropertiesNonDate() { 145 final var resc = model.getResource(RESOURCE_ID.getResourceId()); 146 resc.addLiteral(LAST_MODIFIED_DATE, "Notadate"); 147 resc.addLiteral(LAST_MODIFIED_BY, USER_PRINCIPAL); 148 resc.addLiteral(CREATED_DATE, Created_xsddatetime); 149 resc.addLiteral(CREATED_BY, USER_PRINCIPAL); 150 151 final RdfSourceOperation op = buildOperationWithRelaxProperties(model); 152 153 assertEquals(USER_PRINCIPAL, op.getCreatedBy()); 154 assertEquals(USER_PRINCIPAL, op.getLastModifiedBy()); 155 assertNull(op.getCreatedDate()); 156 assertNull(op.getLastModifiedDate()); 157 } 158 159 @Test(expected = MalformedRdfException.class) 160 public void testRelaxedPropertiesNonDate2() { 161 final var resc = model.getResource(RESOURCE_ID.getResourceId()); 162 resc.addLiteral(LAST_MODIFIED_DATE, Modified_xsddatetime); 163 resc.addLiteral(LAST_MODIFIED_BY, USER_PRINCIPAL); 164 resc.addLiteral(CREATED_DATE, "Notadate"); 165 resc.addLiteral(CREATED_BY, USER_PRINCIPAL); 166 167 final RdfSourceOperation op = buildOperationWithRelaxProperties(model); 168 169 assertEquals(USER_PRINCIPAL, op.getCreatedBy()); 170 assertEquals(USER_PRINCIPAL, op.getLastModifiedBy()); 171 assertNull(op.getCreatedDate()); 172 assertNull(op.getLastModifiedDate()); 173 } 174 175 @Test 176 public void testRelaxedPropertiesNotRelaxed() { 177 final var resc = model.getResource(RESOURCE_ID.getResourceId()); 178 resc.addLiteral(LAST_MODIFIED_DATE, Modified_xsddatetime); 179 resc.addLiteral(LAST_MODIFIED_BY, USER_PRINCIPAL); 180 resc.addLiteral(CREATED_DATE, Created_xsddatetime); 181 resc.addLiteral(CREATED_BY, USER_PRINCIPAL); 182 183 // Relaxed system property not set 184 final RdfSourceOperation op = builder.relaxedProperties(model).build(); 185 186 assertNull(op.getCreatedBy()); 187 assertNull(op.getLastModifiedBy()); 188 assertNull(op.getCreatedDate()); 189 assertNull(op.getLastModifiedDate()); 190 } 191 192 @Test 193 public void testRelaxedPropertiesNoProperties() { 194 final RdfSourceOperation op = buildOperationWithRelaxProperties(model); 195 196 assertNull(op.getCreatedBy()); 197 assertNull(op.getLastModifiedBy()); 198 assertNull(op.getCreatedDate()); 199 assertNull(op.getLastModifiedDate()); 200 } 201 202 @Test 203 public void testArchivalGroupFalseByDefault() { 204 final CreateRdfSourceOperation op = builder.build(); 205 assertFalse(op.isArchivalGroup()); 206 } 207 208 @Test 209 public void testArchivalGroup() { 210 final CreateRdfSourceOperation op = builder.archivalGroup(true).build(); 211 assertTrue(op.isArchivalGroup()); 212 } 213 214 215 private RdfSourceOperation buildOperationWithRelaxProperties(final Model model) { 216 builder = new CreateRdfSourceOperationBuilderImpl(tx, RESOURCE_ID, RDF_SOURCE.toString(), 217 ServerManagedPropsMode.RELAXED); 218 return builder.relaxedProperties(model).build(); 219 } 220 221 @Test 222 public void testUserPrincipal() { 223 final RdfSourceOperation op = builder.userPrincipal(USER_PRINCIPAL).build(); 224 225 assertEquals(USER_PRINCIPAL, op.getUserPrincipal()); 226 } 227 228 @Test 229 public void testParentId() { 230 final CreateRdfSourceOperation op = builder.parentId(PARENT_ID).build(); 231 232 assertEquals(PARENT_ID, op.getParentId()); 233 } 234}