de.mpg.escidoc.pubman.multipleimport.ImportProcess.java Source code

Java tutorial

Introduction

Here is the source code for de.mpg.escidoc.pubman.multipleimport.ImportProcess.java

Source

/*
 *
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License"). You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at license/ESCIDOC.LICENSE
 * or http://www.escidoc.org/license.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at license/ESCIDOC.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2006-2012 Fachinformationszentrum Karlsruhe Gesellschaft
 * fr wissenschaftlich-technische Information mbH and Max-Planck-
 * Gesellschaft zur Frderung der Wissenschaft e.V.
 * All rights reserved. Use is subject to license terms.
 */
package de.mpg.escidoc.pubman.multipleimport;

import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.naming.InitialContext;

import org.apache.axis.types.NonNegativeInteger;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.log4j.Logger;

import de.escidoc.www.services.om.ItemHandler;
import de.mpg.escidoc.pubman.multipleimport.ImportLog.ErrorLevel;
import de.mpg.escidoc.pubman.multipleimport.ImportLog.Status;
import de.mpg.escidoc.pubman.multipleimport.processor.ArxivProcessor;
import de.mpg.escidoc.pubman.multipleimport.processor.BibtexProcessor;
import de.mpg.escidoc.pubman.multipleimport.processor.BmcProcessor;
import de.mpg.escidoc.pubman.multipleimport.processor.EdocProcessor;
import de.mpg.escidoc.pubman.multipleimport.processor.EndnoteProcessor;
import de.mpg.escidoc.pubman.multipleimport.processor.EscidocProcessor;
import de.mpg.escidoc.pubman.multipleimport.processor.FormatProcessor;
import de.mpg.escidoc.pubman.multipleimport.processor.MabProcessor;
import de.mpg.escidoc.pubman.multipleimport.processor.Marc21Processor;
import de.mpg.escidoc.pubman.multipleimport.processor.MarcXmlProcessor;
import de.mpg.escidoc.pubman.multipleimport.processor.RisProcessor;
import de.mpg.escidoc.pubman.multipleimport.processor.WosProcessor;
import de.mpg.escidoc.pubman.multipleimport.processor.ZfNProcessor;
import de.mpg.escidoc.services.common.XmlTransforming;
import de.mpg.escidoc.services.common.referenceobjects.ContextRO;
import de.mpg.escidoc.services.common.util.ResourceUtil;
import de.mpg.escidoc.services.common.valueobjects.AccountUserVO;
import de.mpg.escidoc.services.common.valueobjects.FileVO;
import de.mpg.escidoc.services.common.valueobjects.ItemVO;
import de.mpg.escidoc.services.common.valueobjects.metadata.IdentifierVO;
import de.mpg.escidoc.services.common.valueobjects.publication.PubItemVO;
import de.mpg.escidoc.services.framework.PropertyReader;
import de.mpg.escidoc.services.framework.ProxyHelper;
import de.mpg.escidoc.services.framework.ServiceLocator;
import de.mpg.escidoc.services.pubman.PubItemDepositing;
import de.mpg.escidoc.services.search.Search;
import de.mpg.escidoc.services.search.query.ItemContainerSearchResult;
import de.mpg.escidoc.services.search.query.MetadataSearchCriterion;
import de.mpg.escidoc.services.search.query.MetadataSearchCriterion.CriterionType;
import de.mpg.escidoc.services.search.query.MetadataSearchCriterion.LogicalOperator;
import de.mpg.escidoc.services.search.query.MetadataSearchQuery;
import de.mpg.escidoc.services.transformation.Configurable;
import de.mpg.escidoc.services.transformation.Transformation;
import de.mpg.escidoc.services.transformation.TransformationBean;
import de.mpg.escidoc.services.transformation.valueObjects.Format;
import de.mpg.escidoc.services.validation.ItemValidating;
import de.mpg.escidoc.services.validation.valueobjects.ValidationReportItemVO;
import de.mpg.escidoc.services.validation.valueobjects.ValidationReportVO;

/**
 * TODO Description
 * 
 * @author franke (initial creation)
 * @author $Author$ (last modification)
 * @version $Revision$ $LastChangedDate$
 */
public class ImportProcess extends Thread {
    private static final Logger logger = Logger.getLogger(ImportProcess.class);

    public enum DuplicateStrategy {
        NO_CHECK, CHECK, ROLLBACK
    }

