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