/* * Licensed to DuraSpace under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. * * DuraSpace licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fcrepo.integration.kernel.modeshape; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Collections.emptySet; import static java.util.regex.Pattern.compile; import static org.apache.commons.io.IOUtils.toInputStream; import static org.apache.jena.datatypes.xsd.XSDDatatype.XSDstring; import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel; import static org.fcrepo.kernel.api.RequiredRdfContext.PROPERTIES; import static org.fcrepo.kernel.api.RdfCollectors.toModel; import static org.fcrepo.kernel.modeshape.FedoraJcrConstants.FIELD_DELIMITER; import static org.fcrepo.kernel.modeshape.FedoraSessionImpl.getJcrSession; import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getJcrNode; import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getReferencePropertyName; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import javax.inject.Inject; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.Value; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.Resource; import org.fcrepo.kernel.api.FedoraRepository; import org.fcrepo.kernel.api.FedoraSession; import org.fcrepo.kernel.api.exception.MalformedRdfException; import org.fcrepo.kernel.api.models.Container; import org.fcrepo.kernel.api.services.ContainerService; import org.fcrepo.kernel.modeshape.rdf.impl.DefaultIdentifierTranslator; import org.junit.Before; import org.junit.Test; import org.springframework.test.context.ContextConfiguration; /** * <p>{@link ContainerImplIT} class.</p> * * @author ksclarke * @author ajs6f */ @ContextConfiguration({"/spring-test/repo.xml"}) public class ContainerImplIT extends AbstractIT { @Inject FedoraRepository repo; @Inject ContainerService containerService; private FedoraSession session; private DefaultIdentifierTranslator subjects; @Before public void setUp() throws RepositoryException { session = repo.login(); subjects = new DefaultIdentifierTranslator(getJcrSession(session)); } @Test public void testCreatedObject() throws RepositoryException { containerService.findOrCreate(session, "/testObject"); session.commit(); session.expire(); session = repo.login(); final Container obj = containerService.findOrCreate(session, "/testObject"); assertNotNull("Couldn't find object!", obj); } @Test public void testObjectGraph() throws Exception { final Container object = containerService.findOrCreate(session, "/graphObject"); final Model model = object.getTriples(subjects, PROPERTIES).collect(toModel()); final Resource graphSubject = subjects.reverse().convert(object); assertFalse("Graph store should not contain JCR prefixes", compile("jcr").matcher(model.toString()).find()); assertFalse("Graph store should contain our fcrepo prefix", compile("fcrepo") .matcher(model.toString()).find()); object.updateProperties(subjects, "PREFIX dc: <http://purl.org/dc/elements/1.1/>\n" + "INSERT { <" + graphSubject + "> dc:title " + "\"This is an example title\" } WHERE {}", object.getTriples(subjects, PROPERTIES)); final Value[] values = getJcrNode(object).getProperty("dc:title").getValues(); assertTrue(values.length > 0); assertTrue(values[0] .getString(), values[0] .getString().equals("This is an example title" + FIELD_DELIMITER + XSDstring.getURI())); object.updateProperties(subjects, "PREFIX myurn: <info:myurn/>\n" + "INSERT { <" + graphSubject + "> myurn:info " + "\"This is some example data\"} WHERE {}", object.getTriples(subjects, PROPERTIES)); final Value value = getJcrNode(object).getProperty(getJcrNode(object).getSession() .getNamespacePrefix("info:myurn/") + ":info").getValues()[0]; assertEquals("This is some example data" + FIELD_DELIMITER + XSDstring.getURI(), value.getString()); object.updateProperties(subjects, "PREFIX dcterms: <http://purl.org/dc/terms/>\n" + "INSERT { <" + graphSubject + "> dcterms:" + "isPartOf <" + graphSubject + "> } WHERE {}", object.getTriples(subjects, PROPERTIES)); final Value refValue = getJcrNode(object).getProperty("dcterms:isPartOf_ref").getValues()[0]; assertTrue(refValue.getString(), refValue.getString().equals(getJcrNode(object).getIdentifier())); object.updateProperties(subjects, "PREFIX dc: <http://purl.org/dc/elements/1.1/>\n" + "DELETE { <" + graphSubject + "> dc:title " + "\"This is an example title\" } WHERE {}", object.getTriples(subjects, PROPERTIES)); assertFalse("Found unexpected dc:title", getJcrNode(object).hasProperty("dc:title")); object.updateProperties(subjects, "PREFIX dcterms: <http://purl.org/dc/terms/>\n" + "DELETE { <" + graphSubject + "> " + "dcterms:isPartOf <" + graphSubject + "> " + "} WHERE {}", object.getTriples(subjects, PROPERTIES)); assertFalse("found unexpected reference", getJcrNode(object).hasProperty("dcterms:isPartOf")); session.commit(); } @Test public void testObjectGraphWithUriProperty() throws RepositoryException { final Container object = containerService.findOrCreate(session, "/graphObject"); final Resource graphSubject = subjects.reverse().convert(object); final Session jcrSession = getJcrSession(session); object.updateProperties(subjects, "PREFIX some: <info:some#>\n" + "INSERT { <" + graphSubject + "> some:urlProperty " + "<" + graphSubject + "> } WHERE {}", object.getTriples(subjects, PROPERTIES)); final String prefix = jcrSession.getWorkspace().getNamespaceRegistry().getPrefix("info:some#"); final String propertyName = prefix + ":urlProperty"; final String referencePropertyName = getReferencePropertyName(propertyName); assertTrue(getJcrNode(object).hasProperty(referencePropertyName)); assertFalse(getJcrNode(object).hasProperty(propertyName)); assertEquals(getJcrNode(object), jcrSession.getNodeByIdentifier( getJcrNode(object).getProperty(prefix + ":urlProperty_ref").getValues()[0].getString())); object.updateProperties(subjects, "PREFIX some: <info:some#>\n" + "DELETE { <" + graphSubject + "> some:urlProperty " + "<" + graphSubject + "> } WHERE {}", object.getTriples(subjects, PROPERTIES)); assertFalse(getJcrNode(object).hasProperty(referencePropertyName)); assertFalse(getJcrNode(object).hasProperty(propertyName)); object.updateProperties(subjects, "PREFIX some: <info:some#>\n" + "INSERT DATA { <" + graphSubject + "> some:urlProperty <" + graphSubject + ">;\n" + " some:urlProperty <info:somewhere/else> . }", object.getTriples(subjects, PROPERTIES)); assertTrue(getJcrNode(object).hasProperty(referencePropertyName)); assertTrue(getJcrNode(object).hasProperty(propertyName)); assertEquals(1, getJcrNode(object).getProperty(prefix + ":urlProperty_ref").getValues().length); assertEquals(getJcrNode(object), jcrSession.getNodeByIdentifier( getJcrNode(object).getProperty(prefix + ":urlProperty_ref").getValues()[0].getString())); } @Test public void testUpdatingObjectGraphWithErrors() { final String pid = getRandomPid(); final Container object = containerService.findOrCreate(session, pid); MalformedRdfException e = null; try { object.updateProperties(subjects, "INSERT DATA { <> <info:some-property> <relative-url> . \n" + "<> <info:some-other-property> <another-relative-url> }", object.getTriples(subjects, emptySet())); } catch (final MalformedRdfException ex) { e = ex; } assertNotNull("Expected an exception to get thrown", e); assertEquals("Excepted two nested exceptions", 2, e.getMessage().split("\n").length); assertTrue(e.getMessage().contains("/relative-url")); assertTrue(e.getMessage().contains("/another-relative-url")); } @Test public void testReplaceObjectGraphWithErrors() { final String pid = getRandomPid(); final Container object = containerService.findOrCreate(session, pid); final Model model = createDefaultModel().read( toInputStream("<> <info:some-property> <relative-url> . \n" + "<> <info:some-other-property> <another-relative-url>", UTF_8), subjects.reverse().convert(object).toString(), "TTL"); MalformedRdfException e = null; try { object.replaceProperties(subjects, model, object.getTriples(subjects, emptySet())); } catch (final MalformedRdfException ex) { e = ex; } assertNotNull("Expected an exception to get thrown", e); assertEquals("Excepted two nested exceptions", 2, e.getMessage().split("\n").length); assertTrue(e.getMessage().contains("/relative-url")); assertTrue(e.getMessage().contains("/another-relative-url")); } @Test(expected = MalformedRdfException.class) public void testUpdatingObjectGraphWithOutOfDomainSubjects() throws MalformedRdfException { final Container object = containerService.findOrCreate(session, "/graphObject"); object.updateProperties(subjects, "PREFIX dc: <http://purl.org/dc/elements/1.1/>\n" + "INSERT { <http://example/egbook> dc:title " + "\"This is an example of an update that will be " + "ignored\" } WHERE {}", object.getTriples(subjects, PROPERTIES)); } }