    private ImportLog log;
    private File file;
    private Transformation transformation;
    private ItemValidating itemValidating;
    private XmlTransforming xmlTransforming;
    private PubItemDepositing pubItemDepositing;
    private Search search;
    private Format format;
    private ContextRO escidocContext;
    private String publicationContentModel;
    private AccountUserVO user;
    private FormatProcessor formatProcessor;
    private String fileName;
    private boolean rollback;
    private DuplicateStrategy duplicateStrategy;
    private String itemContentModel;
    private Map<String, String> configuration = null;
    private boolean failed = false;
    private static final Format ESCIDOC_FORMAT = new Format("eSciDoc-publication-item", "application/xml", "utf-8");
    private static final Format ENDNOTE_FORMAT = new Format("endnote", "text/plain", "utf-8");
    private static final Format ENDNOTE_ICE_FORMAT = new Format("endnote-ice", "text/plain", "utf-8");
    private static final Format BIBTEX_FORMAT = new Format("bibtex", "text/plain", "utf-8");
    private static final Format ARXIV_FORMAT = new Format("arxiv", "application/xml", "utf-8");
    private static final Format EDOC_FORMAT = new Format("edoc", "application/xml", "utf-8");
    private static final Format EDOC_FORMAT_AEI = new Format("eDoc-AEI", "application/xml", "utf-8");
    private static final Format RIS_FORMAT = new Format("ris", "text/plain", "utf-8");
    private static final Format WOS_FORMAT = new Format("wos", "text/plain", "utf-8");
    private static final Format MAB_FORMAT = new Format("mab", "text/plain", "UTF-8");
    public static final Format ZFN_FORMAT = new Format("zfn_tei", "application/xml", "UTF-8");

    private static final Format MARC21_FORMAT = new Format("marc21viaxml", "application/marc", "UTF-8");
    private static final Format MARCXML_FORMAT = new Format("marcxml", "application/marcxml+xml", "UTF-8");
    private static final Format BMC_FORMAT = new Format("bmc_editura", "application/xml", "UTF-8");

    private String name;
    private long lastBeat = 0;

    public ImportProcess(String name, String fileName, File file, Format format, ContextRO escidocContext,
            AccountUserVO user, boolean rollback, int duplicateStrategy, Map<String, String> configuration) {
        try {
            this.publicationContentModel = PropertyReader
                    .getProperty("escidoc.framework_access.content-model.id.publication");
        } catch (Exception e) {
            throw new RuntimeException(
                    "Error getting property 'escidoc.framework_access.content-model.id.publication'", e);
        }

        log = new ImportLog("import", user.getReference().getObjectId(), format.getName());

        log.setUserHandle(user.getHandle());

        log.setPercentage(5);
        // Say Hello
        log.startItem("import_process_started");
        log.finishItem();
        DuplicateStrategy strategy;
        if (duplicateStrategy == 1) {
            strategy = DuplicateStrategy.NO_CHECK;
        } else if (duplicateStrategy == 2) {
            strategy = DuplicateStrategy.CHECK;
        } else if (duplicateStrategy == 3) {
            strategy = DuplicateStrategy.ROLLBACK;
        } else {
            throw new RuntimeException("Invalid value " + duplicateStrategy + " for DuplicateStrategy");
        }
        // Initialize
        initialize(name, fileName, file, format, escidocContext, user, rollback, strategy, configuration);
        log.setPercentage(7);
        if (log.isDone()) {
            return;
        }
        // Validate
        if (!validate(file, format)) {
            return;
        }
        log.setPercentage(10);
    }

