/* * Copyright (C) 2012 Jan Pokorsky * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package cz.cas.lib.proarc.common.imports; import com.yourmediashelf.fedora.generated.foxml.ObjectFactory; import cz.cas.lib.proarc.common.CustomTemporaryFolder; import cz.cas.lib.proarc.common.config.AppConfiguration; import cz.cas.lib.proarc.common.config.AppConfigurationFactory; import cz.cas.lib.proarc.common.dao.Batch; import cz.cas.lib.proarc.common.dao.BatchItem; import cz.cas.lib.proarc.common.dao.BatchItem.ObjectState; import cz.cas.lib.proarc.common.dao.BatchItemDao; import cz.cas.lib.proarc.common.dao.DaoFactory; import cz.cas.lib.proarc.common.dao.Transaction; import cz.cas.lib.proarc.common.dublincore.DcStreamEditor; import cz.cas.lib.proarc.common.export.mets.JhoveContext; import cz.cas.lib.proarc.common.export.mets.JhoveUtility; import cz.cas.lib.proarc.common.fedora.BinaryEditor; import cz.cas.lib.proarc.common.fedora.MixEditor; import cz.cas.lib.proarc.common.fedora.StringEditor; import cz.cas.lib.proarc.common.fedora.relation.RelationEditor; import cz.cas.lib.proarc.common.imports.ImportBatchManager.BatchItemObject; import cz.cas.lib.proarc.common.imports.ImportProcess.ImportOptions; import cz.cas.lib.proarc.common.mods.ModsStreamEditor; import cz.cas.lib.proarc.common.object.DigitalObjectManager; import cz.cas.lib.proarc.common.object.K4Plugin; import cz.cas.lib.proarc.common.object.model.MetaModelRepository; import cz.cas.lib.proarc.common.object.ndk.NdkPlugin; import cz.cas.lib.proarc.common.ocr.AltoDatastream; import cz.cas.lib.proarc.common.user.UserManager; import cz.cas.lib.proarc.common.user.UserProfile; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import javax.xml.XMLConstants; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import org.apache.commons.io.FileUtils; import org.custommonkey.xmlunit.SimpleNamespaceContext; import org.custommonkey.xmlunit.XMLAssert; import org.custommonkey.xmlunit.XMLUnit; import org.easymock.EasyMock; import org.easymock.IAnswer; import org.junit.After; import org.junit.AfterClass; import static org.junit.Assert.*; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.xml.sax.InputSource; /** * * @author Jan Pokorsky */ public class TiffImporterTest { @Rule public CustomTemporaryFolder temp = new CustomTemporaryFolder(); private File tiff1; private File ocr1; private File alto1; private File ac1; private File uc1; private AppConfiguration config; private ArrayList<Object> toVerify = new ArrayList<Object>();; private JhoveContext jhoveContext; private UserProfile junit; private ImportBatchManager ibm; public TiffImporterTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() throws Exception { junit = new UserProfile(); junit.setUserName("junit"); File root = temp.getRoot(); System.out.println("root: " + root.toString()); tiff1 = new File(root, "img1.tiff"); URL resource = TiffImporterTest.class.getResource("testscan-lzw.tiff"); FileUtils.copyURLToFile(resource, tiff1); assertTrue(tiff1.length() > 0); ocr1 = new File(root, "img1.ocr.txt"); FileUtils.writeStringToFile(ocr1, "test", "UTF-8"); alto1 = new File(root, "img1.ocr.xml"); FileUtils.writeStringToFile(alto1, "<alto xmlns=\"http://www.loc.gov/standards/alto/ns-v2#\">" + "<Layout><Page ID=\"Page1\" PHYSICAL_IMG_NR=\"1\"/></Layout>" + "</alto>", "UTF-8"); ac1 = new File(root, "img1.ac.jp2"); resource = TiffImporterTest.class.getResource("testscan.uc.jp2"); FileUtils.copyURLToFile(resource, ac1); assertTrue(ac1.length() > 0); uc1 = new File(root, "img1.uc.jp2"); FileUtils.copyURLToFile(resource, uc1); assertTrue(uc1.length() > 0); config = AppConfigurationFactory.getInstance().create(new HashMap<String, String>() {{ put(AppConfiguration.PROPERTY_APP_HOME, temp.getRoot().getPath()); }}); jhoveContext = JhoveUtility.createContext(temp.newFolder("jhove")); DaoFactory daos = createMockDaoFactory(); ibm = new ImportBatchManager(config, daos); // MetaModelRepository.setInstance(new String[]{K4Plugin.ID}); MetaModelRepository.setInstance(new String[]{NdkPlugin.ID}); DigitalObjectManager.setDefault(new DigitalObjectManager(config, ibm, null, MetaModelRepository.getInstance(), EasyMock.createNiceMock(UserManager.class)) ); } @After public void tearDown() { if (jhoveContext != null) { jhoveContext.destroy(); } } @Test public void testConsume() throws Exception { temp.setDeleteOnExit(true); File targetFolder = ImportProcess.createTargetFolder(temp.getRoot()); assertTrue(targetFolder.exists()); String mimetype = ImportProcess.findMimeType(tiff1); assertNotNull(mimetype); ImportOptions ctx = new ImportOptions(tiff1.getParentFile(), "scanner:scanner1", true, junit, config.getImportConfiguration()); ctx.setTargetFolder(targetFolder); Batch batch = new Batch(); batch.setId(1); batch.setFolder(ibm.relativizeBatchFile(tiff1.getParentFile())); ctx.setBatch(batch); FileSet fileSet = ImportFileScanner.getFileSets(Arrays.asList(tiff1, ocr1, alto1, ac1, uc1)).get(0); ctx.setJhoveContext(jhoveContext); TiffImporter instance = new TiffImporter(ibm); BatchItemObject result = instance.consume(fileSet, ctx); String pid = result.getPid(); assertTrue(pid.startsWith("uuid")); assertEquals(ObjectState.LOADED, result.getState()); File foxml = result.getFile(); assertTrue(foxml.toString(), foxml.exists()); File rootFoxml = new File(foxml.getParent(), ImportBatchManager.ROOT_ITEM_FILENAME); assertTrue(rootFoxml.toString(), rootFoxml.exists()); File raw1 = new File(targetFolder, "img1.full.jpg"); assertTrue(raw1.exists() && raw1.length() > 0); File preview1 = new File(targetFolder, "img1.preview.jpg"); assertTrue(preview1.exists() && preview1.length() > 0); File thumb1 = new File(targetFolder, "img1.thumb.jpg"); assertTrue(thumb1.exists() && thumb1.length() > 0); // validate FOXML SchemaFactory sfactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); URL foxmlXsdUrl = ObjectFactory.class.getResource("/xsd/foxml/foxml1-1.xsd"); assertNotNull(foxmlXsdUrl); Schema foxmlXsd = sfactory.newSchema(foxmlXsdUrl); foxmlXsd.newValidator().validate(new StreamSource(foxml)); // check datastreams with xpath HashMap<String, String> namespaces = new HashMap<String, String>(); namespaces.put("f", "info:fedora/fedora-system:def/foxml#"); XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(namespaces)); String foxmlSystemId = foxml.toURI().toASCIIString(); XMLAssert.assertXpathExists(streamXPath(ModsStreamEditor.DATASTREAM_ID), new InputSource(foxmlSystemId)); XMLAssert.assertXpathExists(streamXPath(DcStreamEditor.DATASTREAM_ID), new InputSource(foxmlSystemId)); XMLAssert.assertXpathExists(streamXPath(StringEditor.OCR_ID), new InputSource(foxmlSystemId)); XMLAssert.assertXpathExists(streamXPath(AltoDatastream.ALTO_ID), new InputSource(foxmlSystemId)); XMLAssert.assertXpathExists(streamXPath(RelationEditor.DATASTREAM_ID), new InputSource(foxmlSystemId)); XMLAssert.assertXpathExists(streamXPath(BinaryEditor.FULL_ID), new InputSource(foxmlSystemId)); XMLAssert.assertXpathExists(streamXPath(BinaryEditor.PREVIEW_ID), new InputSource(foxmlSystemId)); XMLAssert.assertXpathExists(streamXPath(BinaryEditor.THUMB_ID), new InputSource(foxmlSystemId)); XMLAssert.assertXpathExists(streamXPath(BinaryEditor.RAW_ID), new InputSource(foxmlSystemId)); XMLAssert.assertXpathExists(streamXPath(MixEditor.RAW_ID), new InputSource(foxmlSystemId)); XMLAssert.assertXpathExists(streamXPath(BinaryEditor.NDK_ARCHIVAL_ID), new InputSource(foxmlSystemId)); XMLAssert.assertXpathExists(streamXPath(BinaryEditor.NDK_USER_ID), new InputSource(foxmlSystemId)); XMLAssert.assertXpathExists(streamXPath(MixEditor.NDK_ARCHIVAL_ID), new InputSource(foxmlSystemId)); String rootSystemId = rootFoxml.toURI().toASCIIString(); XMLAssert.assertXpathExists(streamXPath(RelationEditor.DATASTREAM_ID), new InputSource(rootSystemId)); EasyMock.verify(toVerify.toArray()); } @Test public void testMissingRequiredContent() throws Exception { assertTrue(alto1.delete()); assertTrue(config.getImportConfiguration().getRequiredDatastreamId().contains(AltoDatastream.ALTO_ID)); File targetFolder = ImportProcess.createTargetFolder(temp.getRoot()); assertTrue(targetFolder.exists()); String mimetype = ImportProcess.findMimeType(tiff1); assertNotNull(mimetype); ImportOptions ctx = new ImportOptions(tiff1.getParentFile(), "scanner:scanner1", true, junit, config.getImportConfiguration()); ctx.setTargetFolder(targetFolder); Batch batch = new Batch(); batch.setId(1); batch.setFolder(ibm.relativizeBatchFile(tiff1.getParentFile())); ctx.setBatch(batch); FileSet fileSet = ImportFileScanner.getFileSets(Arrays.asList(tiff1, ocr1, ac1, uc1)).get(0); ctx.setJhoveContext(jhoveContext); TiffImporter instance = new TiffImporter(ibm); BatchItemObject result = instance.consume(fileSet, ctx); assertEquals(ObjectState.LOADING_FAILED, result.getState()); String log = result.getLog(); assertNotNull(log); assertTrue(log, log.contains("Missing ALTO")); } private static String streamXPath(String dsId) { return "f:digitalObject/f:datastream[@ID='" + dsId + "']"; } private DaoFactory createMockDaoFactory() { DaoFactory daos = EasyMock.createMock(DaoFactory.class); EasyMock.expect(daos.createTransaction()).andAnswer(new IAnswer<Transaction>() { @Override public Transaction answer() throws Throwable { return createMockTransaction(); } }).anyTimes(); EasyMock.expect(daos.createBatchItem()).andAnswer(new IAnswer<BatchItemDao>() { @Override public BatchItemDao answer() throws Throwable { return createMockBatchItemDao(); } }).anyTimes(); EasyMock.replay(daos); toVerify.add(daos); return daos; } private Transaction createMockTransaction() { Transaction tx = EasyMock.createMock(Transaction.class); tx.commit(); EasyMock.expectLastCall().atLeastOnce(); tx.rollback(); EasyMock.expectLastCall().anyTimes(); tx.close(); EasyMock.replay(tx); toVerify.add(tx); return tx; } private BatchItemDao createMockBatchItemDao() { BatchItemDao dao = EasyMock.createMock(BatchItemDao.class); dao.update(EasyMock.<BatchItem>anyObject()); EasyMock.expectLastCall().anyTimes(); EasyMock.expect(dao.create()).andReturn(new BatchItem()).anyTimes(); dao.setTransaction(EasyMock.<Transaction>anyObject()); EasyMock.replay(dao); toVerify.add(dao); return dao; } }