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