    /**
     * @param inputStream
     * @param format
     */
    private void initialize(String name, String fileName, File file, Format format, ContextRO escidocContext,
            AccountUserVO user, boolean rollback, DuplicateStrategy duplicateStrategy,
            Map<String, String> configuration) {
        log.startItem("import_process_initialize");
        try {
            log.setMessage(name);
            log.setContext(escidocContext.getObjectId());
            log.setFormat(format.getName());
            this.name = name;
            this.fileName = fileName;
            this.format = format;
            this.escidocContext = escidocContext;
            this.user = user;
            this.transformation = new TransformationBean();
            this.file = file;
            this.rollback = rollback;
            this.duplicateStrategy = duplicateStrategy;
            InitialContext context = new InitialContext();
            this.itemValidating = (ItemValidating) context
                    .lookup("java:global/pubman_ear/validation/ItemValidatingBean");
            this.xmlTransforming = (XmlTransforming) context
                    .lookup("java:global/pubman_ear/common_logic/XmlTransformingBean");
            this.pubItemDepositing = (PubItemDepositing) context
                    .lookup("java:global/pubman_ear/pubman_logic/PubItemDepositingBean");
            this.search = (Search) context.lookup("java:global/pubman_ear/search/SearchBean");
            this.itemContentModel = PropertyReader
                    .getProperty("escidoc.framework_access.content-model.id.publication");
            this.configuration = configuration;
        } catch (Exception e) {
            log.addDetail(ErrorLevel.FATAL, "import_process_initialization_failed");
            log.addDetail(ErrorLevel.FATAL, e);
            fail();
        }
        log.finishItem();
    }

    /**
     * @param inputStream
     * @param format
     */
    private boolean validate(File file, Format format) {
        log.startItem("import_process_validate");
        if (file == null) {
            log.addDetail(ErrorLevel.FATAL, "import_process_inputstream_unavailable");
            fail();
            return false;
        } else {
            log.addDetail(ErrorLevel.FINE, "import_process_inputstream_available");
        }
        if (format == null) {
            log.addDetail(ErrorLevel.FATAL, "import_process_format_unavailable");
            fail();
            return false;
        } else {
            log.addDetail(ErrorLevel.FINE, "import_process_format_available");
        }
        Format[] allSourceFormats = transformation.getSourceFormats(ESCIDOC_FORMAT);

        boolean found = false;
        for (Format sourceFormat : allSourceFormats) {
            if (format.matches(sourceFormat)) {
                found = true;
                if (setProcessor(format)) {
                    log.addDetail(ErrorLevel.FINE, "import_process_format_valid");
                } else {
                    log.addDetail(ErrorLevel.FATAL, "import_process_format_not_supported");
                    fail();
                }
                break;
            }
        }
        if (!found) {
            log.addDetail(ErrorLevel.FATAL, "import_process_format_invalid");
            fail();
            return false;
        }
        log.finishItem();
        return true;
    }

    private boolean setProcessor(Format format) {
        try {
            if (format == null) {
                return false;
            } else if (ENDNOTE_FORMAT.matches(format) || ENDNOTE_ICE_FORMAT.matches(format)) {
                this.formatProcessor = new EndnoteProcessor();
            } else if (RIS_FORMAT.matches(format)) {
                this.formatProcessor = new RisProcessor();
            } else if (BIBTEX_FORMAT.matches(format)) {
                this.formatProcessor = new BibtexProcessor();
            } else if (ARXIV_FORMAT.matches(format)) {
                this.formatProcessor = new ArxivProcessor();
            } else if (WOS_FORMAT.matches(format)) {
                this.formatProcessor = new WosProcessor();
            } else if (ESCIDOC_FORMAT.matches(format)) {
                this.formatProcessor = new EscidocProcessor();
            } else if (EDOC_FORMAT.matches(format) || EDOC_FORMAT_AEI.matches(format)) {
                this.formatProcessor = new EdocProcessor();
            } else if (MAB_FORMAT.matches(format)) {
                this.formatProcessor = new MabProcessor();
            } else if (ZFN_FORMAT.matches(format)) {
                this.formatProcessor = new ZfNProcessor();
            } else if (BMC_FORMAT.matches(format)) {
                this.formatProcessor = new BmcProcessor();
            } else if (MARCXML_FORMAT.matches(format)) {
                this.formatProcessor = new MarcXmlProcessor();
            } else if (MARC21_FORMAT.matches(format)) {
                this.formatProcessor = new Marc21Processor();
            } else {
                return false;
            }
        } catch (Exception e) {
            log.addDetail(ErrorLevel.FATAL, "import_process_format_error");
            log.addDetail(ErrorLevel.FATAL, e);
            fail();
        }
        this.formatProcessor.setEncoding(format.getEncoding());
        return true;
    }

    private void fail() {
        this.failed = true;
        log.finishItem();
        log.startItem(ErrorLevel.FATAL, "import_process_failed");
        log.finishItem();
        if (this.rollback) {
            log.setStatus(Status.ROLLBACK);
            rollback();
        }
        log.close();
    }

