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.migration;
017
018import java.io.ByteArrayInputStream;
019import java.io.ByteArrayOutputStream;
020import java.io.File;
021import java.io.FileNotFoundException;
022import java.io.IOException;
023import java.io.InputStream;
024import java.net.URL;
025import java.util.ArrayList;
026import java.util.Collections;
027import java.util.Iterator;
028import java.util.List;
029
030import javax.xml.stream.XMLStreamException;
031
032import org.apache.commons.io.IOUtils;
033import org.fcrepo.migration.foxml.CachedContent;
034import org.fcrepo.migration.foxml.FoxmlInputStreamFedoraObjectProcessor;
035import org.fcrepo.migration.foxml.InternalIDResolver;
036import org.fcrepo.migration.foxml.URLFetcher;
037import org.junit.Assert;
038import org.junit.Test;
039
040/**
041 * An abstract base class that defines some dummy classes useful for
042 * testing a Migrator instance and a suite of tests appropriate for
043 * a single example object.  Subclasses may expose this example object
044 * in different ways.
045 * @author mdurbin
046 */
047public abstract class Example1TestSuite {
048
049    protected abstract DummyHandler getResult();
050
051    protected abstract DummyURLFetcher getFetcher();
052
053
054    @Test
055    public void testObjectInfoParsing() {
056        Assert.assertEquals("example:1", getResult().objectInfo.getPid());
057        Assert.assertNull(getResult().objectInfo.getFedoraURI());
058    }
059
060    @Test
061    public void testPropertiesParsing() {
062        final List<? extends ObjectProperty> propertyList = getResult().properties.listProperties();
063        Assert.assertEquals(5, propertyList.size());
064        Assert.assertEquals("info:fedora/fedora-system:def/model#state", propertyList.get(0).getName());
065        Assert.assertEquals("Active", propertyList.get(0).getValue());
066        Assert.assertEquals("info:fedora/fedora-system:def/model#label", propertyList.get(1).getName());
067        Assert.assertEquals("This is an example object.", propertyList.get(1).getValue());
068        Assert.assertEquals("info:fedora/fedora-system:def/model#ownerId", propertyList.get(2).getName());
069        Assert.assertEquals("exampleOwner", propertyList.get(2).getValue());
070        Assert.assertEquals("info:fedora/fedora-system:def/model#createdDate", propertyList.get(3).getName());
071        Assert.assertEquals("2015-01-27T19:07:33.120Z", propertyList.get(3).getValue());
072        Assert.assertEquals("info:fedora/fedora-system:def/view#lastModifiedDate", propertyList.get(4).getName());
073        Assert.assertEquals("2015-01-27T20:26:16.998Z", propertyList.get(4).getValue());
074    }
075
076    @Test
077    public void testDatastreamParsing() throws XMLStreamException, IOException {
078        Assert.assertEquals(7, getResult().dsVersions.size());
079    }
080
081    @Test
082    public void testAuditDatastreamParsing() {
083        final DatastreamVersion audit0 = getResult().dsVersions.get(0);
084        Assert.assertEquals("AUDIT", audit0.getDatastreamInfo().getDatastreamId());
085        Assert.assertEquals("A", audit0.getDatastreamInfo().getState());
086        Assert.assertEquals("X", audit0.getDatastreamInfo().getControlGroup());
087        Assert.assertFalse(audit0.getDatastreamInfo().getVersionable());
088        Assert.assertEquals("AUDIT.0", audit0.getVersionId());
089        Assert.assertEquals("Audit Trail for this object", audit0.getLabel());
090        Assert.assertEquals("2015-01-27T19:07:33.120Z", audit0.getCreated());
091        Assert.assertEquals("text/xml", audit0.getMimeType());
092        Assert.assertEquals("info:fedora/fedora-system:format/xml.fedora.audit", audit0.getFormatUri());
093    }
094
095    @Test
096    public void testDCDatastreamParsing() throws IOException {
097        final DatastreamVersion dc0 = getResult().dsVersions.get(1);
098        Assert.assertEquals("DC", dc0.getDatastreamInfo().getDatastreamId());
099        Assert.assertEquals("A", dc0.getDatastreamInfo().getState());
100        Assert.assertEquals("X", dc0.getDatastreamInfo().getControlGroup());
101        Assert.assertTrue(dc0.getDatastreamInfo().getVersionable());
102        Assert.assertEquals("DC1.0", dc0.getVersionId());
103        Assert.assertEquals("Dublin Core Record for this object", dc0.getLabel());
104        Assert.assertEquals("2015-01-27T19:07:33.120Z", dc0.getCreated());
105        Assert.assertEquals("text/xml", dc0.getMimeType());
106        Assert.assertEquals("http://www.openarchives.org/OAI/2.0/oai_dc/", dc0.getFormatUri());
107        Assert.assertEquals(dc0.getSize(), IOUtils.toByteArray(dc0.getContent()).length);
108        Assert.assertEquals("<oai_dc:dc xmlns:oai_dc=\"http://www.openarchives.org/OAI/2.0/oai_dc/\"\n" +
109                "xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n" +
110                "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
111                "xsi:schemaLocation=\"http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd\">\n" +
112                "  <dc:title>This is an example object.</dc:title>\n" +
113                "  <dc:identifier>example:1</dc:identifier>\n" +
114                "</oai_dc:dc>", IOUtils.toString(dc0.getContent()).trim());
115    }
116
117    @Test
118    public void testDS1VersionedDatastreamParsing() throws IOException {
119        final DatastreamVersion ds1 = getResult().dsVersions.get(2);
120        Assert.assertEquals("DS1", ds1.getDatastreamInfo().getDatastreamId());
121        Assert.assertEquals("A", ds1.getDatastreamInfo().getState());
122        Assert.assertEquals("X", ds1.getDatastreamInfo().getControlGroup());
123        Assert.assertTrue(ds1.getDatastreamInfo().getVersionable());
124        Assert.assertEquals("DS1.0", ds1.getVersionId());
125        Assert.assertEquals("Example inline XML datastream", ds1.getLabel());
126        Assert.assertEquals("2015-01-27T19:08:43.701Z", ds1.getCreated());
127        Assert.assertEquals("text/xml", ds1.getMimeType());
128        Assert.assertEquals("alternate_id", ds1.getAltIds());
129        Assert.assertEquals("format:uri", ds1.getFormatUri());
130        Assert.assertEquals(34, ds1.getSize());
131        Assert.assertEquals("<test>\n" +
132                "  This is a test.\n" +
133                "</test>", IOUtils.toString(ds1.getContent()).trim());
134
135        final DatastreamVersion ds2 = getResult().dsVersions.get(3);
136        Assert.assertEquals("DS1", ds2.getDatastreamInfo().getDatastreamId());
137        Assert.assertEquals("A", ds2.getDatastreamInfo().getState());
138        Assert.assertEquals("X", ds2.getDatastreamInfo().getControlGroup());
139        Assert.assertTrue(ds2.getDatastreamInfo().getVersionable());
140        Assert.assertEquals("DS1.1", ds2.getVersionId());
141        Assert.assertEquals("Example inline XML datastream", ds2.getLabel());
142        Assert.assertEquals("2015-01-27T19:20:40.678Z", ds2.getCreated());
143        Assert.assertEquals("text/xml", ds2.getMimeType());
144        Assert.assertEquals("alternate_id", ds2.getAltIds());
145        Assert.assertEquals("format:uri", ds2.getFormatUri());
146        Assert.assertEquals(50, ds2.getSize());
147        Assert.assertNull(ds2.getContentDigest());
148        Assert.assertEquals("<test>\n" +
149                "  This is a test that was edited.\n" +
150                "</test>", IOUtils.toString(ds2.getContent()).trim());
151    }
152
153    @Test
154    public void testDS2BinaryParsing() throws IOException {
155        final DatastreamVersion ds2 = getResult().dsVersions.get(4);
156        Assert.assertEquals("DS2", ds2.getDatastreamInfo().getDatastreamId());
157        Assert.assertEquals("A", ds2.getDatastreamInfo().getState());
158        Assert.assertEquals("M", ds2.getDatastreamInfo().getControlGroup());
159        Assert.assertFalse(ds2.getDatastreamInfo().getVersionable());
160        Assert.assertEquals("DS2.0", ds2.getVersionId());
161        Assert.assertEquals("Example Managed binary datastream", ds2.getLabel());
162        Assert.assertEquals("2015-01-27T19:09:18.112Z", ds2.getCreated());
163        Assert.assertEquals("image/jpeg", ds2.getMimeType());
164        Assert.assertEquals(46168, ds2.getSize());
165        Assert.assertEquals("MD5", ds2.getContentDigest().getType());
166        Assert.assertEquals("d4f18b8b9c64466819ddaad46228fb9b", ds2.getContentDigest().getDigest());
167        Assert.assertTrue("Managed Base64 encoded datastream must be preserved.", IOUtils.contentEquals(
168                getClass().getClassLoader().getResourceAsStream("small-mountains.jpg"),
169                new ByteArrayInputStream(getResult().cachedDsVersionBinaries.get(4))));
170    }
171
172    @Test
173    public void testDS3RedirectParsing() throws IOException {
174        final DatastreamVersion ds3 = getResult().dsVersions.get(5);
175        Assert.assertEquals("DS3", ds3.getDatastreamInfo().getDatastreamId());
176        Assert.assertEquals("A", ds3.getDatastreamInfo().getState());
177        Assert.assertEquals("R", ds3.getDatastreamInfo().getControlGroup());
178        Assert.assertTrue(ds3.getDatastreamInfo().getVersionable());
179        Assert.assertEquals("DS3.0", ds3.getVersionId());
180        Assert.assertEquals("Example Redirect \u007Fdatastream.", ds3.getLabel());
181        Assert.assertEquals("2015-01-27T19:14:05.948Z", ds3.getCreated());
182        Assert.assertEquals("image/jpeg", ds3.getMimeType());
183        Assert.assertEquals(-1, ds3.getSize());
184        ds3.getContent().close();
185        Assert.assertEquals("http://" + SimpleObjectSource.LOCAL_FEDORA_SERVER + "/fedora/get/example:1/DS2",
186                getFetcher().getLastUrl().toExternalForm());
187    }
188
189    @Test
190    public void testDS4ExternalParsing() throws IOException {
191        final DatastreamVersion ds4 = getResult().dsVersions.get(6);
192        Assert.assertEquals("DS4", ds4.getDatastreamInfo().getDatastreamId());
193        Assert.assertEquals("A", ds4.getDatastreamInfo().getState());
194        Assert.assertEquals("E", ds4.getDatastreamInfo().getControlGroup());
195        Assert.assertTrue(ds4.getDatastreamInfo().getVersionable());
196        Assert.assertEquals("DS4.0", ds4.getVersionId());
197        Assert.assertEquals("Example External datastream.", ds4.getLabel());
198        Assert.assertEquals("2015-01-27T19:14:38.999Z", ds4.getCreated());
199        Assert.assertEquals("image/jpeg", ds4.getMimeType());
200        Assert.assertEquals(-1, ds4.getSize());
201        ds4.getContent().close();
202        Assert.assertEquals("http://" + SimpleObjectSource.LOCAL_FEDORA_SERVER
203                        + "/fedora/objects/example:1/datastreams/DS2/content",
204                getFetcher().getLastUrl().toExternalForm());
205    }
206
207    public static class SimpleObjectSource implements ObjectSource {
208
209        private static final String LOCAL_FEDORA_SERVER = "replaced-local-fedora-server";
210
211        private FedoraObjectProcessor p;
212
213        public SimpleObjectSource(final String path, final URLFetcher f,
214                final InternalIDResolver resolver) throws XMLStreamException {
215            try {
216                p = new FoxmlInputStreamFedoraObjectProcessor(new File(path),
217                        f, resolver, LOCAL_FEDORA_SERVER);
218            } catch (FileNotFoundException e) {
219                throw new RuntimeException(e);
220            }
221        }
222
223        @Override
224        public Iterator<FedoraObjectProcessor> iterator() {
225            return Collections.singletonList(p).iterator();
226        }
227    }
228
229    public static class DummyHandler implements StreamingFedoraObjectHandler {
230
231        ObjectInfo objectInfo;
232        ObjectProperties properties;
233        List<DatastreamVersion> dsVersions = new ArrayList<DatastreamVersion>();
234        List<byte[]> cachedDsVersionBinaries = new ArrayList<byte[]>();
235
236        @Override
237        public void beginObject(final ObjectInfo object) {
238            this.objectInfo = object;
239        }
240
241        @Override
242        public void processObjectProperties(final ObjectProperties properties) {
243            this.properties = properties;
244        }
245
246        @Override
247        public void processDatastreamVersion(final DatastreamVersion dsVersion) {
248            dsVersions.add(dsVersion);
249            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
250            try (InputStream content = dsVersion.getContent()) {
251                IOUtils.copy(content, baos);
252                cachedDsVersionBinaries.add(baos.toByteArray());
253            } catch (final IOException e) {
254                throw new RuntimeException(e);
255            }
256
257
258        }
259
260        @Override
261        public void completeObject(final ObjectInfo object) {
262
263        }
264
265        @Override
266        public void abortObject(final ObjectInfo object) {
267
268        }
269    }
270
271    public static class DummyURLFetcher implements URLFetcher {
272
273        private URL lastUrl;
274
275        public URL getLastUrl() {
276            return lastUrl;
277        }
278
279        @Override
280        public InputStream getContentAtUrl(final URL url) throws IOException {
281            lastUrl = url;
282            return new ByteArrayInputStream("DummyURLFetcher".getBytes("UTF-8"));
283        }
284    }
285
286    public static class DummyIDResolver implements InternalIDResolver {
287        @Override
288        public CachedContent resolveInternalID(final String id) {
289            return null;
290        }
291
292        @Override
293        public void close() throws IOException { };
294    }
295
296}