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