    private void rollback() {
        log.startItem(ErrorLevel.FINE, "import_process_rollback");
        log.finishItem();
        log.close();
        DeleteProcess deleteProcess = new DeleteProcess(log);
        deleteProcess.start();
    }

    /**
     * {@inheritDoc}
     */
    public void run() {
        int counter = 0;
        int itemCount = 1;
        if (!failed) {
            try {
                log.startItem("import_process_start_import");
                this.formatProcessor.setSourceFile(file);
                if (this.formatProcessor.hasNext()) {
                    itemCount = this.formatProcessor.getLength();
                }
                log.finishItem();
                while (this.formatProcessor.hasNext() && !failed) {
                    try {
                        if (log.getCurrentItem() == null) {
                            log.startItem("import_process_import_item");
                        }
                        String singleItem = this.formatProcessor.next();
                        if (failed) {
                            return;
                        }
                        if (singleItem != null && !"".equals(singleItem.trim())) {
                            prepareItem(singleItem);
                        }
                        counter++;
                        log.setPercentage(30 * counter / itemCount + 10);
                    } catch (Exception e) {
                        logger.error("Error during import", e);
                        // log.finishItem();
                        // log.startItem(ErrorLevel.ERROR, "import_process_item_error");
                        log.addDetail(ErrorLevel.ERROR, e);
                        log.finishItem();
                        if (this.rollback) {
                            fail();
                            break;
                        }
                    }
                    heartBeat();
                }
            } catch (Exception e) {
                logger.error("Error during import", e);
                log.addDetail(ErrorLevel.ERROR, e);
                log.finishItem();
                if (this.rollback) {
                    fail();
                }
            }
            if (failed) {
                return;
            }
            log.finishItem();
            log.startItem("import_process_preparation_finished");
            log.addDetail(ErrorLevel.FINE, "import_process_no_more_items");
            log.finishItem();
            log.setPercentage(40);
            counter = 0;
            for (int i = 0; i < log.getItems().size(); i++) {
                ImportLogItem item = log.getItems().get(i);
                if (item.getStatus() == Status.SUSPENDED && item.getItemVO() != null && !failed) {
                    try {
                        log.activateItem(item);

                        //Fetch files for zfn import
                        if (this.format.getName().equalsIgnoreCase("zfn_tei")) {
                            try {
                                //Set file
                                FileVO file = ((ZfNProcessor) this.formatProcessor)
                                        .getFileforImport(this.configuration, this.user);
                                item.getItemVO().getFiles().add(file);
                            } catch (Exception e) {
                                log.addDetail(ErrorLevel.WARNING, "Could not fetch file for import");
                            }
                        }

                        log.addDetail(ErrorLevel.FINE, "import_process_save_item");

                        PubItemVO savedPubItem = pubItemDepositing.savePubItem(item.getItemVO(), user);
                        String objid = savedPubItem.getVersion().getObjectId();
                        log.setItemId(objid);
                        log.addDetail(ErrorLevel.FINE, "import_process_item_imported");
                        log.finishItem();
                        counter++;
                        log.setPercentage(55 * counter / itemCount + 40);
                    } catch (Exception e) {
                        logger.error("Error during import", e);
                        // log.finishItem();
                        // log.startItem(ErrorLevel.ERROR, "import_process_item_error");
                        log.addDetail(ErrorLevel.ERROR, e);
                        log.finishItem();
                        if (this.rollback) {
                            fail();
                            break;
                        }
                    }
                }
            }
            if (!failed) {
                log.startItem("import_process_finished");
                log.addDetail(ErrorLevel.FINE, "import_process_import_finished");
                log.finishItem();
                try {
                    log.startItem("import_process_archive_log");
                    log.addDetail(ErrorLevel.FINE, "import_process_build_task_item");
                    // Store log in repository
                    String taskItemXml = createTaskItemXml();

                    ItemHandler itemHandler = ServiceLocator.getItemHandler(this.user.getHandle());
                    String savedTaskItemXml = itemHandler.create(taskItemXml);

                    // log.addDetail(ErrorLevel.FINE, "import_process_retrieve_log_id");
                    Pattern pattern = Pattern.compile("objid=\"([^\"]+)\"");
                    Matcher matcher = pattern.matcher(savedTaskItemXml);
                    if (matcher.find()) {
                        String taskId = matcher.group(1);
                        // log.addDetail(ErrorLevel.FINE, taskId);
                        logger.info("Imported task item: " + taskId);
                    } else {
                        // log.addDetail(ErrorLevel.PROBLEM, "import_process_no_log_id");
                    }
                    log.setPercentage(100);
                } catch (Exception e) {
                    logger.error("Error during import", e);
                    log.finishItem();
                    log.startItem(ErrorLevel.ERROR, "import_process_error");
                    log.addDetail(ErrorLevel.ERROR, e);
                    fail();
                }
            }
        }

        //Close connection if no rollback is done. Otherwise, Connextion is still required for delete process
        if (!this.rollback) {
            log.closeConnection();
        }

        file.delete();
    }

