001/*
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.http.commons.api.rdf;
017
018import com.hp.hpl.jena.rdf.model.Resource;
019import org.fcrepo.kernel.api.TxSession;
020import org.fcrepo.kernel.api.exception.InvalidResourceIdentifierException;
021import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
022import org.fcrepo.kernel.api.models.FedoraBinary;
023import org.fcrepo.kernel.api.models.FedoraResource;
024import org.fcrepo.kernel.api.models.NonRdfSourceDescription;
025import org.fcrepo.kernel.modeshape.FedoraBinaryImpl;
026import org.fcrepo.kernel.modeshape.FedoraResourceImpl;
027import org.fcrepo.kernel.modeshape.NonRdfSourceDescriptionImpl;
028import org.junit.Before;
029import org.junit.Ignore;
030import org.junit.Test;
031import org.junit.runner.RunWith;
032import org.mockito.Mock;
033import org.mockito.runners.MockitoJUnitRunner;
034
035import javax.jcr.ItemNotFoundException;
036import javax.jcr.Node;
037import javax.jcr.Property;
038import javax.jcr.RepositoryException;
039import javax.jcr.Session;
040import javax.jcr.Workspace;
041import javax.jcr.version.Version;
042import javax.jcr.version.VersionHistory;
043import javax.jcr.version.VersionManager;
044import javax.ws.rs.core.UriBuilder;
045
046import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
047import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_NON_RDF_SOURCE_DESCRIPTION;
048import static org.fcrepo.kernel.modeshape.FedoraJcrConstants.FROZEN_NODE;
049import static org.junit.Assert.assertEquals;
050import static org.junit.Assert.assertTrue;
051import static org.mockito.Mockito.when;
052import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT;
053
054/**
055 * @author cabeer
056 */
057@RunWith(MockitoJUnitRunner.class)
058public class HttpResourceConverterTest {
059
060    @Mock
061    private Session session;
062
063    @Mock
064    private TxSession txSession;
065
066    @Mock
067    private Node node;
068
069    @Mock
070    private Node versionedNode;
071
072    @Mock
073    private Node contentNode;
074
075    @Mock
076    private Property mockProperty;
077
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        converter = new HttpResourceConverter(session, uriBuilder);
102        when(session.getNode("/" + path)).thenReturn(node);
103        when(session.getNode("/")).thenReturn(node);
104        when(node.getPath()).thenReturn("/" + path);
105        when(node.isNodeType(FROZEN_NODE)).thenReturn(false);
106        when(node.isNodeType(FEDORA_NON_RDF_SOURCE_DESCRIPTION)).thenReturn(false);
107        when(contentNode.getPath()).thenReturn("/" + path + "/jcr:content");
108        when(session.getWorkspace()).thenReturn(mockWorkspace);
109        when(mockWorkspace.getName()).thenReturn("default");
110        when(mockWorkspace.getVersionManager()).thenReturn(mockVersionManager);
111        when(versionedNode.isNodeType("nt:frozenNode")).thenReturn(true);
112    }
113
114    @Test
115    public void testDoForward() {
116        final FedoraResource converted = converter.convert(resource);
117        assertEquals(node, converted.getNode());
118    }
119
120    @Test
121    public void testDoForwardWithDatastreamContent() throws Exception {
122        when(node.isNodeType(FEDORA_NON_RDF_SOURCE_DESCRIPTION)).thenReturn(true);
123        when(node.getNode(JCR_CONTENT)).thenReturn(contentNode);
124        final FedoraResource converted = converter.convert(resource);
125        assertTrue(converted instanceof FedoraBinary);
126        assertEquals(contentNode, converted.getNode());
127    }
128
129    @Test
130    public void testDoForwardWithDatastreamMetadata() throws Exception {
131        when(node.isNodeType(FEDORA_NON_RDF_SOURCE_DESCRIPTION)).thenReturn(true);
132        final FedoraResource converted = converter.convert(metadataResource);
133        assertTrue(converted instanceof NonRdfSourceDescription);
134        assertEquals(node, converted.getNode());
135    }
136
137    @Test
138    public void testDoForwardWithAHash() throws Exception {
139        when(session.getNode("/" + path + "/#/with-a-hash")).thenReturn(node);
140        final FedoraResource converted =
141                converter.convert(createResource("http://localhost:8080/some/" + path + "#with-a-hash"));
142        assertEquals(node, converted.getNode());
143    }
144
145    @Test
146    public void testDoForwardWithTransaction() throws Exception {
147        final HttpResourceConverter converter = new HttpResourceConverter(txSession,
148                UriBuilder.fromUri(uriTemplate));
149        when(txSession.getTxId()).thenReturn("xyz");
150        when(txSession.getNode("/" + path)).thenReturn(node);
151        when(txSession.getWorkspace()).thenReturn(mockWorkspace);
152        final Resource resource = createResource("http://localhost:8080/some/tx:xyz/" + path);
153        final FedoraResource converted = converter.convert(resource);
154        assertEquals(node, converted.getNode());
155    }
156
157    @Test
158    public void testDoForwardWithUuid() throws Exception {
159        final Resource resource = createResource("http://localhost:8080/some/[xyz]");
160        when(session.getNode("/[xyz]")).thenReturn(node);
161        final FedoraResource converted = converter.convert(resource);
162        assertEquals(node, converted.getNode());
163    }
164
165    @Test
166    public void testDoForwardRoot() {
167        final Resource resource = createResource("http://localhost:8080/some/");
168        final FedoraResource converted = converter.convert(resource);
169        assertEquals(node, converted.getNode());
170        assertTrue(converter.inDomain(resource));
171    }
172
173    @Test
174    public void testDoForwardRootWithoutSlash() {
175        final Resource resource = createResource("http://localhost:8080/some");
176        final FedoraResource converted = converter.convert(resource);
177        assertEquals(node, converted.getNode());
178        assertTrue(converter.inDomain(resource));
179    }
180
181    @Test
182    public void testDoBackward() {
183        final Resource converted = converter.reverse().convert(new FedoraResourceImpl(node));
184        assertEquals(resource, converted);
185    }
186
187    @Test
188    public void testDoBackwardWithDatastreamContent() {
189        final Resource converted = converter.reverse().convert(new FedoraBinaryImpl(contentNode));
190        assertEquals(resource, converted);
191    }
192
193    @Test
194    public void testDoBackwardWithDatastreamMetadata() {
195        final Resource converted = converter.reverse().convert(new NonRdfSourceDescriptionImpl(node));
196        assertEquals(metadataResource, converted);
197    }
198
199    @Test
200    public void testDoBackwardWithHash() throws Exception {
201        when(node.getPath()).thenReturn(path + "/#/with-a-hash");
202        final Resource converted = converter.reverse().convert(new FedoraResourceImpl(node));
203        assertEquals(createResource("http://localhost:8080/some/" + path + "#with-a-hash"), converted);
204    }
205
206    @Test
207    public void testDoForwardWithImplicitVersionedDatastream() throws Exception {
208        when(session.getNodeByIdentifier("x")).thenReturn(versionedNode);
209        when(versionedNode.getProperty("jcr:frozenUuid")).thenReturn(mockProperty);
210        when(mockProperty.getString()).thenReturn("some-identifier");
211        when(node.getIdentifier()).thenReturn("some-identifier");
212        when(mockVersionManager.getVersionHistory("/" + path)).thenReturn(mockVersionHistory);
213        when(mockVersionHistory.hasVersionLabel("x")).thenReturn(true);
214        when(mockVersionHistory.getVersionByLabel("x")).thenReturn(mockVersion);
215        final FedoraResource converted = converter.convert(versionedResource);
216        assertEquals(versionedNode, converted.getNode());
217    }
218
219    @Test
220    public void testDoForwardWithExplicitVersionedDatastream() throws Exception {
221        when(session.getNodeByIdentifier("x")).thenThrow(new ItemNotFoundException());
222        when(mockVersionManager.getVersionHistory("/" + path)).thenReturn(mockVersionHistory);
223        when(mockVersionHistory.hasVersionLabel("x")).thenReturn(true);
224        when(mockVersionHistory.getVersionByLabel("x")).thenReturn(mockVersion);
225        when(mockVersion.getFrozenNode()).thenReturn(versionedNode);
226        final FedoraResource converted = converter.convert(versionedResource);
227        assertEquals(versionedNode, converted.getNode());
228    }
229
230    @Test(expected = RepositoryRuntimeException.class)
231    public void testDoForwardWithMissingVersionedDatastream() throws Exception {
232        when(session.getNodeByIdentifier("x")).thenThrow(new ItemNotFoundException());
233        when(mockVersionManager.getVersionHistory("/" + path)).thenReturn(mockVersionHistory);
234        when(mockVersionHistory.hasVersionLabel("x")).thenReturn(false);
235        converter.convert(versionedResource);
236    }
237
238    @Test
239    @Ignore
240    public void testDoBackwardWithVersionedNode() throws Exception {
241
242        when(versionedNode.getProperty("jcr:frozenUuid")).thenReturn(mockProperty);
243        when(versionedNode.getIdentifier()).thenReturn("x");
244        when(mockProperty.getString()).thenReturn("some-identifier");
245        when(node.getIdentifier()).thenReturn("some-identifier");
246        when(session.getNodeByIdentifier("some-identifier")).thenReturn(node);
247        when(node.isNodeType("mix:versionable")).thenReturn(true);
248
249        final Resource converted = converter.reverse().convert(new FedoraResourceImpl(versionedNode));
250        assertEquals(versionedResource, converted);
251    }
252
253    @Test
254    public void testDoBackwardWithTransaction() throws Exception {
255        final HttpResourceConverter converter = new HttpResourceConverter(txSession,
256                UriBuilder.fromUri(uriTemplate));
257        when(txSession.getTxId()).thenReturn("xyz");
258        when(txSession.getNode("/" + path)).thenReturn(node);
259        when(txSession.getWorkspace()).thenReturn(mockWorkspace);
260        when(node.getSession()).thenReturn(txSession);
261        final Resource resource = createResource("http://localhost:8080/some/tx:xyz/" + path);
262        final Resource converted = converter.reverse().convert(new FedoraResourceImpl(node));
263        assertEquals(resource, converted);
264    }
265
266    @Test
267    public void testToStringWithRoot() {
268        assertEquals("/", converter.asString(createResource("http://localhost:8080/some/")));
269    }
270
271    @Test (expected = InvalidResourceIdentifierException.class)
272    public void testToStringWithEmptPathSegment() {
273        converter.asString(createResource("http://localhost:8080/some/test/a//b/c/d"));
274    }
275}