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.api.rdf;
019
020import org.apache.jena.rdf.model.Resource;
021import org.fcrepo.http.commons.session.HttpSession;
022import org.fcrepo.kernel.api.FedoraSession;
023import org.fcrepo.kernel.api.exception.InvalidResourceIdentifierException;
024import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
025import org.fcrepo.kernel.api.models.FedoraBinary;
026import org.fcrepo.kernel.api.models.FedoraResource;
027import org.fcrepo.kernel.api.models.NonRdfSourceDescription;
028import org.fcrepo.kernel.modeshape.FedoraBinaryImpl;
029import org.fcrepo.kernel.modeshape.FedoraResourceImpl;
030import org.fcrepo.kernel.modeshape.FedoraSessionImpl;
031import org.fcrepo.kernel.modeshape.NonRdfSourceDescriptionImpl;
032import org.junit.Before;
033import org.junit.Ignore;
034import org.junit.Test;
035import org.junit.runner.RunWith;
036import org.mockito.Mock;
037import org.mockito.runners.MockitoJUnitRunner;
038
039import javax.jcr.ItemNotFoundException;
040import javax.jcr.Node;
041import javax.jcr.Property;
042import javax.jcr.RepositoryException;
043import javax.jcr.Session;
044import javax.jcr.Workspace;
045import javax.jcr.version.Version;
046import javax.jcr.version.VersionHistory;
047import javax.jcr.version.VersionManager;
048import javax.ws.rs.core.UriBuilder;
049
050import static org.apache.jena.rdf.model.ResourceFactory.createResource;
051import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_NON_RDF_SOURCE_DESCRIPTION;
052import static org.fcrepo.kernel.modeshape.FedoraJcrConstants.FROZEN_NODE;
053import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getJcrNode;
054import static org.fcrepo.http.commons.test.util.TestHelpers.setField;
055import static org.junit.Assert.assertEquals;
056import static org.junit.Assert.assertTrue;
057import static org.mockito.Mockito.when;
058import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT;
059
060/**
061 * @author cabeer
062 */
063@RunWith(MockitoJUnitRunner.class)
064public class HttpResourceConverterTest {
065
066    @Mock
067    private Session session, txSession;
068
069    @Mock
070    private Node node, versionedNode, contentNode;
071
072    @Mock
073    private Property mockProperty;
074
075    private FedoraSession testSession, testTxSession;
076
077    private HttpSession testHttpSession, testHttpBatchSession;
078
079    private HttpResourceConverter converter;
080    private final String uriTemplate = "http://localhost:8080/some/{path: .*}";
081    private final String path = "arbitrary/path";
082    private final Resource resource = createResource("http://localhost:8080/some/" + path);
083    private final Resource versionedResource = createResource("http://localhost:8080/some/" + path + "/fcr:versions/x");
084    private final Resource metadataResource = createResource(resource.toString() + "/fcr:metadata");
085
086    @Mock
087    private Workspace mockWorkspace;
088
089    @Mock
090    private VersionManager mockVersionManager;
091
092    @Mock
093    private VersionHistory mockVersionHistory;
094
095    @Mock
096    private Version mockVersion;
097
098    @Before
099    public void setUp() throws RepositoryException {
100        final UriBuilder uriBuilder = UriBuilder.fromUri(uriTemplate);
101        testSession = new FedoraSessionImpl(session);
102        testTxSession = new FedoraSessionImpl(txSession);
103        testHttpSession = new HttpSession(testSession);
104        testHttpBatchSession = new HttpSession(testTxSession);
105        testHttpBatchSession.makeBatchSession();
106        converter = new HttpResourceConverter(testHttpSession, uriBuilder);
107
108        when(session.getNode("/" + path)).thenReturn(node);
109        when(session.getNode("/")).thenReturn(node);
110        when(node.getPath()).thenReturn("/" + path);
111        when(node.isNodeType(FROZEN_NODE)).thenReturn(false);
112        when(node.isNodeType(FEDORA_NON_RDF_SOURCE_DESCRIPTION)).thenReturn(false);
113        when(contentNode.getPath()).thenReturn("/" + path + "/jcr:content");
114        when(session.getWorkspace()).thenReturn(mockWorkspace);
115        when(mockWorkspace.getName()).thenReturn("default");
116        when(mockWorkspace.getVersionManager()).thenReturn(mockVersionManager);
117        when(versionedNode.isNodeType("nt:frozenNode")).thenReturn(true);
118    }
119
120    @Test
121    public void testDoForward() {
122        final FedoraResource converted = converter.convert(resource);
123        assertEquals(node, getJcrNode(converted));
124    }
125
126    @Test
127    public void testDoForwardWithDatastreamContent() throws Exception {
128        when(node.isNodeType(FEDORA_NON_RDF_SOURCE_DESCRIPTION)).thenReturn(true);
129        when(node.getNode(JCR_CONTENT)).thenReturn(contentNode);
130        final FedoraResource converted = converter.convert(resource);
131        assertTrue(converted instanceof FedoraBinary);
132        assertEquals(contentNode, getJcrNode(converted));
133    }
134
135    @Test
136    public void testDoForwardWithDatastreamMetadata() throws Exception {
137        when(node.isNodeType(FEDORA_NON_RDF_SOURCE_DESCRIPTION)).thenReturn(true);
138        final FedoraResource converted = converter.convert(metadataResource);
139        assertTrue(converted instanceof NonRdfSourceDescription);
140        assertEquals(node, getJcrNode(converted));
141    }
142
143    @Test
144    public void testDoForwardWithAHash() throws Exception {
145        when(session.getNode("/" + path + "/#/with-a-hash")).thenReturn(node);
146        final FedoraResource converted =
147                converter.convert(createResource("http://localhost:8080/some/" + path + "#with-a-hash"));
148        assertEquals(node, getJcrNode(converted));
149    }
150
151    @Test
152    public void testDoForwardWithTransaction() throws Exception {
153        setField(testTxSession, "id", "xyz");
154        final HttpResourceConverter converter = new HttpResourceConverter(testHttpBatchSession,
155                UriBuilder.fromUri(uriTemplate));
156        when(txSession.getNode("/" + path)).thenReturn(node);
157        when(txSession.getWorkspace()).thenReturn(mockWorkspace);
158        final Resource resource = createResource("http://localhost:8080/some/tx:xyz/" + path);
159        final FedoraResource converted = converter.convert(resource);
160        assertEquals(node, getJcrNode(converted));
161    }
162
163    @Test
164    public void testDoForwardWithUuid() throws Exception {
165        final Resource resource = createResource("http://localhost:8080/some/[xyz]");
166        when(session.getNode("/[xyz]")).thenReturn(node);
167        final FedoraResource converted = converter.convert(resource);
168        assertEquals(node, getJcrNode(converted));
169    }
170
171    @Test
172    public void testDoForwardRoot() {
173        final Resource resource = createResource("http://localhost:8080/some/");
174        final FedoraResource converted = converter.convert(resource);
175        assertEquals(node, getJcrNode(converted));
176        assertTrue(converter.inDomain(resource));
177    }
178
179    @Test
180    public void testDoForwardRootWithoutSlash() {
181        final Resource resource = createResource("http://localhost:8080/some");
182        final FedoraResource converted = converter.convert(resource);
183        assertEquals(node, getJcrNode(converted));
184        assertTrue(converter.inDomain(resource));
185    }
186
187    @Test
188    public void testDoBackward() {
189        final Resource converted = converter.reverse().convert(new FedoraResourceImpl(node));
190        assertEquals(resource, converted);
191    }
192
193    @Test
194    public void testDoBackwardWithDatastreamContent() {
195        final Resource converted = converter.reverse().convert(new FedoraBinaryImpl(contentNode));
196        assertEquals(resource, converted);
197    }
198
199    @Test
200    public void testDoBackwardWithDatastreamMetadata() {
201        final Resource converted = converter.reverse().convert(new NonRdfSourceDescriptionImpl(node));
202        assertEquals(metadataResource, converted);
203    }
204
205    @Test
206    public void testDoBackwardWithHash() throws Exception {
207        when(node.getPath()).thenReturn(path + "/#/with-a-hash");
208        final Resource converted = converter.reverse().convert(new FedoraResourceImpl(node));
209        assertEquals(createResource("http://localhost:8080/some/" + path + "#with-a-hash"), converted);
210    }
211
212    @Test
213    public void testDoForwardWithImplicitVersionedDatastream() throws Exception {
214        when(session.getNodeByIdentifier("x")).thenReturn(versionedNode);
215        when(versionedNode.getProperty("jcr:frozenUuid")).thenReturn(mockProperty);
216        when(mockProperty.getString()).thenReturn("some-identifier");
217        when(node.getIdentifier()).thenReturn("some-identifier");
218        when(mockVersionManager.getVersionHistory("/" + path)).thenReturn(mockVersionHistory);
219        when(mockVersionHistory.hasVersionLabel("x")).thenReturn(true);
220        when(mockVersionHistory.getVersionByLabel("x")).thenReturn(mockVersion);
221        final FedoraResource converted = converter.convert(versionedResource);
222        assertEquals(versionedNode, getJcrNode(converted));
223    }
224
225    @Test
226    public void testDoForwardWithExplicitVersionedDatastream() throws Exception {
227        when(session.getNodeByIdentifier("x")).thenThrow(new ItemNotFoundException());
228        when(mockVersionManager.getVersionHistory("/" + path)).thenReturn(mockVersionHistory);
229        when(mockVersionHistory.hasVersionLabel("x")).thenReturn(true);
230        when(mockVersionHistory.getVersionByLabel("x")).thenReturn(mockVersion);
231        when(mockVersion.getFrozenNode()).thenReturn(versionedNode);
232        final FedoraResource converted = converter.convert(versionedResource);
233        assertEquals(versionedNode, getJcrNode(converted));
234    }
235
236    @Test(expected = RepositoryRuntimeException.class)
237    public void testDoForwardWithMissingVersionedDatastream() throws Exception {
238        when(session.getNodeByIdentifier("x")).thenThrow(new ItemNotFoundException());
239        when(mockVersionManager.getVersionHistory("/" + path)).thenReturn(mockVersionHistory);
240        when(mockVersionHistory.hasVersionLabel("x")).thenReturn(false);
241        converter.convert(versionedResource);
242    }
243
244    @Test
245    @Ignore
246    public void testDoBackwardWithVersionedNode() throws Exception {
247
248        when(versionedNode.getProperty("jcr:frozenUuid")).thenReturn(mockProperty);
249        when(versionedNode.getIdentifier()).thenReturn("x");
250        when(mockProperty.getString()).thenReturn("some-identifier");
251        when(node.getIdentifier()).thenReturn("some-identifier");
252        when(session.getNodeByIdentifier("some-identifier")).thenReturn(node);
253        when(node.isNodeType("mix:versionable")).thenReturn(true);
254
255        final Resource converted = converter.reverse().convert(new FedoraResourceImpl(versionedNode));
256        assertEquals(versionedResource, converted);
257    }
258
259    @Test
260    public void testDoBackwardWithTransaction() throws Exception {
261        setField(testTxSession, "id", "xyz");
262        final HttpResourceConverter converter = new HttpResourceConverter(testHttpBatchSession,
263                UriBuilder.fromUri(uriTemplate));
264        when(txSession.getNode("/" + path)).thenReturn(node);
265        when(txSession.getWorkspace()).thenReturn(mockWorkspace);
266        when(node.getSession()).thenReturn(txSession);
267        final Resource resource = createResource("http://localhost:8080/some/tx:xyz/" + path);
268        final Resource converted = converter.reverse().convert(new FedoraResourceImpl(node));
269        assertEquals(resource, converted);
270    }
271
272    @Test
273    public void testToStringWithRoot() {
274        assertEquals("/", converter.asString(createResource("http://localhost:8080/some/")));
275    }
276
277    @Test (expected = InvalidResourceIdentifierException.class)
278    public void testToStringWithEmptPathSegment() {
279        converter.asString(createResource("http://localhost:8080/some/test/a//b/c/d"));
280    }
281}