    /**
     * Send a request to the framework every 30 minutes to make sure the user handle will not expire.
     */
    private void heartBeat() {
        long now = new Date().getTime();
        if ((now - lastBeat) > 1000 * 60 * 30) {
            logger.info("Refreshing " + log.getUserHandle());
            lastBeat = now;
            try {
                ServiceLocator.getContextHandler(log.getUserHandle()).retrieve(log.getContext());
            } catch (Exception e) {
                logger.warn("Heartbeat error", e);
            }
        }
    }

    private String createTaskItemXml() {
        try {

            String fwUrl = de.mpg.escidoc.services.framework.ServiceLocator.getFrameworkUrl();
            HttpClient client = new HttpClient();
            ProxyHelper.setProxy(client, fwUrl);

            StringBuilder sb = new StringBuilder(ResourceUtil.getResourceAsString(
                    "multipleImport/ImportTaskTemplate.xml", ImportProcess.class.getClassLoader()));
            replace("$01", escape(this.escidocContext.getObjectId()), sb);
            replace("$02", escape(PropertyReader.getProperty("escidoc.import.task.content-model")), sb);
            replace("$03", escape("Import Task Item for import " + name + " "), sb);

            //Upload original data
            PutMethod method = new PutMethod(fwUrl + "/st/staging-file");
            method.setRequestHeader("Content-Type", this.format.toString());
            method.setRequestHeader("Cookie", "escidocCookie=" + this.user.getHandle());
            InputStream is = new FileInputStream(this.formatProcessor.getSourceFile());
            method.setRequestEntity(new InputStreamRequestEntity(is));
            client.executeMethod(method);
            is.close();
            String response = method.getResponseBodyAsString();
            URL originalDataUrl = xmlTransforming.transformUploadResponseToFileURL(response);

            replace("$04", escape(this.name), sb);
            replace("$05", escape(this.fileName), sb);
            replace("$06", escape(originalDataUrl.toExternalForm()), sb);
            replace("$07", escape(log.getStoredId() + ""), sb);
            replace("$08", escape(this.format.toString()), sb);
            replace("$09", escape(String.valueOf(this.formatProcessor.getLength())), sb);

            //Upload and create task item xml
            File tempLogXml = File.createTempFile("multipleImportLogXml", "xml");
            Writer fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tempLogXml), "UTF-8"));
            log.toXML(fw);
            fw.flush();
            fw.close();

            PutMethod method2 = new PutMethod(fwUrl + "/st/staging-file");
            method2.setRequestHeader("Content-Type", "text/xml");
            method2.setRequestHeader("Cookie", "escidocCookie=" + this.user.getHandle());
            is = new FileInputStream(tempLogXml);
            method2.setRequestEntity(new InputStreamRequestEntity(is));
            client.executeMethod(method2);
            is.close();

            response = method2.getResponseBodyAsString();
            URL logXmlUrl = xmlTransforming.transformUploadResponseToFileURL(response);

            replace("$10", escape(this.name), sb);
            replace("$11", "importlog.xml", sb);
            replace("$12", escape(logXmlUrl.toExternalForm()), sb);
            replace("$13", escape(log.getStoredId() + ""), sb);
            replace("$14", escape(String.valueOf(tempLogXml.length())), sb);

            tempLogXml.delete();

            /*
             String taskItemXml = ResourceUtil.getResourceAsString("multipleImport/ImportTaskTemplate.xml");
             taskItemXml = taskItemXml.replace("$1", escape(this.escidocContext.getObjectId()));
             taskItemXml = taskItemXml.replace("$2",
                escape(PropertyReader.getProperty("escidoc.import.task.content-model")));
             taskItemXml = taskItemXml.replace("$4", escape(this.name));
             taskItemXml = taskItemXml.replace("$5", escape(this.fileName));
             taskItemXml = taskItemXml.replace("$6", escape(this.formatProcessor.getDataAsBase64()));
             taskItemXml = taskItemXml.replace("$7", escape(log.getStoredId() + ""));
             taskItemXml = taskItemXml.replace("$8", escape(this.format.toString()));
             taskItemXml = taskItemXml.replace("$9", escape(this.formatProcessor.getLength() + ""));
            */
            log.finishItem();

            log.close();

            return sb.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void replace(String target, String replacement, StringBuilder builder) {
        int indexOfTarget = -1;
        while ((indexOfTarget = builder.indexOf(target)) >= 0) {
            builder.replace(indexOfTarget, indexOfTarget + target.length(), replacement);
        }
    }

    private String escape(String string) {
        if (string == null) {
            return null;
        } else {
            return string.replace("&", "&amp;").replace("\"", "&quot;").replace("<", "&lt;").replace(">", "&gt;");
        }
    }

    /**
     * @param writer
     * @param singleItem
     * @return
     */
    private void prepareItem(String singleItem) {
        log.addDetail(ErrorLevel.FINE, "import_process_source_data_found");
        log.addDetail(ErrorLevel.FINE, singleItem);
        log.addDetail(ErrorLevel.FINE, "import_process_start_transformation");
        String esidocXml = null;
        try {
            if (configuration != null && transformation instanceof Configurable) {
                esidocXml = new String(
                        ((Configurable) transformation).transform(singleItem.getBytes(this.format.getEncoding()),
                                this.format, ESCIDOC_FORMAT, "escidoc", configuration),
                        ESCIDOC_FORMAT.getEncoding());
            } else {
                esidocXml = new String(transformation.transform(singleItem.getBytes(this.format.getEncoding()),
                        this.format, ESCIDOC_FORMAT, "escidoc"), ESCIDOC_FORMAT.getEncoding());
            }
            log.addDetail(ErrorLevel.FINE, esidocXml);
            log.addDetail(ErrorLevel.FINE, "import_process_transformation_done");
            PubItemVO pubItemVO = xmlTransforming.transformToPubItem(esidocXml);
            pubItemVO.setContext(escidocContext);
            pubItemVO.setContentModel(publicationContentModel);
            pubItemVO.getVersion().setObjectId(null);
            pubItemVO.getLocalTags().add("multiple_import");
            pubItemVO.getLocalTags().add(log.getMessage() + " " + log.getStartDateFormatted());

            // Default validation
            log.addDetail(ErrorLevel.FINE, "import_process_default_validation");
            ValidationReportVO validationReportVO = this.itemValidating.validateItemObject(pubItemVO);
            if (validationReportVO.isValid()) {
                if (!validationReportVO.hasItems()) {
                    log.addDetail(ErrorLevel.FINE, "import_process_default_validation_successful");
                } else {
                    log.addDetail(ErrorLevel.WARNING, "import_process_default_validation_successful_with_warnings");
                    for (ValidationReportItemVO item : validationReportVO.getItems()) {
                        log.addDetail(ErrorLevel.WARNING, item.getContent());
                    }
                }
                // Release validation
                log.addDetail(ErrorLevel.FINE, "import_process_release_validation");
                validationReportVO = this.itemValidating.validateItemObject(pubItemVO, "submit_item");
                if (validationReportVO.isValid()) {
                    if (!validationReportVO.hasItems()) {
                        log.addDetail(ErrorLevel.FINE, "import_process_release_validation_successful");
                    } else {
                        log.addDetail(ErrorLevel.WARNING,
                                "import_process_release_validation_successful_with_warnings");
                        for (ValidationReportItemVO item : validationReportVO.getItems()) {
                            log.addDetail(ErrorLevel.WARNING, item.getContent());
                        }
                    }
                } else {
                    log.addDetail(ErrorLevel.WARNING, "import_process_release_validation_failed");
                    for (ValidationReportItemVO item : validationReportVO.getItems()) {
                        if (item.isRestrictive()) {
                            log.addDetail(ErrorLevel.WARNING, item.getContent());
                        } else {
                            log.addDetail(ErrorLevel.WARNING, item.getContent());
                        }
                    }
                }
                log.addDetail(ErrorLevel.FINE, "import_process_generate_item");
                log.setItemVO(pubItemVO);
                if (this.duplicateStrategy != DuplicateStrategy.NO_CHECK) {
                    log.addDetail(ErrorLevel.FINE, "import_process_check_duplicates_by_identifier");
                    boolean duplicatesDetected = checkDuplicatesByIdentifier(pubItemVO);
                    if (duplicatesDetected && this.duplicateStrategy == DuplicateStrategy.ROLLBACK) {
                        this.rollback = true;
                        fail();
                    } else if (duplicatesDetected) {
                        log.addDetail(ErrorLevel.WARNING, "import_process_no_import");
                        log.finishItem();
                    } else {
                        log.suspendItem();
                    }
                } else {
                    log.suspendItem();
                }
            } else {
                log.addDetail(ErrorLevel.PROBLEM, "import_process_default_validation_failed");
                for (ValidationReportItemVO item : validationReportVO.getItems()) {
                    if (item.isRestrictive()) {
                        log.addDetail(ErrorLevel.PROBLEM, item.getContent());
                    } else {
                        log.addDetail(ErrorLevel.WARNING, item.getContent());
                    }
                }
                log.addDetail(ErrorLevel.PROBLEM, "import_process_item_not_imported");
                log.finishItem();
            }
        } catch (Exception e) {
            logger.error("Error while multiple import", e);
            log.addDetail(ErrorLevel.ERROR, e);
            log.addDetail(ErrorLevel.ERROR, "import_process_item_not_imported");
            if (this.rollback) {
                fail();
            }
            log.finishItem();
        }
    }

    private boolean checkDuplicatesByIdentifier(PubItemVO itemVO) {
        try {
            if (itemVO.getMetadata().getIdentifiers().size() > 0) {
                ArrayList<String> contentModels = new ArrayList<String>();
                contentModels.add(this.itemContentModel);
                ArrayList<MetadataSearchCriterion> criteria = new ArrayList<MetadataSearchCriterion>();
                boolean first = true;
                for (IdentifierVO identifierVO : itemVO.getMetadata().getIdentifiers()) {
                    MetadataSearchCriterion criterion = new MetadataSearchCriterion(CriterionType.IDENTIFIER,
                            identifierVO.getId(), (first ? LogicalOperator.AND : LogicalOperator.OR));
                    first = false;
                    criteria.add(criterion);
                }
                MetadataSearchQuery query = new MetadataSearchQuery(contentModels, criteria);
                ItemContainerSearchResult searchResult = search.searchForItemContainer(query);
                if (searchResult.getTotalNumberOfResults().equals(NonNegativeInteger.ZERO)) {
                    log.addDetail(ErrorLevel.FINE, "import_process_no_duplicate_detected");
                    return false;
                } else {
                    log.addDetail(ErrorLevel.FINE, "import_process_duplicates_detected");
                    for (ItemVO duplicate : searchResult.extractItemsOfSearchResult()) {
                        if (this.itemContentModel.equals(duplicate.getContentModel())) {
                            PubItemVO duplicatePubItemVO = new PubItemVO(duplicate);
                            if (this.duplicateStrategy == DuplicateStrategy.ROLLBACK) {
                                log.addDetail(ErrorLevel.PROBLEM, "import_process_duplicate_detected");
                                log.addDetail(ErrorLevel.PROBLEM,
                                        duplicatePubItemVO.getVersion().getObjectId() + " \""
                                                + duplicatePubItemVO.getMetadata().getTitle().getValue() + "\"",
                                        duplicatePubItemVO.getVersion().getObjectId());
                                return true;
                            } else {
                                log.addDetail(ErrorLevel.WARNING, "import_process_duplicate_detected");
                                log.addDetail(ErrorLevel.WARNING,
                                        duplicatePubItemVO.getVersion().getObjectId() + " \""
                                                + duplicatePubItemVO.getMetadata().getTitle().getValue() + "\"",
                                        duplicatePubItemVO.getVersion().getObjectId());
                            }
                        } else {
                            log.addDetail(ErrorLevel.WARNING, "import_process_detected_duplicate_no_publication");
                        }
                    }
                }
                return true;
            } else {
                log.addDetail(ErrorLevel.FINE, "import_process_no_identifier_for_duplicate_check");
                return false;
            }
        } catch (Exception e) {
            log.addDetail(ErrorLevel.WARNING, e);
            // An error while checking for duplicates should not cause the item not to be imported.
            //log.finishItem();
            return false;
        }
    }
}