com.ephesoft.dcma.webservice.util.WebServiceHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.ephesoft.dcma.webservice.util.WebServiceHelper.java

Source

/********************************************************************************* 
* Ephesoft is a Intelligent Document Capture and Mailroom Automation program 
* developed by Ephesoft, Inc. Copyright (C) 2015 Ephesoft Inc. 
* 
* This program is free software; you can redistribute it and/or modify it under 
* the terms of the GNU Affero General Public License version 3 as published by the 
* Free Software Foundation with the addition of the following permission added 
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK 
* IN WHICH THE COPYRIGHT IS OWNED BY EPHESOFT, EPHESOFT DISCLAIMS THE WARRANTY 
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. 
* 
* 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 Affero General Public License for more 
* details. 
* 
* You should have received a copy of the GNU Affero General Public License along with 
* this program; if not, see http://www.gnu.org/licenses or write to the Free 
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
* 02110-1301 USA. 
* 
* You can contact Ephesoft, Inc. headquarters at 111 Academy Way, 
* Irvine, CA 92617, USA. or at email address info@ephesoft.com. 
* 
* The interactive user interfaces in modified source and object code versions 
* of this program must display Appropriate Legal Notices, as required under 
* Section 5 of the GNU Affero General Public License version 3. 
* 
* In accordance with Section 7(b) of the GNU Affero General Public License version 3, 
* these Appropriate Legal Notices must retain the display of the "Ephesoft" logo. 
* If the display of the logo is not reasonably feasible for 
* technical reasons, the Appropriate Legal Notices must display the words 
* "Powered by Ephesoft". 
********************************************************************************/

package com.ephesoft.dcma.webservice.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.jdom.JDOMException;
import org.jdom.output.DOMOutputter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.oxm.XmlMappingException;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;
import org.w3c.dom.Document;

import com.ephesoft.dcma.batch.constant.BatchConstants;
import com.ephesoft.dcma.batch.dao.impl.BatchPluginPropertyContainer.BatchPlugin;
import com.ephesoft.dcma.batch.dao.impl.BatchPluginPropertyContainer.BatchPluginConfiguration;
import com.ephesoft.dcma.batch.dao.xml.BatchSchemaDao;
import com.ephesoft.dcma.batch.encryption.service.EncryptionKeyService;
import com.ephesoft.dcma.batch.encryption.util.CryptoMarshaller;
import com.ephesoft.dcma.batch.encryption.util.DOMEncryptionUtil;
import com.ephesoft.dcma.batch.schema.Batch;
import com.ephesoft.dcma.batch.schema.BatchClasses;
import com.ephesoft.dcma.batch.schema.BatchInstances;
import com.ephesoft.dcma.batch.schema.Coordinates;
import com.ephesoft.dcma.batch.schema.CopyDocumentType;
import com.ephesoft.dcma.batch.schema.DocField;
import com.ephesoft.dcma.batch.schema.DocField.AlternateValues;
import com.ephesoft.dcma.batch.schema.ExtractKV;
import com.ephesoft.dcma.batch.schema.ExtractKVParams;
import com.ephesoft.dcma.batch.schema.ExtractKVParams.Params;
import com.ephesoft.dcma.batch.schema.ExtractTableParam;
import com.ephesoft.dcma.batch.schema.Field;
import com.ephesoft.dcma.batch.schema.HOCRFile;
import com.ephesoft.dcma.batch.schema.HocrPages;
import com.ephesoft.dcma.batch.schema.ImportBatchClassOptions;
import com.ephesoft.dcma.batch.schema.KVExtractionDocType;
import com.ephesoft.dcma.batch.schema.ListValues;
import com.ephesoft.dcma.batch.schema.Modules;
import com.ephesoft.dcma.batch.schema.Modules.Module;
import com.ephesoft.dcma.batch.schema.UploadLearningFiles;
import com.ephesoft.dcma.batch.schema.UploadLearningFiles.DocType;
import com.ephesoft.dcma.batch.schema.UploadLearningFiles.DocType.PageTypeFirst;
import com.ephesoft.dcma.batch.schema.UploadLearningFiles.DocType.PageTypeFirst.FilesToBeUploaded;
import com.ephesoft.dcma.batch.schema.UploadLearningFiles.DocType.PageTypeLast;
import com.ephesoft.dcma.batch.schema.UploadLearningFiles.DocType.PageTypeMiddle;
import com.ephesoft.dcma.batch.schema.WebServiceParams;
import com.ephesoft.dcma.batch.schema.WebServiceParams.Params.Param;
import com.ephesoft.dcma.batch.service.BatchSchemaService;
import com.ephesoft.dcma.batch.service.ImportBatchService;
import com.ephesoft.dcma.batch.service.PluginPropertiesService;
import com.ephesoft.dcma.batch.util.BatchEncryptionUtil;
import com.ephesoft.dcma.common.ImportBatchClassResultCarrier;
import com.ephesoft.dcma.core.DCMAException;
import com.ephesoft.dcma.core.common.BatchInstanceStatus;
import com.ephesoft.dcma.core.common.CategoryType;
import com.ephesoft.dcma.core.common.DCMABusinessException;
import com.ephesoft.dcma.core.common.FileType;
import com.ephesoft.dcma.core.common.PluginProperty;
import com.ephesoft.dcma.core.component.ICommonConstants;
import com.ephesoft.dcma.core.exception.DCMAApplicationException;
import com.ephesoft.dcma.core.threadpool.BatchInstanceThread;
import com.ephesoft.dcma.core.threadpool.ThreadPool;
import com.ephesoft.dcma.da.domain.AdvancedKVExtraction;
import com.ephesoft.dcma.da.domain.BatchClass;
import com.ephesoft.dcma.da.domain.BatchClassGroups;
import com.ephesoft.dcma.da.domain.BatchClassModule;
import com.ephesoft.dcma.da.domain.BatchClassPlugin;
import com.ephesoft.dcma.da.domain.BatchInstance;
import com.ephesoft.dcma.da.domain.DocumentType;
import com.ephesoft.dcma.da.domain.PageType;
import com.ephesoft.dcma.da.id.BatchClassID;
import com.ephesoft.dcma.da.service.BatchClassGroupsService;
import com.ephesoft.dcma.da.service.BatchClassModuleService;
import com.ephesoft.dcma.da.service.BatchClassPluginConfigService;
import com.ephesoft.dcma.da.service.BatchClassService;
import com.ephesoft.dcma.da.service.BatchInstanceGroupsService;
import com.ephesoft.dcma.da.service.BatchInstanceService;
import com.ephesoft.dcma.da.service.DocumentTypeService;
import com.ephesoft.dcma.imagemagick.ImageMagicProperties;
import com.ephesoft.dcma.imagemagick.imageClassifier.SampleThumbnailGenerator;
import com.ephesoft.dcma.imagemagick.service.ImageProcessService;
import com.ephesoft.dcma.kvextraction.service.KVExtractionService;
import com.ephesoft.dcma.lucene.service.SearchClassificationService;
import com.ephesoft.dcma.tableextraction.TableExtraction;
import com.ephesoft.dcma.tableextraction.TableExtractionProperties;
import com.ephesoft.dcma.tablefinder.service.TableFinderService;
import com.ephesoft.dcma.tesseract.TesseractProperties;
import com.ephesoft.dcma.tesseract.service.TesseractService;
import com.ephesoft.dcma.user.service.UserConnectivityService;
import com.ephesoft.dcma.util.ApplicationConfigProperties;
import com.ephesoft.dcma.util.CollectionUtil;
import com.ephesoft.dcma.util.CustomFileFilter;
import com.ephesoft.dcma.util.EphesoftStringUtil;
import com.ephesoft.dcma.util.FileUtils;
import com.ephesoft.dcma.util.IUtilCommonConstants;
import com.ephesoft.dcma.util.OSUtil;
import com.ephesoft.dcma.util.TIFFUtil;
import com.ephesoft.dcma.util.WebServiceUtil;
import com.ephesoft.dcma.util.XMLUtil;
import com.ephesoft.dcma.util.constant.PrivateKeyEncryptionAlgorithm;
import com.ephesoft.dcma.util.exception.HexDecoderException;
import com.ephesoft.dcma.util.exception.KeyGenerationException;
import com.ephesoft.dcma.util.exception.KeyNotFoundException;
import com.ephesoft.dcma.webservice.constants.WebServiceConstants;
import com.ephesoft.dcma.webservice.customexceptions.BatchNameAlreadyExistException;
import com.ephesoft.dcma.webservice.customexceptions.ConfigurationException;
import com.ephesoft.dcma.webservice.customexceptions.InternalServerException;
import com.ephesoft.dcma.webservice.customexceptions.NoUserRoleException;
import com.ephesoft.dcma.webservice.customexceptions.UnAuthorisedAccessException;
import com.ephesoft.dcma.webservice.customexceptions.UnSupportedFileTypeException;
import com.ephesoft.dcma.webservice.customexceptions.ValidationException;
import com.ephesoft.dcma.webservice.exceptionhandler.RestError;
import com.ephesoft.dcma.webservice.responseXML.ErrorElement;
import com.ephesoft.dcma.webservice.responseXML.ResponseCodeElement;
import com.ephesoft.dcma.webservice.responseXML.RootElement;
import com.ephesoft.dcma.workflows.constant.WorkflowConstants;
import com.ephesoft.dcma.workflows.service.DeploymentService;
import com.ephesoft.dcma.workflows.service.WorkflowService;
import com.ephesoft.dcma.workflows.service.engine.EngineService;

/**
 * Web service Helper class is used for providing all the functionality required for processing of web service.
 * 
 * @author Ephesoft
 * @version 3.0
 * @see EphesoftWebServiceAPI
 * 
 */
public class WebServiceHelper {

    /**
     * {@link RootElement} for xml format of the element.
     */
    private RootElement rootElement;

    /**
     * {@link ErrorElement} for xml formatting of the xml element.
     */
    private ErrorElement errorElement;

    /**
     * {@link ResponseCodeElement} for response code inclusion in root element.
     */
    private ResponseCodeElement responseCodeElement;

    /**
     * Initializing batchSchemaService {@link BatchSchemaService}.
     */
    @Autowired
    private BatchSchemaService batchSchemaService;

    /** {@link WorkflowService} The workflow service. */
    @Autowired
    private WorkflowService workflowService;

    /**
     * Initializing searchClassificationService {@link SearchClassificationService}.
     */
    @Autowired
    private SearchClassificationService searchClassificationService;

    /**
     * Initializing batchClassService {@link BatchClassService}.
     */
    @Autowired
    private BatchClassService batchClassService;

    /**
     * Initializing documentTypeService {@link DocumentTypeService}.
     */
    @Autowired
    private DocumentTypeService docTypeService;

    /** The user connectivity service. */
    @Autowired
    private UserConnectivityService userConnectivityService;

    @Autowired
    private ImageProcessService imService;

    @Autowired
    private TesseractService tesseractService;

    @Autowired
    private EncryptionKeyService encryptionService;

    /** The batch class groups service. */
    @Autowired
    private BatchClassGroupsService batchClassGroupsService;

    /** The batch instance service. */
    @Autowired
    private BatchInstanceService batchInstanceService;

    /** The batch instance group service. */
    @Autowired
    private BatchInstanceGroupsService batchInstanceGroupsService;

    /** The batch class module service. */
    @Autowired
    private BatchClassModuleService batchClassModuleService;

    /** The plugin properties service. */
    @Autowired
    @Qualifier("batchInstancePluginPropertiesService")
    private PluginPropertiesService pluginPropertiesService;

    /** The bs service. */
    @Autowired
    private BatchSchemaService bsService;

    @Autowired
    private TableFinderService tableFinderService;

    @Autowired
    @Qualifier("batchClassPluginPropertiesService")
    private PluginPropertiesService batchClassPPService;

    @Autowired
    private TableExtraction tableExtraction;

    /** The bc service. */
    @Autowired
    private BatchClassService bcService;

    // TODO
    @Autowired
    @Qualifier("batchClassPluginPropertiesService")
    private PluginPropertiesService classPluginPropertiesService;

    @Autowired
    private EngineService engineService;

    /** The import batch service. */
    @Autowired
    private ImportBatchService importBatchService;

    @Autowired
    private DeploymentService deploymentService;

    /**
     * The kv service.
     */
    @Autowired
    private KVExtractionService kvService;

    /**
     * Initializing batchSchemaDao {@link BatchSchemaDao}.
     */
    @Autowired
    private BatchSchemaDao batchSchemaDao;

    /**
     * Initializing batchClassPluginConfigService {@link BatchClassPluginConfigService}.
     */
    @Autowired
    private BatchClassPluginConfigService batchClassPluginConfigService;

    @Autowired
    private EncryptionKeyService encryptionKeyService;

    /**
     * Initializing logger {@link Logger}.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(WebServiceHelper.class);

    /**
     * The constant value for minimum confidence threshold value.
     */
    private static final float MIN_CONFIDENCE_THRESHOLD_VALUE = 0;

    /**
     * The constant value for maximum confidence threshold value.
     */
    private static final float MAX_CONFIDENCE_THRESHOLD_VALUE = 100;

    /**
     * Constant for string "true".
     */
    private static final String TRUE = "true";

    /**
     * Constant for string "false".
     */
    private static final String FALSE = "false";

    /**
     * Constant for the type of processing file used for document type creation: "FPR.rsp".
     */
    private static final String DEFAULT_RSP_FILE_NAME = "FPR.rsp";

    /**
     * Constant for the type of processing file used for document type creation: "FPR_Barcode.rsp".
     */
    private static final String DEFAULT_RSP_BARCODE_FILE_NAME = "FPR_Barcode.rsp";

    /**
     * Constant for the maximum limit of value input for name.
     */
    private static final int MAX_CHARACTER_LIMIT = 255;
    /**
     * Constant for minimum limit of priority.
     */
    private static final int MIN_PRIORITY_VALUE = 1;
    /**
     * Constant for maximum limit of priority.
     */
    private static final int MAX_PRIORITY_VALUE = 100;
    /**
     * Constant Defined for Lucene Search Classification type
     */
    private static final String LUCENE_SEARCH_CLASSIFICATION_TYPE = "Lucene";
    /**
     * Constant defined Image-Classification-sample type
     */
    private static final String IMAGE_CLASSIFICATION_SAMPLE_TYPE = "Image";

    @Autowired
    private CryptoMarshaller cryptoMarshaller;

    /**
     * Learning for batch class is performed in this api.
     * 
     * @param batchClassID The batch class identifier for which learning has to be done.
     * @throws InternalServerException the internal server exception
     */
    public void learnFileForBatchClass(final String batchClassID) throws InternalServerException {
        final File batchClassFolder = new File(
                batchSchemaService.getBaseFolderLocation() + File.separator + batchClassID);
        if (!batchClassFolder.exists()) {
            return;
        }
        final BatchClass batchClass = batchClassService.getBatchClassByIdentifier(batchClassID);
        final String ocrPluginName = getOCRPluginNameForBatchClass(batchClassID);
        if (null != ocrPluginName) {
            try {
                if (ocrPluginName.equalsIgnoreCase(WebServiceConstants.TESSERACT_HOCR_PLUGIN)) {
                    searchClassificationService.learnSampleHOCRForTesseract(batchClass.getBatchClassID(), true);
                }
            } catch (final DCMAException exception) {
                LOGGER.error(exception.getMessage());
                final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                final RestError restError = new RestError(status,
                        WebServiceConstants.ERROR_RETRIEVING_FOLDER_PATH_CODE,
                        WebServiceConstants.ERROR_RETRIEVING_FOLDER_PATH_MESSAGE,
                        WebServiceConstants.ERROR_RETRIEVING_FOLDER_PATH_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                throw new InternalServerException(WebServiceConstants.ERROR_RETRIEVING_FOLDER_PATH_MESSAGE,
                        restError);
            }
        }
        sampleThumbnailGenerator(batchClassID);
    }

    /**
     * The OCR engine to be used for learning in this batch class is given by this api.
     * 
     * @param batchClassIdentifier {@link String} the identifier for batch class for which learning has to be done.
     * @return {@link String} the ocr engine name.
     */
    private String getOCRPluginNameForBatchClass(final String batchClassIdentifier) {
        LOGGER.info("Fetching the ocr engine to be used for learning.");
        final String defaultOcrEngineName = getDefaultHOCRPlugin(batchClassIdentifier);
        String ocrEngineName = defaultOcrEngineName;
        PluginProperty ocrEngineSwitch = null;
        String ocrEngineSwitchValue = null;

        ocrEngineSwitch = TesseractProperties.TESSERACT_SWITCH;
        ocrEngineSwitchValue = getOcrEngineSwitchValue(batchClassIdentifier, batchClassPPService, ocrEngineName,
                ocrEngineSwitch);

        if (!WebServiceConstants.SWITCH_ON.equalsIgnoreCase(ocrEngineSwitchValue)) {
            ocrEngineSwitch = TesseractProperties.TESSERACT_SWITCH;
            ocrEngineName = WebServiceConstants.TESSERACT_HOCR_PLUGIN;
            ocrEngineSwitchValue = getOcrEngineSwitchValue(batchClassIdentifier, pluginPropertiesService,
                    ocrEngineName, ocrEngineSwitch);
            if (!WebServiceConstants.SWITCH_ON.equalsIgnoreCase(ocrEngineSwitchValue)) {
                ocrEngineName = defaultOcrEngineName;
            }
        }
        LOGGER.info("OCR Engine used for learning = " + ocrEngineName);
        return ocrEngineName;
    }

    /**
     * To generate the thumb-nails for the images being learned.
     * 
     * @param batchClassIdentifier the batch class identifier for which learning has to be done
     * @throws InternalServerException the internal server exception
     */
    private void sampleThumbnailGenerator(final String batchClassIdentifier) throws InternalServerException {
        final HttpStatus status;
        final RestError restError;
        String sampleBaseFolderPath = null;
        String thumbnailType = null;
        String thumbnailH = null;
        String thumbnailW = null;
        final Map<String, String> properties = batchClassPluginConfigService.getPluginPropertiesForBatchClass(
                batchClassIdentifier, WebServiceConstants.CREATE_THUMBNAILS_PLUGIN, null);
        if (properties != null && !properties.isEmpty()) {
            sampleBaseFolderPath = batchSchemaService.getImageMagickBaseFolderPath(batchClassIdentifier, false);
            if (!(sampleBaseFolderPath != null && sampleBaseFolderPath.length() > 0)) {
                LOGGER.error(WebServiceConstants.ERROR_RETRIEVING_FOLDER_PATH_MESSAGE);
                status = HttpStatus.INTERNAL_SERVER_ERROR;
                restError = new RestError(status, WebServiceConstants.ERROR_RETRIEVING_FOLDER_PATH_CODE,
                        WebServiceConstants.ERROR_RETRIEVING_FOLDER_PATH_MESSAGE,
                        WebServiceConstants.ERROR_RETRIEVING_FOLDER_PATH_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                throw new InternalServerException(WebServiceConstants.ERROR_RETRIEVING_FOLDER_PATH_MESSAGE,
                        restError);
            }
            thumbnailH = properties.get(ImageMagicProperties.CREATE_THUMBNAILS_COMP_THUMB_HEIGHT.getPropertyKey());
            if (!(thumbnailH != null && thumbnailH.length() > 0)) {
                LOGGER.error(WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_DIMENSION_MESSAGE);
                status = HttpStatus.INTERNAL_SERVER_ERROR;
                restError = new RestError(status, WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_DIMENSION_CODE,
                        WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_DIMENSION_MESSAGE,
                        WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_DIMENSION_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                throw new InternalServerException(WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_DIMENSION_MESSAGE,
                        restError);
            }
            thumbnailType = properties.get(ImageMagicProperties.CREATE_THUMBNAILS_COMP_THUMB_TYPE.getPropertyKey());
            if (!(thumbnailType != null && thumbnailType.length() > 0)) {
                LOGGER.error(WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_TYPE_MESSAGE);
                status = HttpStatus.INTERNAL_SERVER_ERROR;
                restError = new RestError(status, WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_TYPE_CODE,
                        WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_TYPE_MESSAGE,
                        WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_TYPE_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                throw new InternalServerException(WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_TYPE_MESSAGE,
                        restError);
            }
            thumbnailW = properties.get(ImageMagicProperties.CREATE_THUMBNAILS_COMP_THUMB_WIDTH.getPropertyKey());
            if (!(thumbnailW != null && thumbnailW.length() > 0)) {
                LOGGER.error(WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_DIMENSION_MESSAGE);
                status = HttpStatus.INTERNAL_SERVER_ERROR;
                restError = new RestError(status, WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_DIMENSION_CODE,
                        WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_DIMENSION_MESSAGE,
                        WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_DIMENSION_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                throw new InternalServerException(WebServiceConstants.ERROR_RETRIEVING_THUMBNAIL_DIMENSION_MESSAGE,
                        restError);
            }
        } else {
            LOGGER.error(WebServiceConstants.NO_IMAGE_MAGIC_PROPERTIES_FOUND_MESSAGE);
            status = HttpStatus.INTERNAL_SERVER_ERROR;
            restError = new RestError(status, WebServiceConstants.NO_IMAGE_MAGIC_PROPERTIES_FOUND_CODE,
                    WebServiceConstants.NO_IMAGE_MAGIC_PROPERTIES_FOUND_MESSAGE,
                    WebServiceConstants.NO_IMAGE_MAGIC_PROPERTIES_FOUND_MESSAGE
                            + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                    WebServiceConstants.DEFAULT_URL);
            throw new InternalServerException(WebServiceConstants.NO_IMAGE_MAGIC_PROPERTIES_FOUND_MESSAGE,
                    restError);
        }
        final SampleThumbnailGenerator sampleThumbnailGenerator = new SampleThumbnailGenerator(sampleBaseFolderPath,
                thumbnailType, thumbnailH, thumbnailW);
        try {
            sampleThumbnailGenerator.generateAllThumbnails(batchClassIdentifier);
        } catch (final DCMAApplicationException e) {
            LOGGER.error(e.getMessage());
            status = HttpStatus.INTERNAL_SERVER_ERROR;
            restError = new RestError(status, WebServiceConstants.INTERNAL_SERVER_ERROR_CODE,
                    WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE,
                    WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE
                            + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                    WebServiceConstants.DEFAULT_URL);
            throw new InternalServerException(WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
        }

    }

    /**
     * The default HOCR plugin to be used.
     * 
     * @param batchClassIdentifier {@link String} the identifier for batch class for which learning has to be done.
     * @return {@link String} the name of default HOCR plugin name.
     */
    private String getDefaultHOCRPlugin(final String batchClassIdentifier) {
        String ocrEngine = WebServiceConstants.TESSERACT_HOCR_PLUGIN;
        if (batchClassIdentifier != null && !batchClassIdentifier.isEmpty()) {
            final BatchClass batchClass = batchClassService.getBatchClassByIdentifier(batchClassIdentifier);
            if (null != batchClass) {
                final List<BatchClassPlugin> batchClassPlugins = getOrderedListOfPlugins(batchClass);
                if (batchClassPlugins != null) {
                    String pluginName = null;
                    for (final BatchClassPlugin batchClassPlugin : batchClassPlugins) {
                        if (batchClassPlugin != null) {
                            pluginName = batchClassPlugin.getPlugin().getPluginName();
                        }
                        if (IUtilCommonConstants.TESSERACT_HOCR_PLUGIN.equals(pluginName)) {
                            ocrEngine = WebServiceConstants.TESSERACT_HOCR_PLUGIN;
                            break;
                        }
                    }
                }
            } else {
                LOGGER.info("Batch Class is non existent.");
            }
        }
        LOGGER.info("Default ocr plugin to be used in case both ");
        return ocrEngine;
    }

    /**
     * The switch value for the OCR engine configured in the batch class.
     * 
     * @param batchClassIdentifier {@link String} batch class identifier.
     * @param service {@link PluginPropertiesService} plugin property service to get the plugin for getting properties.
     * @param ocrEngineName {@link String} the name of the ocr engine.
     * @param ocrEngineSwitch {@link PluginProperty} The plugin switch property for the ocr engine.
     * @return {@link String} the value for the switch.
     */
    private String getOcrEngineSwitchValue(final String batchClassIdentifier, final PluginPropertiesService service,
            final String ocrEngineName, final PluginProperty ocrEngineSwitch) {
        String ocrEngineSwitchValue = null;
        final BatchPlugin plugin = service.getPluginProperties(batchClassIdentifier, ocrEngineName);
        if (plugin != null && plugin.getPropertiesSize() > 0) {
            final List<BatchPluginConfiguration> pluginConfigurations = plugin
                    .getPluginConfigurations(ocrEngineSwitch);
            if (pluginConfigurations != null && !pluginConfigurations.isEmpty()) {
                ocrEngineSwitchValue = pluginConfigurations.get(0).getValue();
                LOGGER.info(ocrEngineName + " switch = " + ocrEngineSwitchValue);
            }
        }
        return ocrEngineSwitchValue;
    }

    /**
     * The list of all the batch class plugins.
     * 
     * @param batchClass {@link BatchClass} the batch class for which all the plugins has to be extracted.
     * @return {@link List} list of batch class plugins.
     */
    private List<BatchClassPlugin> getOrderedListOfPlugins(final BatchClass batchClass) {
        List<BatchClassPlugin> allBatchClassPlugins = null;
        if (batchClass != null) {
            final List<BatchClassModule> batchClassModules = batchClass.getBatchClassModules();
            if (batchClassModules != null) {

                if (allBatchClassPlugins == null) {
                    allBatchClassPlugins = new ArrayList<BatchClassPlugin>();
                }
                for (final BatchClassModule batchClassModule : batchClassModules) {
                    final List<BatchClassPlugin> batchClassPlugins = batchClassModule.getBatchClassPlugins();
                    allBatchClassPlugins.addAll(batchClassPlugins);
                }
            }
        }
        return allBatchClassPlugins;
    }

    /**
     * This Web service helper will create the new document type for the specified Batch Class. If it cant create the Document type it
     * raises an Exception
     * 
     * @param req the {@link HttpServletRequest} The request made by the client encapsulated as an Object
     * @throws InternalServerException When an uncaught Exception occurs
     * @throws ValidationException When the Input Parameters cannot be validated
     */
    public void documentTypeCreation(final HttpServletRequest req)
            throws InternalServerException, ValidationException {
        String respStr = WebServiceConstants.EMPTY_STRING;
        String workingDir = WebServiceConstants.EMPTY_STRING;
        if (req instanceof DefaultMultipartHttpServletRequest) {
            try {
                final String webServiceFolderPath = batchSchemaService.getWebServicesFolderPath();
                workingDir = WebServiceUtil.createWebServiceWorkingDir(webServiceFolderPath);
                final DefaultMultipartHttpServletRequest multiPartRequest = (DefaultMultipartHttpServletRequest) req;
                final MultiValueMap<String, MultipartFile> fileMap = multiPartRequest.getMultiFileMap();
                LOGGER.info("Retreiving xml file.");
                String xmlFileName = WebServiceConstants.EMPTY_STRING;
                xmlFileName = getXMLFile(workingDir, multiPartRequest, fileMap);
                WebServiceParams webServiceParams = null;
                final File xmlFile = new File(workingDir + File.separator + xmlFileName);
                if (xmlFile.exists()) {
                    LOGGER.info("Input xml file found, retrieving the parameters from it.");
                    final FileInputStream inputStream = new FileInputStream(xmlFile);
                    final Source source = XMLUtil.createSourceFromStream(inputStream);
                    webServiceParams = (WebServiceParams) batchSchemaDao.getJAXB2Template().getJaxb2Marshaller()
                            .unmarshal(source);
                } else {
                    respStr = WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE;
                    final RestError restError = createUnprocessableEntityRestError(respStr,
                            WebServiceConstants.INVALID_PARAMETERS_CODE);
                    LOGGER.error(WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE + WebServiceConstants.HTTP_STATUS
                            + HttpStatus.UNPROCESSABLE_ENTITY);
                    throw new ValidationException(WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE, restError);
                }
                if (null != webServiceParams.getParams()) {
                    final List<Param> paramList = webServiceParams.getParams().getParam();
                    if (paramList == null || paramList.isEmpty()) {
                        respStr = WebServiceConstants.PARAMETER_XML_INCORRECT_MESSAGE;
                        final RestError restError = createUnprocessableEntityRestError(respStr,
                                WebServiceConstants.INVALID_PARAMETERS_CODE);
                        LOGGER.error(WebServiceConstants.PARAMETER_XML_INCORRECT_MESSAGE
                                + WebServiceConstants.HTTP_STATUS + HttpStatus.UNPROCESSABLE_ENTITY);
                        throw new InternalServerException(WebServiceConstants.PARAMETER_XML_INCORRECT_MESSAGE,
                                restError);
                    } else {
                        LOGGER.info("Initializing input parameters.");
                        String documentTypeName = WebServiceConstants.EMPTY_STRING;
                        String documentTypeDescription = WebServiceConstants.EMPTY_STRING;
                        String minConfidenceThreshold = WebServiceConstants.EMPTY_STRING;
                        String formProcessingFile = WebServiceConstants.EMPTY_STRING;
                        String secondPageProjectFile = WebServiceConstants.EMPTY_STRING;
                        String thirdPageProjectFile = WebServiceConstants.EMPTY_STRING;
                        String lastPageProjectFile = WebServiceConstants.EMPTY_STRING;
                        String batchClassIdentifier = WebServiceConstants.EMPTY_STRING;
                        String hidden = WebServiceConstants.EMPTY_STRING;
                        for (final Param param : paramList) {
                            if (WebServiceConstants.DOCUMENT_TYPE_NAME.equalsIgnoreCase(param.getName())) {
                                documentTypeName = param.getValue().trim();
                                LOGGER.info("Document type name entered is :" + documentTypeName);
                                continue;
                            }
                            if (WebServiceConstants.DOCUMENT_TYPE_DESCRIPTION.equalsIgnoreCase(param.getName())) {
                                documentTypeDescription = param.getValue().trim();
                                LOGGER.info("Document type description given is :" + documentTypeDescription);
                                continue;
                            }
                            if (WebServiceConstants.MIN_CONFIDENCE_THRESHOLD.equalsIgnoreCase(param.getName())) {
                                minConfidenceThreshold = param.getValue().trim();
                                LOGGER.info("Document type minimum confidence threshold entered is :"
                                        + minConfidenceThreshold);
                                continue;
                            }
                            if (WebServiceConstants.FIRST_PAGE_PROJECT_FILE.equalsIgnoreCase(param.getName())) {
                                formProcessingFile = param.getValue().trim();
                                LOGGER.info(EphesoftStringUtil.concatenate(
                                        "Document type form processing file entered is : ", formProcessingFile));
                                continue;
                            }

                            if (WebServiceConstants.SECOND_PAGE_PROJECT_FILE.equalsIgnoreCase(param.getName())) {
                                secondPageProjectFile = param.getValue().trim();
                                LOGGER.info(EphesoftStringUtil.concatenate(
                                        "Document type second page form processing file entered is : ",
                                        secondPageProjectFile));
                                continue;
                            }

                            if (WebServiceConstants.THIRD_PAGE_PROJECT_FILE.equalsIgnoreCase(param.getName())) {
                                thirdPageProjectFile = param.getValue().trim();
                                LOGGER.info(EphesoftStringUtil.concatenate(
                                        "Document type third page form processing file entered is : ",
                                        thirdPageProjectFile));
                                continue;
                            }

                            if (WebServiceConstants.LAST_PAGE_PROJECT_FILE.equalsIgnoreCase(param.getName())) {
                                lastPageProjectFile = param.getValue().trim();
                                LOGGER.info(EphesoftStringUtil.concatenate(
                                        "Document type last page form processing file entered is : ",
                                        lastPageProjectFile));
                                continue;
                            }
                            if (WebServiceUtil.BATCH_CLASS_IDENTIFIER.equalsIgnoreCase(param.getName())) {
                                batchClassIdentifier = param.getValue().trim();
                                LOGGER.info("Batch class identifier used for copying batch class is :"
                                        + batchClassIdentifier);
                                continue;
                            }
                            if (WebServiceConstants.HIDDEN.equalsIgnoreCase(param.getName())) {
                                hidden = param.getValue().trim();
                                LOGGER.info("Document type hidden field parameter value entered is :" + hidden);
                                continue;
                            }
                        }

                        final List<String> formProcessingFileList = new ArrayList<String>();
                        formProcessingFileList.add(formProcessingFile);
                        formProcessingFileList.add(secondPageProjectFile);
                        formProcessingFileList.add(thirdPageProjectFile);
                        formProcessingFileList.add(lastPageProjectFile);
                        // Validation for document type creation parameters
                        // provided.
                        LOGGER.info("Validating parameters.");
                        respStr = validateDocumentTypeCreationParameters(documentTypeName, documentTypeDescription,
                                minConfidenceThreshold, formProcessingFileList, batchClassIdentifier, hidden);
                        // verify for unique entries for batch class and unc
                        // folders.
                        if (respStr.isEmpty()) {
                            // creating a new document type.
                            final DocumentType newDocumentType = new DocumentType();
                            newDocumentType.setName(documentTypeName);
                            newDocumentType.setDescription(documentTypeDescription);
                            newDocumentType.setMinConfidenceThreshold(Float.parseFloat(minConfidenceThreshold));
                            newDocumentType.setFirstPageProjectFileName(formProcessingFile);
                            newDocumentType.setSecondPageProjectFileName(secondPageProjectFile);
                            newDocumentType.setThirdPageProjectFileName(thirdPageProjectFile);
                            newDocumentType.setFourthPageProjectFileName(lastPageProjectFile);

                            final List<PageType> pages = getListOfPageTypes(documentTypeName);
                            newDocumentType.setPages(pages);
                            if (hidden.equalsIgnoreCase(TRUE)) {
                                newDocumentType.setHidden(true);
                            } else {
                                newDocumentType.setHidden(false);
                            }
                            final BatchClass batchClass = batchClassService
                                    .getBatchClassByIdentifier(batchClassIdentifier);
                            // adding the document type to the requested batch
                            // class.
                            batchClass.addDocumentType(newDocumentType);
                            // merging the batch class for persisting the
                            // database state for new document type entry.
                            batchClassService.merge(batchClass);
                        } else {
                            // if the parameters provided didn't validate.
                            final HttpStatus status = HttpStatus.UNPROCESSABLE_ENTITY;
                            final RestError restError = createUnprocessableEntityRestError(respStr,
                                    WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_CODE);
                            LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
                            throw new ValidationException(respStr, restError);
                        }
                    }
                } else {
                    respStr = WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_MESSAGE;
                    throw new ValidationException(respStr, createUnprocessableEntityRestError(respStr,
                            WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_CODE));
                }
            } catch (final ValidationException validationException) {
                throw validationException;
            } catch (final InternalServerException internalServerError) {
                throw internalServerError;
            } catch (final Exception exception) {
                // to handle any other kind of exception that has occurred
                // during creation.
                final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                respStr = WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + exception;
                final RestError restError = createUnprocessableEntityRestError(
                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + exception.getMessage(),
                        WebServiceConstants.INTERNAL_SERVER_ERROR_CODE);
                LOGGER.error("Error response at server:" + respStr);
                final InternalServerException internalServerExcpetion = new InternalServerException(
                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
                LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
                throw internalServerExcpetion;
            } finally {
                if (!workingDir.isEmpty()) {
                    FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
                }
            }
        } else {
            respStr = WebServiceConstants.INVALID_MULTIPART_REQUEST;
            final RestError restError = createUnprocessableEntityRestError(respStr,
                    WebServiceConstants.INVALID_PARAMETERS_CODE);
            throw new InternalServerException(respStr, restError);
        }

    }

    /**
     * Make the list of page types for the given document type name.
     * 
     * @param documentTypeName {@link String} the name of the document being created.
     * @return {@link List <PageType>}
     */
    private List<PageType> getListOfPageTypes(final String documentTypeName) {
        final List<PageType> pages = new ArrayList<PageType>();
        // Add a first page.
        final PageType firstPage = new PageType();
        firstPage.setDescription(documentTypeName + WebServiceConstants.FIRST_PAGE);
        firstPage.setName(documentTypeName + WebServiceConstants.FIRST_PAGE);
        // Add a middle page.
        final PageType middlePage = new PageType();
        middlePage.setDescription(documentTypeName + WebServiceConstants.MIDDLE_PAGE);
        middlePage.setName(documentTypeName + WebServiceConstants.MIDDLE_PAGE);
        // Add a last page.
        final PageType lastPage = new PageType();
        lastPage.setDescription(documentTypeName + WebServiceConstants.LAST_PAGE);
        lastPage.setName(documentTypeName + WebServiceConstants.LAST_PAGE);
        pages.add(firstPage);
        pages.add(middlePage);
        pages.add(lastPage);
        return pages;
    }

    /**
     * Validation for the document name required for document type creation web service.
     * 
     * @param documentTypeName {@link String} the name of document type which has to be created.
     * @param batchClassIdentifier {@link String} the batch class identifier in which document type has to be created.
     * @return {@link String} the resulting string for validation. If empty then all fields are validated otherwise the error statement
     *         is given in the returned string.
     */
    private boolean validateDocumentName(final String documentTypeName, final String batchClassIdentifier) {
        boolean docTypeNameUnique = true;
        final String respStr = WebServiceConstants.EMPTY_STRING;
        if (respStr.isEmpty()) {
            final BatchClass batchClass = batchClassService.getBatchClassByIdentifier(batchClassIdentifier);
            if (batchClass != null) {
                final List<DocumentType> documentList = batchClass.getDocumentTypes();
                if (documentList != null) {
                    for (final DocumentType docType : documentList) {
                        if (documentTypeName.equalsIgnoreCase(docType.getName())) {
                            docTypeNameUnique = false;
                            break;
                        }

                    }
                }
            }
        }
        return docTypeNameUnique;
    }

    /**
     * Method to validate the input fields for create document type web service.
     * 
     * @param documentTypeName {@link String} the name for new document to be created.
     * @param documentTypeDescription {@link String} the description for the new document type to be created.
     * @param minConfidenceThreshold {@link String} the minimum threshold value for this document type.
     * @param formProcessingFileList {@link String[]} list of the type of rsp processing file required.
     * @param batchClassIdentifier {@link String} the batch class identifier for which this document type has to be created.
     * @param hidden {@link String} value to state if this document type has to be of type hidden.
     * @return {@link String} the resulting string for validation. If empty then all fields are validated otherwise the error statement
     *         is given in the returned string.
     */
    private String validateDocumentTypeCreationParameters(final String documentTypeName,
            final String documentTypeDescription, final String minConfidenceThreshold,
            final List<String> formProcessingFileList, final String batchClassIdentifier, final String hidden) {
        String errorMessage = WebServiceConstants.EMPTY_STRING;
        boolean isValid = true;
        if (documentTypeName == null || documentTypeName.isEmpty()) {
            errorMessage = "The document type name is empty. Please enter unique name for document type.";
            isValid = false;
        }
        if (isValid && documentTypeName.contains("*")) {
            errorMessage = "The name of document type cannot contain character '*' in it."
                    + " Please enter a unique name without this character.";
            isValid = false;
        }
        if (isValid && (documentTypeDescription == null || documentTypeDescription.isEmpty())) {
            errorMessage = "The batch class description is empty. Please enter description for batch class.";
            isValid = false;
        }
        if (isValid && (minConfidenceThreshold == null || minConfidenceThreshold.isEmpty())) {
            errorMessage = "The minimum confidence threshold cannot be null"
                    + " and should be between 0 and 100 inclusive of both. Please enter correct value.";
            isValid = false;
        }
        if (isValid && (batchClassIdentifier == null || batchClassIdentifier.isEmpty())) {
            errorMessage = "The batch class identifier is empty. Please enter proper batch class identifier.";
            isValid = false;
        } else {
            if (isValid) {
                errorMessage = validateBatchClassIdentifier(batchClassIdentifier);
                if (!errorMessage.isEmpty()) {
                    isValid = false;
                }
            }
        }
        if (isValid && (documentTypeName.length() > MAX_CHARACTER_LIMIT)) {
            errorMessage = "Batch class name must not be more than 255 characters.";
            isValid = false;
        }
        if (isValid && !(TRUE.equalsIgnoreCase(hidden) || FALSE.equalsIgnoreCase(hidden))) {
            errorMessage = "The hidden property value entered is incorrect."
                    + " Please give true/false for this property in xml file.";
            isValid = false;
        }

        if (isValid && !validateDocumentName(documentTypeName, batchClassIdentifier)) {
            errorMessage = "Document type name is not unique. Please enter a unique name for document type.";
            isValid = false;
        }

        for (String formProcessingFile : formProcessingFileList) {
            if (!(EphesoftStringUtil.isNullOrEmpty(formProcessingFile))) {
                errorMessage = validateProcessingFile(formProcessingFile, batchClassIdentifier);
                if (EphesoftStringUtil.isNullOrEmpty(errorMessage)) {
                    isValid = false;
                }
            }
        }

        if (isValid) {
            try {
                final float confidenceThreshold = Float.parseFloat(minConfidenceThreshold);
                if (confidenceThreshold < MIN_CONFIDENCE_THRESHOLD_VALUE
                        || confidenceThreshold > MAX_CONFIDENCE_THRESHOLD_VALUE) {
                    errorMessage = "The minimum threshold for confidence should be a numeric value"
                            + " between 0 and 100 inclusive of both.";
                    isValid = false;
                }
            } catch (final NumberFormatException numberFormatException) {
                errorMessage = "The value entered of minimum threshold for confidence should be a numeric value.";
                isValid = false;
            }
        }

        return errorMessage;
    }

    /**
     * This method is used to get the input xml file.
     * 
     * @param workingDir {@link String} the working directory created for web service execution.
     * @param multiPartRequest {@link DefaultMultipartHttpServletRequest} request to get the multipart from request.
     * @param fileMap {@link MultiValueMap} this map contains the input files.
     * @return string
     * @throws IOException
     * @throws FileNotFoundException
     */
    public static String getXMLFile(final String workingDir,
            final DefaultMultipartHttpServletRequest multiPartRequest,
            final MultiValueMap<String, MultipartFile> fileMap) throws IOException {
        InputStream instream = null;
        OutputStream outStream = null;
        String xmlFileName = WebServiceConstants.EMPTY_STRING;
        LOGGER.info("Checking for input file.");
        for (final String fileName : fileMap.keySet()) {
            try {
                if (fileName.endsWith(FileType.XML.getExtensionWithDot())) {
                    xmlFileName = fileName;
                }
                final MultipartFile multiPartFile = multiPartRequest.getFile(fileName);
                instream = multiPartFile.getInputStream();
                final File file = new File(workingDir + File.separator + fileName);
                outStream = new FileOutputStream(file);
                final byte[] buf = new byte[WebServiceUtil.bufferSize];
                int len;
                while ((len = instream.read(buf)) > 0) {
                    outStream.write(buf, 0, len);
                }
            } finally {
                IOUtils.closeQuietly(instream);
                IOUtils.closeQuietly(outStream);
            }
        }
        return xmlFileName;
    }

    /**
     * Validations for batch class identifier.
     * 
     * @param batchClassIdentifier {@link String} the batch class identifier.
     * @return {@link String} null if input is validated otherwise the result string of validation.
     */
    private String validateBatchClassIdentifier(final String batchClassIdentifier) {
        String respStr = WebServiceConstants.EMPTY_STRING;
        LOGGER.info("Validating unique value for batch class identifier.");
        if (batchClassIdentifier == null || batchClassIdentifier.isEmpty()) {
            respStr = "The batch class identifier is empty. Please enter proper batch class identifier.";
        }
        if (respStr.isEmpty() && batchClassService.getBatchClassByIdentifier(batchClassIdentifier) == null) {
            respStr = "Batch class identifier provided does not exist. Please enter a valid value.";
        }
        return respStr;
    }

    /**
     * Method to extract all required fields and process request.
     * 
     * @param req {@link HttpServletRequest} the request header for web service hit.
     * @throws InternalServerException
     * @throws ValidationException
     */
    public void processCopyBatchClass(final HttpServletRequest req)
            throws InternalServerException, ValidationException {
        String respStr = WebServiceConstants.EMPTY_STRING;
        String workingDir = WebServiceConstants.EMPTY_STRING;
        if (req instanceof DefaultMultipartHttpServletRequest) {
            try {
                final String webServiceFolderPath = batchSchemaService.getWebServicesFolderPath();
                workingDir = WebServiceUtil.createWebServiceWorkingDir(webServiceFolderPath);
                final DefaultMultipartHttpServletRequest multiPartRequest = (DefaultMultipartHttpServletRequest) req;
                final MultiValueMap<String, MultipartFile> fileMap = multiPartRequest.getMultiFileMap();
                LOGGER.info("Retreiving xml file.");
                if (respStr.isEmpty()) {
                    String xmlFileName = WebServiceConstants.EMPTY_STRING;
                    xmlFileName = getXMLFile(workingDir, multiPartRequest, fileMap);
                    WebServiceParams webServiceParams = null;
                    final File xmlFile = new File(workingDir + File.separator + xmlFileName);
                    if (xmlFile.exists()) {
                        LOGGER.info("Input xml file found, retrieving the parameters from it.");
                        final FileInputStream inputStream = new FileInputStream(xmlFile);
                        final Source source = XMLUtil.createSourceFromStream(inputStream);
                        webServiceParams = (WebServiceParams) batchSchemaDao.getJAXB2Template().getJaxb2Marshaller()
                                .unmarshal(source);
                    } else {
                        createAndThrowMissingXmlException(WebServiceConstants.INPUT_XML_NOT_FOUND_CODE,
                                WebServiceConstants.INPUT_XML_NOT_FOUND_MESSAGE);
                    }
                    final List<Param> paramList = webServiceParams.getParams().getParam();
                    if (paramList == null || paramList.isEmpty()) {
                        final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                        final RestError restError = new RestError(status,
                                WebServiceConstants.PARAMETER_XML_INCORRECT_CODE,
                                WebServiceConstants.PARAMETER_XML_INCORRECT_MESSAGE,
                                WebServiceConstants.PARAMETER_XML_INCORRECT_MESSAGE
                                        + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                WebServiceConstants.DEFAULT_URL);
                        LOGGER.error(status + WebServiceConstants.PARAMETER_XML_INCORRECT_MESSAGE);
                        throw new ValidationException(WebServiceConstants.PARAMETER_XML_INCORRECT_MESSAGE,
                                restError);
                    } else {
                        LOGGER.info("Initializing input parameters.");
                        String batchClassName = WebServiceConstants.EMPTY_STRING;
                        String batchClassDescription = WebServiceConstants.EMPTY_STRING;
                        String batchClassPriority = WebServiceConstants.EMPTY_STRING;
                        String uncFolderName = WebServiceConstants.EMPTY_STRING;
                        String batchClassIdentifier = WebServiceConstants.EMPTY_STRING;
                        String gridWorkflow = WebServiceConstants.EMPTY_STRING;
                        for (final Param param : paramList) {
                            if ((WebServiceConstants.BATCH_CLASS_NAME).equalsIgnoreCase(param.getName())) {
                                batchClassName = param.getValue().trim();
                                LOGGER.info("Batch class name entered is :" + batchClassName);
                                continue;
                            }
                            if ((WebServiceConstants.BATCH_CLASS_DESCRIPTION).equalsIgnoreCase(param.getName())) {
                                batchClassDescription = param.getValue().trim();
                                LOGGER.info("Batch class description given is :" + batchClassDescription);
                                continue;
                            }
                            if ((WebServiceConstants.BATCH_CLASS_PRIORITY).equalsIgnoreCase(param.getName())) {
                                batchClassPriority = param.getValue().trim();
                                LOGGER.info("Batch class priority entered is :" + batchClassPriority);
                                continue;
                            }
                            if ((WebServiceConstants.BATCH_UNC_FOLDER_NAME).equalsIgnoreCase(param.getName())) {
                                uncFolderName = param.getValue().trim();
                                LOGGER.info("UNC folder path entered is : " + uncFolderName);
                                continue;
                            }
                            if ((WebServiceConstants.COPY_BATCH_CLASS_IDENTIFIER)
                                    .equalsIgnoreCase(param.getName())) {
                                batchClassIdentifier = param.getValue().trim();
                                LOGGER.info("Batch class identifier used for copying batch class is :"
                                        + batchClassIdentifier);
                                continue;
                            }
                            if ((WebServiceConstants.IS_GRIDWORKFLOW).equalsIgnoreCase(param.getName())) {
                                gridWorkflow = param.getValue().trim();
                                LOGGER.info("Grid workflow is :" + gridWorkflow);
                                continue;
                            }
                        }
                        // Validation for batch class creation parameters
                        // provided.
                        LOGGER.info("Validating parameters.");
                        respStr = validateCreateBatchClassParameters(batchClassName, batchClassDescription,
                                batchClassPriority, uncFolderName, batchClassIdentifier, gridWorkflow);
                        // verify for unique entries for batch class and unc
                        // folders.
                        if (respStr.isEmpty()) {
                            respStr = validateBatchClassAndUNC(batchClassName, uncFolderName, batchClassIdentifier);
                            if (respStr.isEmpty()) {
                                // After validation creating batch class.
                                Set<String> superAdminGroups = userConnectivityService.getAllSuperAdminGroups();
                                if (superAdminGroups != null && !superAdminGroups.isEmpty()) {
                                    performBatchClassCreation(batchClassName, batchClassDescription,
                                            batchClassPriority, uncFolderName, batchClassIdentifier,
                                            superAdminGroups.toArray()[0].toString());
                                    BatchClass batchClass = batchClassService
                                            .getBatchClassbyUncFolder(uncFolderName);
                                    List<BatchClassGroups> assignedRoles = new ArrayList<BatchClassGroups>();
                                    BatchClassGroups bcGrup = new BatchClassGroups();
                                    bcGrup.setBatchClass(batchClass);
                                    for (int itr = 1; itr < superAdminGroups.size(); itr++) {
                                        bcGrup.setGroupName(superAdminGroups.toArray()[itr].toString());
                                    }
                                    assignedRoles.add(bcGrup);
                                    // batchClass.setAssignedGroups(assignedRoles);
                                    batchClassService.saveOrUpdate(batchClass);
                                    // JIRA-BUG-ID-11125
                                    deploymentService.createAndDeployProcessDefinition(batchClass, false);
                                } else {
                                    respStr = "Error in retreving admin groups.Please check user-connectivity settings.";
                                    final HttpStatus status = HttpStatus.FORBIDDEN;
                                    final RestError restError = new RestError(status,
                                            WebServiceConstants.ADMIN_ROLES_NOT_FOUND, respStr,
                                            WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                            WebServiceConstants.DEFAULT_URL);
                                    LOGGER.error(
                                            "Error in retreving admin groups.Please check user-connectivity settings"
                                                    + status);
                                    throw new ValidationException(respStr, restError);
                                }
                            } else {
                                final HttpStatus status = HttpStatus.UNPROCESSABLE_ENTITY;
                                final RestError restError = new RestError(status,
                                        WebServiceConstants.VALIDATION_EXCEPTION_CODE, respStr,
                                        WebServiceConstants.VALIDATION_EXCEPTION_MESSAGE
                                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                        WebServiceConstants.DEFAULT_URL);
                                LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
                                throw new ValidationException(respStr, restError);
                            }
                        } else {
                            final HttpStatus status = HttpStatus.UNPROCESSABLE_ENTITY;
                            final RestError restError = new RestError(status,
                                    WebServiceConstants.VALIDATION_EXCEPTION_CODE, respStr,
                                    WebServiceConstants.CLASS_WEB_SERVICE_UTILITY, WebServiceConstants.DEFAULT_URL);
                            LOGGER.error("Error in Validating Input XML " + respStr + status);
                            throw new ValidationException(respStr, restError);
                        }
                    }
                }
            } catch (org.xml.sax.SAXParseException Ex) {
                respStr = "Error in Parsing Input XML.Please try again";
                final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                        WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_CODE, respStr,
                        WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                LOGGER.error("Error response at server:" + respStr);
                throw new ValidationException(respStr, restError);
            } catch (final FileNotFoundException fe) {
                respStr = "Input XMl file is not found.Please try again";
                final RestError restError = new RestError(HttpStatus.NOT_FOUND,
                        WebServiceConstants.INPUT_XML_NOT_FOUND_CODE, respStr,
                        WebServiceConstants.INPUT_XML_NOT_FOUND_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                LOGGER.error("Error response at server:" + respStr + fe);
                throw new ValidationException(WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
            } catch (ValidationException validationException) {
                throw validationException;
            } catch (InternalServerException validationException) {
                throw validationException;
            } catch (final Exception exception) {
                final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                respStr = WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + exception;
                final RestError restError = new RestError(status, WebServiceConstants.INTERNAL_SERVER_ERROR_CODE,
                        respStr, respStr + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                LOGGER.error("Error response at server:" + respStr + exception);
                throw new InternalServerException(respStr, restError);
            } finally {
                if (!workingDir.isEmpty()) {
                    FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
                }
            }
        } else {
            final HttpStatus status = HttpStatus.UNPROCESSABLE_ENTITY;
            final RestError restError = new RestError(status, WebServiceConstants.VALIDATION_EXCEPTION_CODE,
                    WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE,
                    respStr + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY, WebServiceConstants.DEFAULT_URL);
            LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
            throw new ValidationException(respStr, restError);
        }
    }

    /**
     * This method is used to check for batch class name and unc folder path uniqueness.
     * 
     * @param batchClassName {@link String} this is the name of batch class to be created.
     * @param uncFolderPath {@link String} this is the unc folder path for batch class to be created.
     * @param batchClassIdentifier {@link String} this is the identifier for thebatch class from which new batch class has to be
     *            copied.
     * @return {@link String} the resulting string for batch class parameter validation. If string is not empty then it means some
     *         error has occurred.
     */
    private String validateBatchClassAndUNC(final String batchClassName, final String uncFolderPath,
            final String batchClassIdentifier) {
        boolean isValid = true;
        String respStr = WebServiceConstants.EMPTY_STRING;
        LOGGER.info("Validating unique values for batch class name and unc folder path inputs.");
        // Checking for batch class identifier present or not.
        if (batchClassService.getBatchClassByIdentifier(batchClassIdentifier) == null) {
            respStr = "Batch class identifier provided to copy batch class does not exist. Please enter a valid value.";
            isValid = false;
        }
        // Checking for unique batch class name.
        if (isValid && batchClassService.getBatchClassbyName(batchClassName) != null) {
            respStr = "Batch class name is not unique. Please enter a unique name for batch class.";
            isValid = false;
        }
        // Checking for unique batch class unc folder.
        if (isValid) {
            final List<BatchClass> batchClassList = batchClassService.getAllBatchClasses();
            for (final BatchClass batchClass : batchClassList) {
                if (batchClass.getUncFolder().endsWith(uncFolderPath)) {
                    respStr = "Batch class UNC folder is not unique."
                            + " Please enter a unique UNC folder path for batch class.";
                    break;
                }
            }
        }
        return respStr;
    }

    /**
     * This method is used to get the call for batch class creation.
     * 
     * @param batchClassName {@link String} batch class name for creating new batch class.
     * @param batchClassDescription {@link String} batch class description for creating new batch class.
     * @param batchClassPriority {@link String} batch class priority for creating new batch class.
     * @param uncFolderPath {@link String} batch class unc path for creating new batch class.
     * @param batchClassIdentifier {@link String} batch class identifier to be used for copying batch class.
     * @param batchClassGroup {@link String} group to which this batch class has to be assigned.
     * @param configureExportFolder {@link String} property used for configuring the export folder for new batch class.
     * @throws InternalServerException
     */
    private void performBatchClassCreation(final String batchClassName, final String batchClassDescription,
            final String batchClassPriority, final String uncFolderPath, final String batchClassIdentifier,
            final String batchClassGroup) throws InternalServerException {
        LOGGER.info("Input parameters validated, creating batch class:");
        try {
            // Calling the batch class copy method for batch class service.
            final BatchClass copiedBatchClass = batchClassService.copyBatchClass(batchClassIdentifier,
                    batchClassName, batchClassDescription, batchClassGroup, batchClassPriority, uncFolderPath,
                    true);
            // Copied Batch Class should get deployed.
            if (null != copiedBatchClass) {
                deploymentService.createAndDeployProcessDefinition(copiedBatchClass, false);
            }
        } catch (final Exception exception) {
            final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
            final RestError restError = new RestError(status, WebServiceConstants.INTERNAL_SERVER_ERROR_CODE,
                    WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE,
                    WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE
                            + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                    WebServiceConstants.DEFAULT_URL);
            LOGGER.error(WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + exception.getMessage());
            throw new InternalServerException("Could not create batch class due to internal error", restError);
        }
    }

    /**
     * Perform the learning for provided batch class identifier.
     * 
     * @param batchClassIdentifier {@link String} the identifier for the batch class for which learning has to be done.
     * @throws InternalServerException
     * @throws ValidationException
     */
    public void performLearningForBatchClass(final String batchClassIdentifier)
            throws InternalServerException, ValidationException {
        String respStr = WebServiceConstants.EMPTY_STRING;
        // validating the input for batch class identifier.
        respStr = validateBatchClassIdentifier(batchClassIdentifier);
        if (respStr.isEmpty()) {
            try {
                learnFileForBatchClass(batchClassIdentifier);
            } catch (final Exception e) {
                final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                respStr = WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE;
                final RestError restError = new RestError(status, WebServiceConstants.IMPROPER_INPUT_TO_SERVER_CODE,
                        WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                        WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
                throw new InternalServerException(WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE, restError);
            }
        } else {
            final HttpStatus status = HttpStatus.UNPROCESSABLE_ENTITY;
            final RestError restError = new RestError(status, WebServiceConstants.VALIDATION_EXCEPTION_CODE,
                    respStr, respStr + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                    WebServiceConstants.DEFAULT_URL);
            LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
            throw new ValidationException(respStr, restError);
        }
    }

    /**
     * This method is used to validate the input parameters for create batch class parameters.
     * 
     * @param batchClassName {@link String} batch class name to be created.
     * @param batchClassDescription {@link String} batch class description to be created.
     * @param batchClassPriority {@link String} batch class priority to be created.
     * @param batchUNCFolder {@link String} batch class unc folder path to be created.
     * @param batchClassID {@link String} batch class identifier from which it has to be copied.
     * @param gridWorkflow {@link String} batch class grid workflow deployment variable.
     * @return {@link String} return string carries the result of validation. If string is empty then it means that parameters are
     *         validated, otherwise the error statement is returned.
     */
    public static String validateCreateBatchClassParameters(final String batchClassName,
            final String batchClassDescription, final String batchClassPriority, final String batchUNCFolder,
            final String batchClassID, final String gridWorkflow) {
        String respStr = WebServiceConstants.EMPTY_STRING;
        boolean isValid = true;
        if (batchClassName == null || batchClassName.isEmpty()) {
            respStr = "The batch class name is empty. Please enter unique name for batch class.";
            isValid = false;
        }
        if (isValid && (batchClassDescription == null || batchClassDescription.isEmpty())) {
            respStr = "The batch class description is empty. Please enter description for batch class.";
            isValid = false;
        }
        if (isValid && (batchClassPriority == null || batchClassPriority.isEmpty())) {
            respStr = "The batch class priority is empty. Please enter priority for batch class.";
            isValid = false;
        }
        if (isValid && (batchUNCFolder == null || batchUNCFolder.isEmpty())) {
            respStr = "The batch class UNC folder is empty. Please enter proper UNC folder path for batch class.";
            isValid = false;
        }
        if (isValid && (batchClassID == null || batchClassID.isEmpty())) {
            respStr = "The batch class identifier is empty. Please enter proper batch class identifier.";
            isValid = false;
        }
        if (isValid && (batchClassName.contains(" ") || batchClassName.contains("-"))) {
            respStr = "Batch class name must not contain a space or a hyphen.";
            isValid = false;
        }
        if (isValid && (gridWorkflow == null || gridWorkflow.isEmpty())) {
            respStr = "Grid workflow must not be empty. Please enter a valid value.";
            isValid = false;
        }
        if (isValid && !(TRUE.equalsIgnoreCase(gridWorkflow) || FALSE.equalsIgnoreCase(gridWorkflow))) {
            respStr = "Grid workflow must be either true or false. Please enter a valid value.";
            isValid = false;
        }
        if (isValid && (batchClassName.length() > MAX_CHARACTER_LIMIT)) {
            respStr = "Batch class name must not be more than 255 characters.";
            isValid = false;
        }
        if (isValid) {
            try {
                final int priority = Integer.parseInt(batchClassPriority);
                if (priority < MIN_PRIORITY_VALUE || priority > MAX_PRIORITY_VALUE) {
                    respStr = "The batch class priority should be a numeric value between 0 and 100 inclusive of both.";
                    isValid = false;
                }
            } catch (final NumberFormatException numberFormatException) {
                respStr = "The value entered for priority should be a numeric value.";
                isValid = false;
            }
        }
        return respStr;
    }

    /**
     * Extracting the xml structure for exception received.
     * 
     * @param statusCode {@link HttpStatus} the status code for received exception.
     * @param cause {@link String} the cause description to the error.
     * @param customCode int the custom code maintained for this specific error cause.
     * @return {@link RootElement} the root object of xml structure returned.
     */
    public RootElement getXMLStructureObjectForError(final HttpStatus statusCode, final String cause,
            final int customCode) {
        rootElement = new RootElement();
        responseCodeElement = new ResponseCodeElement();
        errorElement = new ErrorElement();
        responseCodeElement.setHttpCode(statusCode.value());
        responseCodeElement.setResult(WebServiceConstants.ERROR);
        rootElement.setResponseCode(responseCodeElement);
        errorElement.setCause(cause);
        errorElement.setCustomCode(customCode);
        errorElement.setInfoUrl(WebServiceConstants.DEFAULT_URL);
        rootElement.setError(errorElement);
        return rootElement;
    }

    /**
     * This is an helper API for the request of getting Batch Class Identifiers by role to the user. It returns the {@link ListValues}
     * corresponding to the Object
     * 
     * @param role {@link String} The Role Corresponding to which the Batch Class instances are required
     * @return {@link ListValues} of the Batch Class identifiers corresponding to the role
     * @throws ValidationException When the input cannot be validated to the request
     */
    public ListValues getBatchClassIdentifiersForRole(final String role) throws ValidationException {
        final Set<String> batchClassIdentifiers = new TreeSet<String>();
        if (!StringUtils.isEmpty(role) && userConnectivityService.getAllGroups().contains(role)) {
            LOGGER.info("Given role: " + role + " is valid.");
            if (userConnectivityService.getAllSuperAdminGroups().contains(role)) {
                LOGGER.info("Given role:" + role + " is super admin.");
                final List<String> results = batchClassService.getAllBatchClassIdentifier();
                if (CollectionUtils.isNotEmpty(results)) {
                    batchClassIdentifiers.addAll(results);
                }
            } else {
                final Set<String> userRoles = new HashSet<String>();
                userRoles.add(role);
                LOGGER.info("Fetching batch classes for user role" + role);
                final Set<String> results = batchClassGroupsService.getBatchClassIdentifierForUserRoles(userRoles,
                        false);
                if (CollectionUtils.isNotEmpty(results)) {
                    batchClassIdentifiers.addAll(results);
                }
            }
        } else {
            throw new ValidationException(WebServiceConstants.INVALID_ROLE_ERROR_MESSAGE,
                    createUnprocessableEntityRestError(WebServiceConstants.INVALID_ROLE_ERROR_MESSAGE,
                            WebServiceConstants.INVALID_ROLE_ERROR_CODE));
        }
        final ListValues list = new ListValues();
        list.getValue().addAll(batchClassIdentifiers);
        return list;
    }

    /**
     * Gets the batch instance identifiers for role corresponding to the role passed as an argument. It process the request and returns
     * the {@link ListValues} corresponding to the role. and throws an {@link ValidationException} when could not validate the input
     * role
     * 
     * @param role {@link String} role corresponding to which the Batch instances are required
     * @return {@link ListValues} of the Batch Instances
     * @throws ValidationException when could not validate the Input role.
     */
    public ListValues getBatchInstanceIdentifiersForRole(final String role) throws ValidationException {
        final Set<String> batchInstanceIdentifiers = new TreeSet<String>();
        if (!StringUtils.isEmpty(role) && userConnectivityService.getAllGroups().contains(role)) {
            LOGGER.info("Given role:" + role + " is valid.");
            List<BatchClass> batchClassList;
            if (userConnectivityService.getAllSuperAdminGroups().contains(role)) {
                LOGGER.info("Given role:" + role + " is super admin.");
                batchClassList = batchClassService.getAllBatchClasses();
            } else {
                final Set<String> userRoles = new HashSet<String>();
                userRoles.add(role);
                batchClassList = batchClassService.getAllBatchClassesByUserRoles(userRoles);
            }
            if (CollectionUtils.isNotEmpty(batchClassList)) {
                List<BatchInstance> eachBatchInstance;
                for (final BatchClass batchClass : batchClassList) {
                    // TODO : service hit should not be inside the loop.
                    eachBatchInstance = batchInstanceService.getBatchInstByBatchClass(batchClass);
                    for (final BatchInstance batchInstance : eachBatchInstance) {
                        batchInstanceIdentifiers.add(batchInstance.getIdentifier());
                    }
                }
            }
        } else {
            throw new ValidationException(WebServiceConstants.INVALID_ROLE_ERROR_MESSAGE,
                    createUnprocessableEntityRestError(WebServiceConstants.INVALID_ROLE_ERROR_MESSAGE,
                            WebServiceConstants.INVALID_ROLE_ERROR_CODE));
        }
        final ListValues list = new ListValues();
        list.getValue().addAll(batchInstanceIdentifiers);
        return list;
    }

    /**
     * Gets the batch instance list on the basis of passed status, roles of the logged in user and flag whether the user is super admin
     * or not.
     * 
     * @param statusParam the batch instance status
     * @param loggedInUserRole the logged in user role
     * @param isSuperAdmin the flag if the user is super admin
     * @return the batch instance list
     * @throws ValidationException
     * @throws ValidationException the validation exception
     */
    public BatchInstances getBatchInstanceList(final String statusParam, final Set<String> loggedInUserRole,
            final boolean isSuperAdmin) throws ValidationException {
        final BatchInstances batchInstances = new BatchInstances();
        boolean isStatusValid = false;
        String status = null;
        final List<String> statusList = BatchInstanceStatus.valuesAsStringList();
        for (final String statusItem : statusList) {
            if (statusItem.equalsIgnoreCase(statusParam)) {
                status = statusItem;
                isStatusValid = true;
                break;
            }
        }
        if (!isStatusValid) {
            throw new ValidationException(WebServiceConstants.INVALID_BATCH_INSTANCE_STATUS_MESSAGE,
                    new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                            WebServiceConstants.INVALID_BATCH_INSTANCE_STATUS_CODE,
                            WebServiceConstants.INVALID_BATCH_INSTANCE_STATUS_MESSAGE,
                            WebServiceConstants.INVALID_BATCH_INSTANCE_STATUS_MESSAGE
                                    + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                            WebServiceConstants.DEFAULT_URL));
        } else {
            final Set<String> batchInstancesId = new TreeSet<String>();
            final BatchInstanceStatus batchInstanceStatus = BatchInstanceStatus.valueOf(status);
            LOGGER.info("Batch instance status is " + status);
            LOGGER.info("Fetching batch instance list from the database");
            final List<BatchInstance> batchInstance = batchInstanceService
                    .getBatchInstByStatus(batchInstanceStatus);
            if (CollectionUtils.isNotEmpty(batchInstance)) {
                if (!isSuperAdmin) {
                    // fetch the batch instances from batch instance groups
                    final Set<String> batchInstancesIdentifiers = batchInstanceGroupsService
                            .getBatchInstanceIdentifierForUserRoles(loggedInUserRole);

                    if (CollectionUtils.isNotEmpty(batchInstancesIdentifiers)) {
                        batchInstancesId.addAll(batchInstancesIdentifiers);
                    }

                    // fetch the list of batch instances from the batch instance
                    // table for batch classes having the given role.
                    final List<BatchClass> batchClasses = batchClassService
                            .getAllBatchClassesByUserRoles(loggedInUserRole);
                    List<BatchInstance> eachBatchInstance;
                    for (final BatchClass batchClass : batchClasses) {
                        // TODO : service hit should not be inside a loop.
                        // Modify the API to return list of Identifiers
                        // only, rather than complete objects.
                        eachBatchInstance = batchInstanceService.getBatchInstByBatchClass(batchClass);
                        for (final BatchInstance bi : eachBatchInstance) {
                            batchInstancesId.add(bi.getIdentifier());
                        }
                    }
                } else {
                    for (final BatchInstance bi : batchInstance) {
                        batchInstancesId.add(bi.getIdentifier());
                    }
                }
                LOGGER.info("Fetched list of batch instances from the batch instance table"
                        + " for batch classes having the given role:");
                LOGGER.info(batchInstancesId.toString());
                final List<com.ephesoft.dcma.batch.schema.BatchInstances.BatchInstance> batchInstanceList = batchInstances
                        .getBatchInstance();

                com.ephesoft.dcma.batch.schema.BatchInstances.BatchInstance batchLocal;
                for (final BatchInstance eachBatchInstance : batchInstance) {
                    if (batchInstancesId.contains(eachBatchInstance.getIdentifier())) {
                        batchLocal = new com.ephesoft.dcma.batch.schema.BatchInstances.BatchInstance();
                        batchLocal.setIdentifier(eachBatchInstance.getIdentifier());
                        batchLocal.setBatchName(eachBatchInstance.getBatchName());
                        batchLocal.setCurrentUser(eachBatchInstance.getCurrentUser());
                        batchLocal.setExecutedModules(eachBatchInstance.getExecutedModules());
                        batchLocal.setLocalFolder(eachBatchInstance.getLocalFolder());
                        batchLocal.setRemoteBatchInstanceId(eachBatchInstance.getRemoteBatchInstance() != null
                                ? eachBatchInstance.getRemoteBatchInstance().getRemoteBatchInstanceIdentifier()
                                : null);
                        batchLocal.setReviewOperatorName(eachBatchInstance.getReviewUserName());
                        batchLocal.setServerIP(eachBatchInstance.getServerIP());
                        batchLocal.setUncSubFolder(eachBatchInstance.getUncSubfolder());
                        batchLocal.setValidateOperatorName(eachBatchInstance.getValidationUserName());
                        batchInstanceList.add(batchLocal);
                    }
                }
            }
        }
        return batchInstances;
    }

    /**
     * Gets the all WorkFlow name and the module name of the Batch Class Identifier as requested by the Client in the Request
     * 
     * @param loggedInUserRole {@link Set} Roles specifed for the user
     * @param identifier {@link String} Batch Class identifier which is the Name of the Batch Class Identifier
     * @param isBatchClassViewable boolean It is t5he flag which determines that the Batch Class is Visible to the user or not
     * @return {@link Modules} All the modules and the work Flow names
     * @throws ValidationException The validation exception - in case some parameter is not valid.
     * @throws UnAuthorisedAccessException the un authorised access exception - in case user does not have access to the passed batch
     *             class.
     */
    public Modules getAllModulesWorkflowNameByBatchClass(final Set<String> loggedInUserRole,
            final String identifier, final boolean isBatchClassViewable)
            throws ValidationException, UnAuthorisedAccessException {
        final Modules modulesSchema = new Modules();
        if (CollectionUtils.isEmpty(loggedInUserRole)) {
            throw new UnAuthorisedAccessException();
        } else {
            final BatchClass batchClass = batchClassService.getBatchClassByIdentifier(identifier);
            if (batchClass != null) {
                if (isBatchClassViewable) {
                    final List<BatchClassModule> modules = batchClass.getBatchClassModules();
                    for (final BatchClassModule bcm : modules) {
                        final Module module = new Module();
                        module.setModuleName(bcm.getModule().getName());
                        module.setWorkflowName(bcm.getWorkflowName());
                        modulesSchema.getModule().add(module);
                    }
                } else {
                    throw new UnAuthorisedAccessException();
                }
            } else {
                throw new ValidationException(WebServiceConstants.INVALID_BATCH_CLASS_ID_MESSAGE + identifier,
                        createUnprocessableEntityRestError(WebServiceConstants.INVALID_BATCH_CLASS_ID_MESSAGE,
                                WebServiceConstants.INVALID_BATCH_CLASS_ID_CODE));
            }
        }
        return modulesSchema;
    }

    /**
     * This Web Service Helper restarts the batch Instance whose identifier is passed as an argument. This whill throw an exception if
     * it could not restart the Batch else would process the request and return a success/failure Message
     * 
     * @param identifier {@link String} The identity of the Batch instance Batch Instance Identifier
     * @param moduleName {@link String} name of the Module from which the batch is supposed to be restarted
     * @param loggedInUserRole {@link Set} The roles assigned to the logged in user
     * @param isSuperAdmin {@link Boolean} The flag which determines whether the user is a super admin or not
     * @return Success or error message after processing the request. Which is the information regarding the process
     * @throws UnAuthorisedAccessException When the user is not authenticated to make the request
     * @throws ValidationException When the input parameters are not validated
     * @throws InternalServerException When the Server could not process the request due to some reason or some lock acquired on the
     *             batch class
     */
    public String restartBatchInstance(final String identifier, final String moduleName,
            final Set<String> loggedInUserRole, final boolean isSuperAdmin)
            throws UnAuthorisedAccessException, ValidationException, InternalServerException {
        boolean isRestarted = false;
        String moduleWorkflowNameToRestart = null;
        if (!EphesoftStringUtil.isNullOrEmpty(moduleName)) {
            if (StringUtils.isNotBlank(identifier)) {
                boolean isSuccess = false;
                LOGGER.info("Start processing of restarting batch for batch instance:" + identifier);
                final BatchInstance batchInstance = batchInstanceService.getBatchInstanceByIdentifier(identifier);
                // only batch instance with these status can be restarted
                if (batchInstance == null) {
                    throw new ValidationException(
                            WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_MESSAGE
                                    + getAdditionalInfo(identifier),
                            createUnprocessableEntityRestError(
                                    WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_MESSAGE
                                            + getAdditionalInfo(identifier),
                                    WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_CODE));
                } else if (BatchInstanceStatus.DELETED.equals(batchInstance.getStatus())) {
                    LOGGER.error("Error response at server: "
                            + WebServiceConstants.BATCH_INSTANCE_ALREADY_DELETED_MESSAGE
                            + getAdditionalInfo(identifier));
                    throw new ValidationException(
                            WebServiceConstants.BATCH_INSTANCE_ALREADY_DELETED_MESSAGE
                                    + getAdditionalInfo(identifier),
                            createUnprocessableEntityRestError(
                                    WebServiceConstants.BATCH_INSTANCE_ALREADY_DELETED_MESSAGE
                                            + getAdditionalInfo(identifier),
                                    WebServiceConstants.BATCH_INSTANCE_ALREADY_DELETED_CODE));

                } else if (!BatchInstanceStatus.restartableStatusList().contains(batchInstance.getStatus())) {
                    throw new ValidationException(
                            WebServiceConstants.BATCH_INSTANCE_CANNOT_BE_RESTARTED_MESSAGE
                                    + getAdditionalInfo(identifier + " " + batchInstance.getStatus()),
                            createUnprocessableEntityRestError(
                                    WebServiceConstants.BATCH_INSTANCE_CANNOT_BE_RESTARTED_MESSAGE
                                            + getAdditionalInfo(identifier + " " + batchInstance.getStatus()),
                                    WebServiceConstants.BATCH_INSTANCE_CANNOT_BE_DELETED_CODE));
                } else if (StringUtils.isNotBlank(batchInstance.getCurrentUser())) {
                    // the batch is locked by some user, cannot be
                    // restarted/deleted
                    LOGGER.error("Error response at server: " + WebServiceConstants.BATCH_INSTANCE_LOCKED_MESSAGE
                            + getAdditionalInfo(identifier));
                    throw new InternalServerException(
                            WebServiceConstants.BATCH_INSTANCE_LOCKED_MESSAGE + getAdditionalInfo(identifier),
                            createUnprocessableEntityRestError(
                                    WebServiceConstants.BATCH_INSTANCE_LOCKED_MESSAGE
                                            + getAdditionalInfo(identifier),
                                    WebServiceConstants.BATCH_INSTANCE_LOCKED_CODE));
                } else {
                    LOGGER.info(
                            "Batch is in the valid state to restart.Restarting batch instance:" + batchInstance);
                    final Set<String> batchInstanceRoles = batchInstanceService
                            .getRolesForBatchInstance(batchInstance);
                    if (isSuperAdmin || batchInstanceRoles.removeAll(loggedInUserRole)) {
                        LOGGER.info("User is authorized to perform operation on the batch instance:" + identifier);
                        final String batchClassIdentifier = batchInstanceService
                                .getBatchClassIdentifier(identifier);
                        final String executedBatchInstanceModules = batchInstance.getExecutedModules();
                        // if some of the modules are already executed
                        if (StringUtils.isNotBlank(executedBatchInstanceModules)) {
                            final String[] executedModulesArray = executedBatchInstanceModules.split(";");
                            if (batchClassIdentifier != null) {
                                LOGGER.info("Restarting the batch instance for the  batch class:"
                                        + batchClassIdentifier);
                                final BatchClassModule batchClassModuleItem = batchClassModuleService
                                        .getBatchClassModuleByName(batchClassIdentifier, moduleName);
                                if (batchClassModuleItem != null) {
                                    for (final String executedModule : executedModulesArray) {
                                        if (executedModule.equalsIgnoreCase(
                                                String.valueOf(batchClassModuleItem.getModule().getId()))) {
                                            moduleWorkflowNameToRestart = batchClassModuleItem.getWorkflowName();
                                            isSuccess = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        } else {
                            // if none of the modules has executed
                            isSuccess = true;
                            final List<BatchClassModule> batchClassModuleList = batchInstance.getBatchClass()
                                    .getBatchClassModules();
                            moduleWorkflowNameToRestart = batchClassModuleList.get(0).getWorkflowName();
                            LOGGER.info("Restarting the batch from first module." + moduleWorkflowNameToRestart
                                    + " as the executed module list is empty.");
                        }
                        final boolean isZipSwitchOn = batchSchemaService.isZipSwitchOn();
                        LOGGER.info("Zipped Batch XML switch is: " + isZipSwitchOn);

                        if (isSuccess) {
                            LOGGER.info("All parameters for restarting the batch are valid.");
                            try {
                                isRestarted = processRestartingBatchInternal(identifier,
                                        moduleWorkflowNameToRestart, batchInstance, batchClassIdentifier,
                                        isZipSwitchOn);
                            } catch (final Exception exception) {
                                LOGGER.error("Error in restarting batch instance " + identifier + exception,
                                        exception);

                                // update the batch instance to ERROR state and
                                // get Exception
                                if (null != workflowService) {
                                    workflowService.handleErrorBatch(batchInstance, exception,
                                            exception.getMessage());
                                }
                            }
                        } else {
                            final List<BatchClassModule> batchClassModules = batchClassModuleService
                                    .getAllBatchClassModulesByIdentifier(batchClassIdentifier);
                            final String[] executedModulesArray = executedBatchInstanceModules.split(";");
                            final Set<String> executedWorkflows = new HashSet<String>();
                            String batchInstanceModuleName = "";
                            for (final String executedModuleId : executedModulesArray) {
                                for (final BatchClassModule batchClassModule : batchClassModules) {
                                    if (batchClassModule != null && executedModuleId.equalsIgnoreCase(
                                            String.valueOf(batchClassModule.getModule().getId()))) {
                                        batchInstanceModuleName = batchClassModule.getModule().getName();
                                        executedWorkflows.add(batchClassModule.getWorkflowName());
                                        break;
                                    }
                                }
                            }
                            final String errorMessage = WebServiceConstants.INVALID_MODULE_NAME_TO_RESTART_MESSAGE
                                    + (StringUtils.isNotBlank(batchInstanceModuleName)
                                            ? "Batch instance is currently in " + batchInstanceModuleName
                                                    + " state. It cannot be restarted from " + moduleName
                                            : "");
                            LOGGER.error("Error response at server:" + errorMessage);
                            throw new ValidationException(errorMessage, createUnprocessableEntityRestError(
                                    errorMessage, WebServiceConstants.INVALID_MODULE_NAME_TO_RESTART_CODE));
                        }
                    } else {
                        throw new UnAuthorisedAccessException();
                    }
                }
            } else {
                throw new ValidationException(WebServiceConstants.NO_INSTANCE_NAME,
                        createUnprocessableEntityRestError(WebServiceConstants.NO_INSTANCE_NAME,
                                WebServiceConstants.NO_INSTANCE_NAME_CODE));
            }
            if (!isRestarted) {
                throw new InternalServerException(WebServiceConstants.MODULE_CANNOT_BE_RESTARTED_MESSAGE,
                        createUnprocessableEntityRestError(WebServiceConstants.MODULE_CANNOT_BE_RESTARTED_MESSAGE,
                                WebServiceConstants.MODULE_CANNOT_BE_RESTARTED_CODE));
            }
        } else {
            throw new ValidationException(WebServiceConstants.NO_MODULE_NAME, createUnprocessableEntityRestError(
                    WebServiceConstants.NO_MODULE_NAME, WebServiceConstants.NO_MODULE_NAME_CODE));
        }
        return WebServiceConstants.BATCH_RESTARTED_SUCCESS_MESSAGE + getAdditionalInfo(identifier);
    }

    private String getAdditionalInfo(final String info) {
        return " (" + info + "). ";
    }

    /**
     * WebService Helper which will restart all the Batched in the REVIEW and the VALIDATION phase
     * 
     * @param loggedInUserRole {@link Set} Roles assigned to the User
     * @param isSuperAdmin {@link Boolean} Flag that determines that the user is a Super Admin or not
     * @return the success/failure message defining whether the Request is processed or not and raise an exception when culdnot
     *         validate the request
     * 
     * @throws InternalServerException When could not process the Request
     */
    public String restartAllBatchInstance(final Set<String> loggedInUserRole, final boolean isSuperAdmin)
            throws InternalServerException {
        final StringBuffer successMessage = new StringBuffer(WebServiceConstants.BATCH_RESTARTED_SUCCESS_MESSAGE);
        StringBuffer failureMessage;
        boolean isRestarted = false;
        final List<BatchInstanceStatus> batchStatusList = new ArrayList<BatchInstanceStatus>();
        batchStatusList.add(BatchInstanceStatus.READY_FOR_REVIEW);
        batchStatusList.add(BatchInstanceStatus.READY_FOR_VALIDATION);
        List<BatchInstance> batchInstanceList = null;
        if (isSuperAdmin) {
            batchInstanceList = batchInstanceService.getBatchInstanceByStatusList(batchStatusList);
        } else {
            batchInstanceList = batchInstanceService.getBatchInstancesForStatusPriority(batchStatusList, null,
                    loggedInUserRole);
        }
        final boolean isZipSwitchOn = batchSchemaService.isZipSwitchOn();
        if (CollectionUtils.isNotEmpty(batchInstanceList)) {
            failureMessage = new StringBuffer(WebServiceConstants.BATCH_RESTARTED_FAIL_MESSAGE);
            for (final BatchInstance batchInstance : batchInstanceList) {
                final String batchInstanceIdentifier = batchInstance.getIdentifier();
                LOGGER.info("Restarting batch instance : " + batchInstanceIdentifier);
                final String moduleName = workflowService.getActiveModuleName(batchInstanceIdentifier);
                if (moduleName != null) {
                    try {
                        final String batchClassIdentifier = batchInstanceService
                                .getBatchClassIdentifier(batchInstanceIdentifier);
                        isRestarted = processRestartingBatchInternal(batchInstanceIdentifier, moduleName,
                                batchInstance, batchClassIdentifier, isZipSwitchOn);

                        successMessage
                                .append(EphesoftStringUtil.concatenate(WebServiceConstants.OPENING_SQUARE_BRACES,
                                        batchInstanceIdentifier, WebServiceConstants.CLOSING_SQUARE_BRACES));
                    } catch (final Exception e) {
                        failureMessage.append(batchInstanceIdentifier);
                        final RestError restError = createUnprocessableEntityRestError(
                                WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE,
                                WebServiceConstants.INTERNAL_SERVER_ERROR_CODE);
                        LOGGER.error("Error while restarting batch instance: " + batchInstanceIdentifier);
                        throw new InternalServerException(WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE,
                                restError);

                    }
                } else {
                    failureMessage.append(batchInstanceIdentifier);
                }
            }
        } else {
            failureMessage = new StringBuffer(WebServiceConstants.NO_BATCH_INSTANCE_FOUND);
        }
        return isRestarted ? successMessage.toString() : failureMessage.toString();
    }

    /**
     * Reads from the property file that can all the batch instances restart.
     * 
     * @return true if the restart all property is enabled else return false.
     */
    private boolean canRestartAllBatchInstances() {
        boolean canRestart = false;
        LOGGER.info("Reading restart_all batch instance property.");
        try {
            ApplicationConfigProperties properties = ApplicationConfigProperties.getApplicationConfigProperties();
            if (properties != null) {
                String property = properties.getProperty(WebServiceConstants.RESTART_ALL_BATCH_INSTANCE_PROPERTY);
                if (EphesoftStringUtil.isValidBooleanValue(property)) {
                    canRestart = Boolean.parseBoolean(property);
                }
            }
        } catch (IOException ioException) {
            LOGGER.error("Could not read from application-config-properties to restart");
        }
        return canRestart;
    }

    /**
     * Process restarting batch.
     * 
     * @param identifier the identifier
     * @param moduleWorkflowNameToRestart the module name
     * @param newBatchInstance the batch instance
     * @param batchClassIdentifier the batch class identifier
     * @param isZipSwitchOn the is zip switch on
     * @param activeModule the active module
     * @return true, if successful
     * @throws Exception the exception
     */
    private boolean processRestartingBatchInternal(final String identifier,
            final String moduleWorkflowNameToRestart, final BatchInstance batchInstance,
            final String batchClassIdentifier, final boolean isZipSwitchOn) throws Exception {
        boolean isRestarted = true;
        BatchInstance newBatchInstance = batchInstance;
        LOGGER.info("Inside processRestartingBatchInternal method.");
        engineService.deleteProcessInstanceByBatchInstance(batchInstance, false);
        final BatchInstanceThread batchInstanceThread = ThreadPool.getBatchInstanceThreadList(identifier);
        if (batchInstanceThread != null) {
            batchInstanceThread.remove();
            LOGGER.info("Removing the batch instance thread done successsfully.");
        }
        String executedModules = WebServiceUtil.EMPTY_STRING;
        if (moduleWorkflowNameToRestart != null) {
            LOGGER.info("Restarting the batch instance from the module:" + moduleWorkflowNameToRestart);
            final Properties properties = WebServiceUtil.fetchConfig();

            importBatchService.updateBatchFolders(properties, newBatchInstance, moduleWorkflowNameToRestart,
                    isZipSwitchOn);

            LOGGER.info("Batch folders have been updated successfully.");
            executedModules = newBatchInstance.getExecutedModules();
            if (executedModules != null && !executedModules.isEmpty()) {
                LOGGER.info("List of executed modules:" + executedModules);
                if (batchClassIdentifier != null) {
                    final BatchClassModule batchClassModuleItem = batchClassModuleService
                            .getBatchClassModuleByWorkflowName(batchClassIdentifier, moduleWorkflowNameToRestart);
                    final BatchClass batchClass = batchClassService.getBatchClassByIdentifier(batchClassIdentifier);
                    final List<BatchClassModule> batchClassModules = batchClass.getBatchClassModules();
                    if (null != batchClassModules) {
                        for (final BatchClassModule batchClassModule : batchClassModules) {
                            if (batchClassModule != null && batchClassModule.getModule() != null) {
                                if (batchClassModule.getOrderNumber() >= batchClassModuleItem.getOrderNumber()) {
                                    final String replaceText = batchClassModule.getModule().getId() + ";";
                                    executedModules = executedModules.replace(replaceText,
                                            WebServiceUtil.EMPTY_STRING);
                                }
                            }
                        }
                    }
                }
            }
            LOGGER.info("Resetted the executed modules list to :" + executedModules);
        } else {
            LOGGER.info("Restarting the batch instance from the begining.");
            importBatchService.removeFolders(newBatchInstance);
            executedModules = WebServiceUtil.EMPTY_STRING;
            LOGGER.info("Resetted the executed modules list to :" + executedModules);
        }

        newBatchInstance = batchInstanceService.getBatchInstanceByIdentifier(identifier);
        newBatchInstance.setExecutedModules(executedModules);
        newBatchInstance = batchInstanceService.merge(newBatchInstance);
        LOGGER.info("BatchInstance object updated in the database successfully.");

        if (!EphesoftStringUtil.isNullOrEmpty(moduleWorkflowNameToRestart)
                && moduleWorkflowNameToRestart.equalsIgnoreCase(WorkflowConstants.WORKFLOW_CONTINUE_CHECK)) {
            isRestarted = false;
            LOGGER.error(EphesoftStringUtil.concatenate("Error in restarting batch instance : ", identifier));
        }
        workflowService.startWorkflow(newBatchInstance.getBatchInstanceID(), moduleWorkflowNameToRestart);
        return isRestarted;
    }

    /**
     * Delete batch instance and return the Success or the error Message when it tries to process the request and raise an exception
     * when unable to process the request
     * 
     * @param identifier {@link PathVariable} The path variable which is the identifier of the batch instance to be deleted
     * @param loggedInUserRole {@link Set} Set of the roles the user is assigned to.
     * @param isSuperAdmin {@link Boolean} The flag which determines the user is SuperAdmin or not
     * @return the success/error message when process the request
     * @throws ValidationException When could not validate the input provided
     * @throws UnAuthorisedAccessException When the user is not authorized to make the request.
     * @throws InternalServerException When the request could not be processed by the server or any run time exception being generated
     * @throws DCMAApplicationException
     */
    public String deleteBatchInstance(final String identifier, final Set<String> loggedInUserRole,
            final boolean isSuperAdmin)
            throws ValidationException, UnAuthorisedAccessException, InternalServerException {
        boolean isDeleted = false;
        if (StringUtils.isNotBlank(identifier)) {
            final BatchInstance batchInstance = batchInstanceService.getBatchInstanceByIdentifier(identifier);
            // Status for which a batch can be deleted:
            if (batchInstance == null) {
                LOGGER.error(
                        "Error response at server: " + WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_MESSAGE
                                + getAdditionalInfo(identifier));
                throw new ValidationException(
                        WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_MESSAGE
                                + getAdditionalInfo(identifier),
                        createUnprocessableEntityRestError(
                                WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_MESSAGE
                                        + getAdditionalInfo(identifier),
                                WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_CODE));
            } else if (BatchInstanceStatus.DELETED.equals(batchInstance.getStatus())) {
                LOGGER.error(
                        "Error response at server: " + WebServiceConstants.BATCH_INSTANCE_ALREADY_DELETED_MESSAGE
                                + getAdditionalInfo(identifier));
                throw new ValidationException(
                        WebServiceConstants.BATCH_INSTANCE_ALREADY_DELETED_MESSAGE + getAdditionalInfo(identifier),
                        createUnprocessableEntityRestError(
                                WebServiceConstants.BATCH_INSTANCE_ALREADY_DELETED_MESSAGE
                                        + getAdditionalInfo(identifier),
                                WebServiceConstants.BATCH_INSTANCE_ALREADY_DELETED_CODE));
            } else if (!BatchInstanceStatus.restartableStatusList().contains(batchInstance.getStatus())) {
                LOGGER.error("Error response at server: "
                        + WebServiceConstants.BATCH_INSTANCE_CANNOT_BE_DELETED_MESSAGE);
                throw new ValidationException(
                        WebServiceConstants.BATCH_INSTANCE_CANNOT_BE_DELETED_MESSAGE
                                + getAdditionalInfo(identifier + " " + batchInstance.getStatus()),
                        createUnprocessableEntityRestError(
                                WebServiceConstants.BATCH_INSTANCE_CANNOT_BE_DELETED_MESSAGE
                                        + getAdditionalInfo(identifier + " " + batchInstance.getStatus()),
                                WebServiceConstants.BATCH_INSTANCE_CANNOT_BE_DELETED_CODE));
            } else if (StringUtils.isNotBlank(batchInstance.getCurrentUser())) {
                // the batch is locked by some user, cannot be restarted/deleted
                LOGGER.error("Error response at server: " + WebServiceConstants.BATCH_INSTANCE_LOCKED_MESSAGE
                        + getAdditionalInfo(identifier));
                throw new InternalServerException(
                        WebServiceConstants.BATCH_INSTANCE_LOCKED_MESSAGE + getAdditionalInfo(identifier),
                        createUnprocessableEntityRestError(
                                WebServiceConstants.BATCH_INSTANCE_LOCKED_MESSAGE + getAdditionalInfo(identifier),
                                WebServiceConstants.BATCH_INSTANCE_LOCKED_CODE));
            } else {
                final Set<String> batchInstanceRoles = batchInstanceService.getRolesForBatchInstance(batchInstance);
                if (isSuperAdmin || batchInstanceRoles.removeAll(loggedInUserRole)) {
                    LOGGER.info("Deleting the batch instance:" + identifier);

                    BatchInstanceThread batchInstanceThread = ThreadPool.getBatchInstanceThreadList(identifier);
                    if (batchInstanceThread != null) {
                        batchInstanceThread.remove();
                        try {
                            Thread.sleep(90000);
                        } catch (InterruptedException e) {
                            LOGGER.info("Unable to sleep for 90000 mili seconds.");
                        }
                    }
                    pluginPropertiesService.clearCache(identifier);
                    engineService.deleteProcessInstanceByBatchInstance(batchInstance, true);
                    batchInstance.setStatus(BatchInstanceStatus.DELETED);
                    batchInstanceService.updateBatchInstance(batchInstance);
                    batchInstanceGroupsService.deleteBatchInstanceFromGrps(identifier);
                    final File uncFile = new File(batchInstance.getUncSubfolder());
                    LOGGER.info("uncFile for the batch instance:" + uncFile);
                    if (null != uncFile) {
                        FileUtils.deleteDirectoryAndContentsRecursive(uncFile);
                        LOGGER.info("Deleted the unc folders of batch instance:" + identifier + " successfully.");
                    }
                    deleteBatchFolder(batchInstance);
                    deleteSerFile(batchInstance);
                    isDeleted = true;
                } else {
                    throw new UnAuthorisedAccessException();
                }
            }
        }
        return isDeleted ? WebServiceConstants.BATCH_DELETED_SUCCESS_MESSAGE + getAdditionalInfo(identifier)
                : WebServiceConstants.BATCH_DELETED_FAILURE_MESSAGE;
    }

    /**
     * Adds the user roles to batch instance.
     * 
     * @param identifier the batch class identifier
     * @param userRole the user role to add
     * @param isSuperAdmin the flag if user is super admin
     * @return the success or failure message.
     * @throws ValidationException the validation exception
     * @throws UnAuthorisedAccessException the un authorised access exception
     */
    public String addUserRolesToBatchInstance(final String identifier, final String userRole,
            final Boolean isSuperAdmin) throws ValidationException, UnAuthorisedAccessException {
        boolean isRoleAdded = false;
        final BatchInstance batchInstance = batchInstanceService.getBatchInstanceByIdentifier(identifier);
        final Set<String> allRoles = userConnectivityService.getAllGroups();
        if (CollectionUtils.isNotEmpty(allRoles) && allRoles.contains(userRole)) {
            if (batchInstance != null) {
                if (isSuperAdmin) {
                    batchInstanceGroupsService.addUserRolesToBatchInstanceIdentifier(identifier, userRole);
                    isRoleAdded = true;
                } else {
                    throw new UnAuthorisedAccessException();
                }
            } else {
                createAndThrowValidationException(identifier,
                        WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_CODE,
                        WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_MESSAGE);
            }
        } else {
            throw new ValidationException(WebServiceConstants.INVALID_ROLE_ERROR_MESSAGE,
                    new RestError(HttpStatus.UNPROCESSABLE_ENTITY, WebServiceConstants.INVALID_ROLE_ERROR_CODE,
                            WebServiceConstants.INVALID_ROLE_ERROR_MESSAGE,
                            WebServiceConstants.INVALID_ROLE_ERROR_MESSAGE
                                    + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                            WebServiceConstants.DEFAULT_URL));
        }
        return isRoleAdded
                ? WebServiceConstants.USER_ROLE_ADDED_SUCCESS_MESSAGE
                        + getAdditionalInfo(userRole + " added to " + identifier)
                : WebServiceConstants.USER_ROLE_ADDED_FAILURE_MESSAGE + identifier;
    }

    /**
     * Gets the batch class list defined for the User. These Batch class roles would be different for the Super Admin which would not
     * account for the deleted ones
     * 
     * @param loggedInUserRole {@link Set} nSet of roles assigned to the Logged in user
     * @param isSuperAdmin {@link Boolean} Flag that determines that the user is a super Admin or not
     * @return {@link BatchClasses} That is List representation of the {@link BatchClass}
     * @throws UnAuthorisedAccessException When the user is not authorised to make the req
     */
    public BatchClasses getBatchClassList(final Set<String> loggedInUserRole, final boolean isSuperAdmin)
            throws UnAuthorisedAccessException {
        final BatchClasses batchClasses = new BatchClasses();
        if (CollectionUtils.isNotEmpty(loggedInUserRole)) {
            List<BatchClass> batchClass = null;
            if (isSuperAdmin) {
                batchClass = batchClassService.getAllBatchClassesExcludeDeleted();
            } else {
                batchClass = batchClassService.getAllBatchClassesByUserRoles(loggedInUserRole);
            }
            final List<com.ephesoft.dcma.batch.schema.BatchClasses.BatchClass> batchClassList = batchClasses
                    .getBatchClass();
            LOGGER.info("Total batch class found from the database is : " + batchClass.size());
            com.ephesoft.dcma.batch.schema.BatchClasses.BatchClass batchClassLocal;
            for (final BatchClass eachBatchClass : batchClass) {
                batchClassLocal = createBatchClass(eachBatchClass);
                batchClassList.add(batchClassLocal);
            }
        } else {
            throw new UnAuthorisedAccessException();
        }
        return batchClasses;
    }

    /**
     * Method to perform conversion of batch class from database to xsd for web service.
     * 
     * @param eachBatchClass the each batch class
     * @return the com.ephesoft.dcma.batch.schema. batch classes. batch class
     */
    private com.ephesoft.dcma.batch.schema.BatchClasses.BatchClass createBatchClass(
            final BatchClass eachBatchClass) {
        final com.ephesoft.dcma.batch.schema.BatchClasses.BatchClass batchClassLocal = new com.ephesoft.dcma.batch.schema.BatchClasses.BatchClass();
        batchClassLocal.setCurrentUser(eachBatchClass.getCurrentUser());
        batchClassLocal.setDescription(eachBatchClass.getDescription());
        batchClassLocal.setIdentifier(eachBatchClass.getIdentifier());
        batchClassLocal.setName(eachBatchClass.getName());
        batchClassLocal.setPriority(eachBatchClass.getPriority());
        batchClassLocal.setUncFolder(eachBatchClass.getUncFolder());
        batchClassLocal.setVersion(eachBatchClass.getVersion());
        return batchClassLocal;
    }

    /**
     * The Helper method for the Web Service API which defines the working of fetching the roles on the Batch Class. It returns the
     * values of roles
     * 
     * @param identifier {@link String} The Batch Class Identifier received from the request
     * @param loggedInUserRole {@link Set} The Set of Roles defined for the User that has logged in
     * @param isSuperAdmin {@link Boolean} defines whether the user is Super-Admin or not
     * @param isBatchClassViewableToUser {@link Boolean} Defines whether the Batch is Visible to User or not
     * @return {@link ListValues} The list Values that defines the Roles as on the Batch Class Idenitifer
     * @throws ValidationException {@link ValidationException} When there is some Validation issue this Exception would be raised
     * @throws UnAuthorisedAccessException {@link UnAuthorisedAccessException} When the user is not allowed to make the request
     */
    public ListValues getRoles(final String identifier, final Set<String> loggedInUserRole,
            final boolean isSuperAdmin, final boolean isBatchClassViewableToUser)
            throws ValidationException, UnAuthorisedAccessException {
        Set<String> userGroups = null;
        if (isBatchClassViewableToUser) {
            final BatchClass batchClass = batchClassService.getBatchClassByIdentifier(identifier);
            if (batchClass != null) {
                LOGGER.info("Fetching user roles for batch class identifier" + identifier);
                userGroups = batchClassGroupsService.getRolesForBatchClass(identifier);
            } else {
                throw new ValidationException(WebServiceConstants.INVALID_BATCH_INSTANCE_STATUS_MESSAGE,
                        createUnprocessableEntityRestError(
                                WebServiceConstants.INVALID_BATCH_INSTANCE_STATUS_MESSAGE,
                                WebServiceConstants.INVALID_BATCH_INSTANCE_STATUS_CODE));
            }
        } else {
            throw new UnAuthorisedAccessException();
        }
        final ListValues list = new ListValues();
        list.getValue().addAll(userGroups);
        return list;
    }

    /**
     * This Web Service implements the functionality of uploading the Batch and creating the new BatchInstances with the name provided
     * by the user making sure that the there is no Other Batch Instance with the same name under that Batch class and as well as the
     * user has the access to that Batch Class
     * 
     * @param req {@link HttpServletRequest} The request Object encapsulated for the clients Request
     * @param batchClassIdentifier {@link String} Batch Class Identifier which uniquely Identifies the Object
     * @param batchInstanceName {@link String} Batch Instance Name that is the unique name which identifies the batch Instance
     * @param roles {@link Set} Set of the roles assigned to the user
     * @return {@link String} the Result to be displaying When the Request is executed successfully withoput generating an Exception
     * @throws ValidationException When the Input Parameters cannot be validated
     * @throws UnAuthorisedAccessException When User tries to make an access to a batch which is not under his role
     * @throws NoUserRoleException : When the user is not assigned to any role
     * @throws UnSupportedFileTypeException : When the uploaded file is not from any of the supprted file type by plugin pdf/tif/tiff
     * @throws BatchNameAlreadyExistException : The Batch With same Name aslready exist
     * @throws InternalServerException : When Some IOException Occurs at Server
     * @throws Exception When unable to process the Multi-Part Request
     */
    public String uploadBatch(final HttpServletRequest req, final String batchClassIdentifier,
            final String batchInstanceName, final Set<String> roles)
            throws ValidationException, UnAuthorisedAccessException, NoUserRoleException,
            UnSupportedFileTypeException, BatchNameAlreadyExistException, InternalServerException, Exception {
        String workingDir = WebServiceUtil.EMPTY_STRING;
        boolean isSuccess = false;
        try {
            InputStream inStream = null;
            OutputStream outStream = null;
            if (StringUtils.isBlank(batchClassIdentifier)) {
                throw new ValidationException(
                        WebServiceConstants.INVALID_BATCH_CLASS_ID_MESSAGE + batchClassIdentifier,
                        createUnprocessableEntityRestError(WebServiceConstants.INVALID_BATCH_CLASS_ID_MESSAGE,
                                WebServiceConstants.INVALID_BATCH_CLASS_ID_CODE));
            } else if (StringUtils.isBlank(batchInstanceName)) {
                throw new ValidationException(
                        WebServiceConstants.INVALID_BATCH_INSTANCE_NAME_MESSAGE + batchClassIdentifier,
                        createUnprocessableEntityRestError(WebServiceConstants.INVALID_BATCH_INSTANCE_NAME_MESSAGE,
                                WebServiceConstants.INVALID_BATCH_INSTANCE_NAME_CODE));
            } else if (req instanceof DefaultMultipartHttpServletRequest) {
                final String webServiceFolderPath = batchSchemaService.getWebServicesFolderPath();
                workingDir = WebServiceUtil.createWebServiceWorkingDir(webServiceFolderPath);
                final DefaultMultipartHttpServletRequest multiPartRequest = (DefaultMultipartHttpServletRequest) req;
                final MultiValueMap<String, MultipartFile> fileMap = multiPartRequest.getMultiFileMap();
                String uncFolderPath = WebServiceUtil.EMPTY_STRING;
                final List<File> fileList = new ArrayList<File>();
                if (CollectionUtils.isNotEmpty(roles)) {
                    final BatchClass batchClass = batchClassService.getBatchClassByUserRoles(roles,
                            batchClassIdentifier);
                    if (batchClass == null) {
                        LOGGER.error(
                                "The user does not have the authentication to run the batch in the requested batch class with id: "
                                        + batchClassIdentifier);
                        throw new UnAuthorisedAccessException();
                    } else {
                        uncFolderPath = batchClass.getUncFolder();
                    }
                } else {
                    LOGGER.error(WebServiceConstants.NO_USER_ROLE_EXCEPTION_MESSAGE);
                    throw new NoUserRoleException();
                }
                if (fileMap.size() == 0) {
                    throw new ValidationException(WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                            createUnprocessableEntityRestError(WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                                    WebServiceConstants.IMPROPER_INPUT_TO_SERVER_CODE));
                }
                for (final String srcFileName : fileMap.keySet()) {
                    if (FileType.isValidFileName(srcFileName)) {
                        final File file = new File(workingDir + File.separator + srcFileName);
                        fileList.add(file);
                        final MultipartFile multiPartFile = multiPartRequest.getFile(srcFileName);
                        inStream = multiPartFile.getInputStream();
                        outStream = new FileOutputStream(file);
                        final byte[] buf = new byte[WebServiceUtil.bufferSize];
                        int len = inStream.read(buf);
                        while (len > 0) {
                            outStream.write(buf, 0, len);
                            len = inStream.read(buf);
                        }
                        IOUtils.closeQuietly(inStream);
                        IOUtils.closeQuietly(outStream);
                    } else {
                        LOGGER.error(WebServiceConstants.UNSUPPORTED_FILE_TYPE_EXCEPTION_MESSAGE);
                        throw new UnSupportedFileTypeException();
                    }
                }
                final String filePath = workingDir + File.separator + batchInstanceName;
                final File file = new File(filePath);
                if (file.mkdir()) {
                    for (final File srcFileName : fileList) {
                        final File destFile = new File(filePath + File.separator + srcFileName.getName());
                        FileUtils.copyFile(srcFileName, destFile);
                    }
                    final File destFile = new File(uncFolderPath + File.separator + batchInstanceName);
                    if (!destFile.exists()) {
                        FileUtils.copyDirectoryWithContents(file, destFile);
                    } else {
                        LOGGER.error(WebServiceConstants.BATCH_NAME_ALREADY_EXIST_EXCEPTION_MESSAGE);
                        throw new BatchNameAlreadyExistException();
                    }
                    isSuccess = true;
                } else {
                    LOGGER.error(WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE);
                    throw new InternalServerException(WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                            createUnprocessableEntityRestError(WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                                    WebServiceConstants.IMPROPER_INPUT_TO_SERVER_CODE));
                }
            } else {
                throw new ValidationException(WebServiceConstants.INVALID_INPUT_FOR_UPLOAD_BATCH,
                        createUnprocessableEntityRestError(WebServiceConstants.INVALID_INPUT_FOR_UPLOAD_BATCH,
                                WebServiceConstants.INVALID_PARAMETERS_CODE));
            }
        } finally {
            if (!workingDir.isEmpty()) {
                FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
            }
        }
        return isSuccess ? WebServiceConstants.BATCH_UPLOADED_SUCCESS_MESSAGE
                : WebServiceConstants.BATCH_UPLOADED_FAILURE_MESSAGE;
    }

    /**
     * Function of the Helper Class which helps the web services to handle the Request of importing the Batch Class. It process the
     * request but raises an Exception when could not process the Request
     * 
     * @param httpRequest {@link HttpServletRequest} The request made by the client encapsulated as an object
     * @return success or error Message When an exception is not raised after processing the request
     * @throws ValidationException : When could not validate the input or input condition required for the request
     * @throws InternalServerException : When input is valid but server could not process the request
     * @throws Exception : In case of any un-expected Failure
     */
    public String importBatchClass(final HttpServletRequest httpRequest)
            throws ValidationException, InternalServerException, Exception {
        String workingDir = WebServiceUtil.EMPTY_STRING;
        boolean isImported = false;
        LOGGER.info("Reached Here");
        if (httpRequest instanceof DefaultMultipartHttpServletRequest) {
            InputStream instream = null;
            OutputStream outStream = null;
            final String webServiceFolderPath = batchSchemaService.getWebServicesFolderPath();
            LOGGER.info("web Service Folder Path" + webServiceFolderPath);
            final DefaultMultipartHttpServletRequest mPartReq = (DefaultMultipartHttpServletRequest) httpRequest;
            final MultiValueMap<String, MultipartFile> fileMap = mPartReq.getMultiFileMap();
            if (fileMap.size() == WebServiceConstants.IMPORT_BATCH_CLASS_FILES) {
                try {
                    workingDir = WebServiceUtil.createWebServiceWorkingDir(webServiceFolderPath);
                    LOGGER.info("Created the web service working directory successfully  :" + workingDir);
                    ImportBatchClassOptions option = null;
                    String zipFilePath = WebServiceUtil.EMPTY_STRING;
                    for (final String fileName : fileMap.keySet()) {
                        try {
                            final MultipartFile f = mPartReq.getFile(fileName);
                            instream = f.getInputStream();
                            if (fileName.toLowerCase().indexOf(FileType.XML.getExtension().toLowerCase()) > -1) {
                                final Source source = XMLUtil.createSourceFromStream(instream);
                                option = (ImportBatchClassOptions) batchSchemaDao.getJAXB2Template()
                                        .getJaxb2Marshaller().unmarshal(source);
                                continue;
                            } else if (fileName.toLowerCase()
                                    .indexOf(FileType.ZIP.getExtension().toLowerCase()) > -1) {
                                zipFilePath = workingDir + File.separator + fileName;
                                LOGGER.info("Zip file is using for importing batch class is " + zipFilePath);
                                final File file = new File(zipFilePath);
                                outStream = new FileOutputStream(file);
                                final byte[] buf = new byte[WebServiceUtil.bufferSize];
                                int len;
                                while ((len = instream.read(buf)) > 0) {
                                    outStream.write(buf, 0, len);
                                }
                                continue;
                            } else {
                                throw new ValidationException(WebServiceConstants.INVALID_FILES_SEND,
                                        createUnprocessableEntityRestError(WebServiceConstants.INVALID_FILES_SEND,
                                                WebServiceConstants.INVALID_PARAMETERS_CODE));
                            }
                        } finally {
                            IOUtils.closeQuietly(instream);
                            IOUtils.closeQuietly(outStream);
                        }
                    }
                    importBatchClassInternal(workingDir, option, zipFilePath);
                    isImported = true;
                } catch (final InternalServerException ise) {
                    throw ise;
                } catch (final ValidationException validationException) {
                    throw validationException;
                } catch (final Exception exception) {
                    exception.printStackTrace();
                    throw new InternalServerException(
                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE.concat(exception.getMessage()),
                            createUnprocessableEntityRestError(
                                    WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE
                                            .concat(exception.getMessage()),
                                    WebServiceConstants.INTERNAL_SERVER_ERROR_CODE));
                } finally {
                    FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
                }
            } else {
                final String errorMessage = "Improper input to server. Expected two files: zip and xml file. Returning without processing the results.";
                LOGGER.error("Error response at server:" + errorMessage);
                final RestError restError = createUnprocessableEntityRestError(
                        WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                        WebServiceConstants.IMPROPER_INPUT_TO_SERVER_CODE);
                LOGGER.error(errorMessage + WebServiceConstants.HTTP_STATUS + HttpStatus.INTERNAL_SERVER_ERROR);
                throw new ValidationException(
                        WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE + getAdditionalInfo(errorMessage),
                        restError);
            }
        } else {
            final String errorMessage = "Improper input to server. Expected two files: zip and xml file. Returning without processing the results.";
            LOGGER.error("Error response at server:" + errorMessage);
            final RestError restError = createUnprocessableEntityRestError(
                    WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                    WebServiceConstants.IMPROPER_INPUT_TO_SERVER_CODE);
            LOGGER.error(errorMessage + WebServiceConstants.HTTP_STATUS + HttpStatus.INTERNAL_SERVER_ERROR);
            throw new ValidationException(
                    WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE + getAdditionalInfo(errorMessage),
                    restError);
        }
        if (!workingDir.isEmpty()) {
            FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
        }
        return isImported ? WebServiceConstants.BATCH_IMPORTED_SUCCESS_MESSAGE
                : WebServiceConstants.BATCH_IMPORTED_FAILURE_MESSAGE;
    }

    /**
     * Import batch class internal. Process the request fetched from the Import Function and import the batch class using various DAO
     * Services
     * 
     * @param workingDir {@link String} The working directory of the user
     * @param option {@link ImportBatchClassOptions} The import batch class options
     * @param zipFilePath {@link String} Path to the zipped file
     * @throws IOException Signals that an I/O exception has occurred.
     * @throws ValidationException : When could not validate the input or input condition required for the request
     * @throws InternalServerException : When input is valid but server could not process the request
     */
    private void importBatchClassInternal(final String workingDir, final ImportBatchClassOptions option,
            final String zipFilePath) throws IOException, InternalServerException, ValidationException {
        LOGGER.info("Reached Batch Class Internal");
        Set<String> assignedGroups = null;
        if (option != null && !zipFilePath.isEmpty()) {
            final Map<Boolean, String> results = importBatchService.validateInputXML(option);
            final String errorMsg = results.get(Boolean.FALSE);
            if (StringUtils.isNotBlank(errorMsg)) {
                throw new InternalServerException(
                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + getAdditionalInfo(errorMsg),
                        createUnprocessableEntityRestError(
                                WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + getAdditionalInfo(errorMsg),
                                WebServiceConstants.INTERNAL_SERVER_ERROR_CODE));
            } else {
                LOGGER.info("zip file path:" + zipFilePath);
                final File tempZipFile = new File(zipFilePath);
                final String tempOutputUnZipDir = tempZipFile.getParent() + File.separator
                        + tempZipFile.getName().substring(0, tempZipFile.getName().indexOf(WebServiceUtil.DOT));
                LOGGER.info("temporary Output UnZip Directory:" + tempOutputUnZipDir);
                try {
                    FileUtils.unzip(tempZipFile, tempOutputUnZipDir);
                } catch (final Exception e) {
                    FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
                    tempZipFile.delete();
                    final String errorMessage = "Unable to unzip file. Returning without processing the results.";
                    LOGGER.error(errorMessage);
                    throw new InternalServerException(
                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + getAdditionalInfo(errorMessage),
                            createUnprocessableEntityRestError(
                                    WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE
                                            + getAdditionalInfo(errorMessage),
                                    WebServiceConstants.INTERNAL_SERVER_ERROR_CODE));
                }

                option.setZipFilePath(tempOutputUnZipDir);
                LOGGER.info("Importing batch class");

                // JIRA-Bug-11092
                if (!option.isRolesImported()) {
                    assignedGroups = userConnectivityService.getAllSuperAdminGroups();
                }
                final boolean isDeployed = deploymentService.isDeployed(option.getName());
                // final Map<Boolean, String> resultsImport =
                // importBatchService.importBatchClass(option, isDeployed, true,
                // assignedGroups);
                ImportBatchClassResultCarrier importBatchClassResultCarrier = importBatchService
                        .importBatchClass(option, isDeployed, true, assignedGroups);
                if (null != importBatchClassResultCarrier
                        && null != importBatchClassResultCarrier.getImportResults()) {
                    final Map<Boolean, String> resultsImport = importBatchClassResultCarrier.getImportResults();
                    final String errorMessgImport = resultsImport.get(Boolean.FALSE);
                    if (StringUtils.isNotBlank(errorMessgImport)) {
                        throw new InternalServerException(
                                WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE
                                        + getAdditionalInfo(errorMessgImport),
                                createUnprocessableEntityRestError(
                                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE
                                                + getAdditionalInfo(errorMessgImport),
                                        WebServiceConstants.INTERNAL_SERVER_ERROR_CODE));
                    } else {
                        final String batchClassId = resultsImport.get(Boolean.TRUE);
                        final BatchClass batchClass = batchClassService.get(batchClassId);
                        batchClassService.evict(batchClassService.getLoadedBatchClassByIdentifier(batchClassId));
                        deployBatchClass(batchClassId);
                        // if success in importing batch class and generating
                        // key,
                        // clear the HOCR files from diff folders.
                        // Adding check for use case as it has to be checked in
                        // case
                        // of Windows only.
                        if (OSUtil.isWindows() && !option.isUseKey()) {
                            try {
                                generateBatchClassLevelKey(option.getBatchClassKey(),
                                        option.getEncryptionAlgorithm(), batchClassId);
                            } catch (Exception e) {
                                RestError restError = new RestError(HttpStatus.INTERNAL_SERVER_ERROR,
                                        WebServiceConstants.INTERNAL_SERVER_ERROR_CODE, e.getMessage(),
                                        e.getMessage() + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                        WebServiceConstants.DEFAULT_URL);
                                LOGGER.error(WebServiceConstants.HTTP_STATUS + HttpStatus.UNPROCESSABLE_ENTITY);
                                InternalServerException internalServerExcpetion = new InternalServerException(
                                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
                                throw internalServerExcpetion;
                            }
                            clearFoldersAfterKeyGeneration(option);
                        }
                        LOGGER.info("Batch class with identifier:" + batchClass.getIdentifier()
                                + " imported successfully.");
                    }
                }
            }
        } else {
            LOGGER.error(WebServiceConstants.HTTP_STATUS + HttpStatus.UNPROCESSABLE_ENTITY);
            throw new ValidationException(WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                    createUnprocessableEntityRestError(WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                            WebServiceConstants.IMPROPER_INPUT_TO_SERVER_CODE));
        }
    }

    private void deployBatchClass(final String batchClassId) throws InternalServerException {
        try {
            deployNewBatchClass(batchClassId, false);
        } catch (DCMAException dcmaException) {

            RestError restError = new RestError(HttpStatus.INTERNAL_SERVER_ERROR,
                    WebServiceConstants.INTERNAL_SERVER_ERROR_CODE, dcmaException.getMessage(),
                    dcmaException.getMessage() + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                    WebServiceConstants.DEFAULT_URL);
            LOGGER.error(WebServiceConstants.HTTP_STATUS + HttpStatus.UNPROCESSABLE_ENTITY);
            InternalServerException internalServerExcpetion = new InternalServerException(
                    WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
            throw internalServerExcpetion;
        }
    }

    public void generateBatchClassLevelKey(String batchClassKey, String selectedEncryptionAlgo,
            String batchClassIdentifier) throws Exception {
        BatchClass batchClass = batchClassService.getBatchClassByIdentifier(batchClassIdentifier);
        if (null != batchClass) {
            try {
                // remove previous key present if any.
                encryptionService.removeBatchClassKey(batchClassIdentifier);
                batchClass.setEncryptionAlgorithm(encryptionService.getPrivateKeyAlgorithm(selectedEncryptionAlgo));
                batchClassService.saveOrUpdate(batchClass);
                // generate new key.
                encryptionService.generateBatchClassKey(batchClassIdentifier, batchClassKey.getBytes());
            } catch (KeyGenerationException keyGenException) {
                LOGGER.error(keyGenException.getMessage(), keyGenException);
                throw new Exception("Problem generating the key : " + keyGenException.getMessage());
            } catch (Exception exception) {
                LOGGER.error(exception.getMessage(), exception);
                throw new Exception("Problem generating the key : " + exception.getMessage());
            }
        }
    }

    private String getBatchClassLearningFolderPath(String batchClassIdentifier) {
        String learnSampleFolderPath = WebServiceConstants.EMPTY_STRING;
        learnSampleFolderPath = batchSchemaService.getSearchClassSamplePath(batchClassIdentifier, false);
        return learnSampleFolderPath;
    }

    private String getTestClassificationPath(String batchClassIdentifier) {
        StringBuilder folderPathBuilder = new StringBuilder(batchSchemaService.getBaseFolderLocation());
        folderPathBuilder.append(File.separator);
        folderPathBuilder.append(batchClassIdentifier);
        File batchClassFolder = new File(folderPathBuilder.toString());
        // The path for test classification folder is found.......
        folderPathBuilder.append(File.separator);
        folderPathBuilder.append(WebServiceConstants.TEST_CLASSIFICATION_FOLDER_NAME);
        clearFolderForHOCRFiles(folderPathBuilder.toString());
        return folderPathBuilder.toString();
    }

    private void clearFolderForHOCRFiles(String inputFilesPath) {
        if (null != inputFilesPath && !WebServiceConstants.EMPTY_STRING.equals(inputFilesPath)) {
            // remove redundant thumbnail files.
            File imageFolderPath = new File(inputFilesPath);
            if (null != imageFolderPath) {
                if (!imageFolderPath.exists()) {
                    imageFolderPath.mkdirs();
                }
                File[] listOfimages = imageFolderPath.listFiles(new CustomFileFilter(false,
                        FileType.TIF.getExtensionWithDot(), FileType.TIFF.getExtensionWithDot(),
                        FileType.PNG.getExtensionWithDot(), FileType.PDF.getExtensionWithDot()));
                if (null != listOfimages) {
                    for (File tiffFile : listOfimages) {
                        if (null != tiffFile && tiffFile.getName().contains("_th")) {
                            tiffFile.delete();
                        }
                    }
                }
                File[] listOfAllFiles = imageFolderPath.listFiles();
                if (null != listOfAllFiles) {
                    for (File file : listOfAllFiles) {
                        if (null != file) {
                            if (file.isDirectory()) {
                                clearFolderForHOCRFiles(file.getAbsolutePath());
                            } else {
                                boolean notPresent = true;
                                for (File tiffFiles : listOfimages) {
                                    if (null != tiffFiles && null != file
                                            && tiffFiles.getName().equals(file.getName())) {
                                        notPresent = false;
                                        break;
                                    }
                                }
                                if (notPresent) {
                                    file.delete();
                                }
                            }
                        }
                    }
                }
            }
        } else {
            LOGGER.info("The provided folder path is null or empty, no files for deleting.");
        }
    }

    private void clearFoldersAfterKeyGeneration(ImportBatchClassOptions option) {
        BatchClass batchClass = batchClassService.getBatchClassbyName(option.getName());
        if (null != batchClass) {
            String batchClassIdentifier = batchClass.getIdentifier();
            clearFolderForHOCRFiles(getBatchClassLearningFolderPath(batchClassIdentifier));
            // get and clear the test classification folder.
            getTestClassificationPath(batchClassIdentifier);
            // for ocring all the files present in test classification folder
            BatchClassID batchClassID = new BatchClassID(batchClassIdentifier);
            String testTableFolderPath = batchSchemaService.getTestTableFolderPath(batchClassID, true);
            clearFolderForHOCRFiles(testTableFolderPath);
            // recreating the indexes for fuzzy search
            String fuzzyDBFolderPath = batchSchemaService.getFuzzyDBIndexFolder(batchClassIdentifier, true);
            clearFolderForHOCRFiles(fuzzyDBFolderPath);
            // test extraction folder clearance and re-learning.
            String testKVExtractionFolderPath = batchSchemaService.getTestKVExtractionFolderPath(batchClassID,
                    true);
            clearFolderForHOCRFiles(testKVExtractionFolderPath);
            // test advanced extraction folder clearance and re-learning
            String testAdvKVExtractionFolderPath = batchSchemaService
                    .getTestAdvancedKvExtractionFolderPath(batchClassIdentifier, true);
            clearFolderForHOCRFiles(testAdvKVExtractionFolderPath);
        }

    }

    private void deployNewBatchClass(String identifier, boolean isGridWorkflow) throws DCMAException {
        LOGGER.info("Deploying the newly copied batch class");

        BatchClass batchClass = batchClassService.getLoadedBatchClassByIdentifier(identifier);
        renameBatchClassModules(batchClass);
        batchClass = batchClassService.merge(batchClass);
        deploymentService.createAndDeployProcessDefinition(batchClass, isGridWorkflow);
    }

    /**
     * Rename batch class modules.
     * 
     * @param batchClass the batch class
     */
    private void renameBatchClassModules(final BatchClass batchClass) {
        final String existingBatchClassIdentifier = batchClass.getIdentifier();
        for (final BatchClassModule batchClassModule : batchClass.getBatchClassModules()) {
            final String existingModuleName = batchClassModule.getModule().getName();
            final StringBuffer newWorkflowNameStringBuffer = new StringBuffer();
            newWorkflowNameStringBuffer.append(existingModuleName.replaceAll(" ", "_"));
            newWorkflowNameStringBuffer.append("_");
            newWorkflowNameStringBuffer.append(existingBatchClassIdentifier);
            batchClassModule.setWorkflowName(newWorkflowNameStringBuffer.toString());
        }
    }

    /**
     * Validates the total number of files for learning from the <code>docTypes</code>.
     * 
     * @param docTypes {@link List} of {@link DocType} which is to be validated. If null returns false.
     * @param size int total expected number of files.
     * @return true if the files count for learning in <code> doctypes </code> matches the size else false.
     */
    private boolean isValidFileCountForLearning(final List<DocType> docTypes, final int size) {
        boolean isValid = false;
        int totalFiles = 0;
        LOGGER.info(EphesoftStringUtil.concatenate("Validating the total documents with count =", size));
        if (docTypes != null) {
            for (DocType documentType : docTypes) {
                if (documentType != null) {
                    totalFiles += getFirstPageFileCount(documentType.getPageTypeFirst());
                    totalFiles += getMiddlePageFileCount(documentType.getPageTypeMiddle());
                    totalFiles += getLastPageFileCount(documentType.getPageTypeLast());
                    LOGGER.info(EphesoftStringUtil.concatenate("total file count after ",
                            documentType.getDocTypeName(), " is ", totalFiles));
                }
            }
        }
        isValid = totalFiles == size;
        return isValid;
    }

    /**
     * Returns the count of number of files in the <code>middlePage<code>
     * 
     * @param middlePage {@link PageTypeMiddle} page in which files to be counted. If NULL, returns 0.
     * @return number of files to upload in the page.
     */
    private int getMiddlePageFileCount(final PageTypeMiddle middlePage) {
        int totalFiles = 0;
        LOGGER.info(EphesoftStringUtil.concatenate("Counting files in middle page ", middlePage));
        if (middlePage != null) {
            com.ephesoft.dcma.batch.schema.UploadLearningFiles.DocType.PageTypeMiddle.FilesToBeUploaded uploadFiles = middlePage
                    .getFilesToBeUploaded();
            if (uploadFiles != null) {
                List<String> filesToUpload = uploadFiles.getFileName();
                if (filesToUpload != null) {
                    totalFiles = totalFiles + filesToUpload.size();
                }
            }
        }
        return totalFiles;
    }

    /**
     * Returns the count of number of files in the <code>lastPage<code>
     * 
     * @param middlePage {@link PageTypeLast} page in which files to be counted. If NULL, returns 0.
     * @return number of files to upload in the page.
     */
    private int getLastPageFileCount(final PageTypeLast lastPage) {
        int totalFiles = 0;
        LOGGER.info(EphesoftStringUtil.concatenate("Counting files in last page ", lastPage));
        if (lastPage != null) {
            com.ephesoft.dcma.batch.schema.UploadLearningFiles.DocType.PageTypeLast.FilesToBeUploaded uploadFiles = lastPage
                    .getFilesToBeUploaded();
            if (uploadFiles != null) {
                List<String> filesToUpload = uploadFiles.getFileName();
                if (filesToUpload != null) {
                    totalFiles = totalFiles + filesToUpload.size();
                }
            }
        }
        return totalFiles;
    }

    /**
     * Returns the count of number of files in the <code>firstPage<code>
     * 
     * @param middlePage {@link PageTypeFirst} page in which files to be counted. If NULL, returns 0.
     * @return number of files to upload in the page.
     */
    private int getFirstPageFileCount(final PageTypeFirst firstPage) {
        int totalFiles = 0;
        LOGGER.info(EphesoftStringUtil.concatenate("Counting files in first page ", firstPage));
        if (firstPage != null) {
            FilesToBeUploaded uploadFiles = firstPage.getFilesToBeUploaded();
            if (uploadFiles != null) {
                List<String> filesToUpload = uploadFiles.getFileName();
                if (filesToUpload != null) {
                    totalFiles = totalFiles + filesToUpload.size();
                }
            }
        }
        return totalFiles;
    }

    /**
     * This Method is Added to process the input provided for WebService to upload files for Learning
     * 
     * @param req the {@link HttpServletRequest} the request header for this web service hit
     * @throws InternalServerException the internal server exception
     * @throws ValidationException the validation exception
     */
    public void getUploadFilesforLearning(final HttpServletRequest req)
            throws InternalServerException, ValidationException {
        LOGGER.info("Inside getUploadFilesforLearning method");
        String respStr = WebServiceConstants.EMPTY_STRING;
        String workingDir = WebServiceConstants.EMPTY_STRING;
        String docTypeName = WebServiceConstants.EMPTY_STRING;
        String learningType = WebServiceConstants.EMPTY_STRING;
        List<String> fileNamesFirst = null;
        List<String> fileNamesMiddle = null;
        List<String> fileNamesLast = null;
        if (req instanceof DefaultMultipartHttpServletRequest) {
            try {
                final String webServiceFolderPath = batchSchemaService.getWebServicesFolderPath();
                workingDir = WebServiceUtil.createWebServiceWorkingDir(webServiceFolderPath);
                final DefaultMultipartHttpServletRequest multiPartRequest = (DefaultMultipartHttpServletRequest) req;
                final MultiValueMap<String, MultipartFile> fileMap = multiPartRequest.getMultiFileMap();
                final int fileCountValue = checkFileCountForExtentionType("xml", fileMap);
                if (fileCountValue >= 2) {
                    final HttpStatus status = HttpStatus.UNPROCESSABLE_ENTITY;
                    respStr = "There are more than 1 xml file uploaded with the request. Only 1 xml is expected";
                    final RestError restError = new RestError(status,
                            WebServiceConstants.INTERNAL_SERVER_ERROR_CODE, respStr,
                            respStr + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                            WebServiceConstants.DEFAULT_URL);
                    LOGGER.error("Error response at server:" + respStr);

                    final InternalServerException internalServerExcpetion = new InternalServerException(
                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
                    LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
                    throw internalServerExcpetion;
                }

                String xmlFileName = WebServiceConstants.EMPTY_STRING;
                xmlFileName = getXMLFile(workingDir, multiPartRequest, fileMap);
                LOGGER.info("XML file name is" + xmlFileName);
                UploadLearningFiles uploadLearningFileXML = null;
                final File xmlFile = new File(workingDir + File.separator + xmlFileName);

                final FileInputStream inputStream = new FileInputStream(xmlFile);
                final Source source = XMLUtil.createSourceFromStream(inputStream);
                uploadLearningFileXML = (UploadLearningFiles) batchSchemaDao.getJAXB2Template().getJaxb2Marshaller()
                        .unmarshal(source);
                final String inputXMLValidationRes = validateInputXMLForLearning(uploadLearningFileXML);
                if (inputXMLValidationRes.isEmpty()) {
                    String searchPathName = WebServiceConstants.EMPTY_STRING;
                    final List<DocType> docTypes = uploadLearningFileXML.getDocType();
                    if (isValidFileCountForLearning(docTypes, fileMap.size() - 1)) {
                        for (final DocType docType : docTypes) {
                            docTypeName = docType.getDocTypeName();
                            learningType = docType.getLearningType();
                            if (docType.getPageTypeFirst() != null
                                    && docType.getPageTypeFirst().getFilesToBeUploaded().getFileName() != null
                                    && !docType.getPageTypeFirst().getFilesToBeUploaded().getFileName().isEmpty()) {
                                fileNamesFirst = docType.getPageTypeFirst().getFilesToBeUploaded().getFileName();
                                if (LUCENE_SEARCH_CLASSIFICATION_TYPE.equalsIgnoreCase(learningType)) {
                                    searchPathName = EphesoftStringUtil.concatenate(
                                            batchSchemaService.getSearchClassSamplePath(
                                                    uploadLearningFileXML.getBatchClassId(), true),
                                            File.separator, docType.getDocTypeName(), File.separator, docTypeName,
                                            WebServiceConstants.FIRST_PAGE);

                                    uploadInputImagesToLearningFolder(searchPathName, workingDir, fileNamesFirst);
                                    LOGGER.info(
                                            "Sucessfully Uploaded Images for lucene-search-classification-sample");
                                } else if ("Image".equalsIgnoreCase(learningType)) {

                                    searchPathName = EphesoftStringUtil.concatenate(
                                            batchSchemaService.getImageMagickBaseFolderPath(
                                                    uploadLearningFileXML.getBatchClassId(), true),
                                            File.separator, docType.getDocTypeName(), File.separator, docTypeName,
                                            WebServiceConstants.FIRST_PAGE);
                                    uploadInputImagesToLearningFolder(searchPathName, workingDir, fileNamesFirst);
                                } else {

                                    searchPathName = EphesoftStringUtil.concatenate(
                                            batchSchemaService.getSearchClassSamplePath(
                                                    uploadLearningFileXML.getBatchClassId(), true),
                                            File.separator, docType.getDocTypeName(), File.separator, docTypeName,
                                            WebServiceConstants.FIRST_PAGE);

                                    uploadInputImagesToLearningFolder(searchPathName, workingDir, fileNamesFirst);
                                    LOGGER.info(
                                            "Sucessfully Uploaded Images for lucene-search-classification-sample");

                                    searchPathName = EphesoftStringUtil.concatenate(
                                            batchSchemaService.getImageMagickBaseFolderPath(
                                                    uploadLearningFileXML.getBatchClassId(), true),
                                            File.separator, docType.getDocTypeName(), File.separator, docTypeName,
                                            WebServiceConstants.FIRST_PAGE);

                                    uploadInputImagesToLearningFolder(searchPathName, workingDir, fileNamesFirst);
                                    LOGGER.info("Sucessfully Uploaded Images for image-classification-sample");
                                }
                            }

                            if (docType.getPageTypeMiddle() != null
                                    && docType.getPageTypeMiddle().getFilesToBeUploaded().getFileName() != null
                                    && !docType.getPageTypeMiddle().getFilesToBeUploaded().getFileName()
                                            .isEmpty()) {
                                fileNamesMiddle = docType.getPageTypeMiddle().getFilesToBeUploaded().getFileName();
                                if (LUCENE_SEARCH_CLASSIFICATION_TYPE.equalsIgnoreCase(learningType)) {

                                    searchPathName = EphesoftStringUtil.concatenate(
                                            batchSchemaService.getSearchClassSamplePath(
                                                    uploadLearningFileXML.getBatchClassId(), true),
                                            File.separator, docType.getDocTypeName(), File.separator, docTypeName,
                                            WebServiceConstants.MIDDLE_PAGE);

                                    uploadInputImagesToLearningFolder(searchPathName, workingDir, fileNamesMiddle);
                                    LOGGER.info(
                                            "Sucessfully Uploaded Images for lucene-search-classification-sample");
                                } else if ("Image".equalsIgnoreCase(learningType)) {
                                    searchPathName = EphesoftStringUtil.concatenate(
                                            batchSchemaService.getImageMagickBaseFolderPath(
                                                    uploadLearningFileXML.getBatchClassId(), true),
                                            File.separator, docType.getDocTypeName(), File.separator, docTypeName,
                                            WebServiceConstants.MIDDLE_PAGE);

                                    uploadInputImagesToLearningFolder(searchPathName, workingDir, fileNamesMiddle);
                                    LOGGER.info("Sucessfully Uploaded Images for image-classification-sample");
                                } else {

                                    searchPathName = EphesoftStringUtil.concatenate(
                                            batchSchemaService.getSearchClassSamplePath(
                                                    uploadLearningFileXML.getBatchClassId(), true),
                                            File.separator, docType.getDocTypeName(), File.separator, docTypeName,
                                            WebServiceConstants.MIDDLE_PAGE);

                                    uploadInputImagesToLearningFolder(searchPathName, workingDir, fileNamesMiddle);
                                    LOGGER.info(
                                            "Sucessfully Uploaded Images for lucene-search-classification-sample");

                                    searchPathName = EphesoftStringUtil.concatenate(
                                            batchSchemaService.getImageMagickBaseFolderPath(
                                                    uploadLearningFileXML.getBatchClassId(), true),
                                            File.separator, docType.getDocTypeName(), File.separator, docTypeName,
                                            WebServiceConstants.MIDDLE_PAGE);

                                    uploadInputImagesToLearningFolder(searchPathName, workingDir, fileNamesMiddle);
                                    LOGGER.info("Sucessfully Uploaded Images for image-classification-sample");
                                }
                            }

                            if (docType.getPageTypeLast() != null
                                    && docType.getPageTypeLast().getFilesToBeUploaded().getFileName() != null
                                    && !docType.getPageTypeLast().getFilesToBeUploaded().getFileName().isEmpty()) {
                                fileNamesLast = docType.getPageTypeLast().getFilesToBeUploaded().getFileName();
                                if (LUCENE_SEARCH_CLASSIFICATION_TYPE.equalsIgnoreCase(learningType)) {
                                    searchPathName = EphesoftStringUtil.concatenate(
                                            batchSchemaService.getSearchClassSamplePath(
                                                    uploadLearningFileXML.getBatchClassId(), true),
                                            File.separator, docType.getDocTypeName(), File.separator, docTypeName,
                                            WebServiceConstants.LAST_PAGE);

                                    uploadInputImagesToLearningFolder(searchPathName, workingDir, fileNamesLast);
                                    LOGGER.info(
                                            "Sucessfully Uploaded Images for lucene-search-classification-sample");
                                } else if ("Image".equalsIgnoreCase(learningType)) {

                                    searchPathName = EphesoftStringUtil.concatenate(
                                            batchSchemaService.getImageMagickBaseFolderPath(
                                                    uploadLearningFileXML.getBatchClassId(), true),
                                            File.separator, docType.getDocTypeName(), File.separator, docTypeName,
                                            WebServiceConstants.LAST_PAGE);

                                    uploadInputImagesToLearningFolder(searchPathName, workingDir, fileNamesLast);
                                    LOGGER.info("Sucessfully Uploaded Images for image-classification-sample");
                                } else {

                                    searchPathName = EphesoftStringUtil.concatenate(
                                            batchSchemaService.getSearchClassSamplePath(
                                                    uploadLearningFileXML.getBatchClassId(), true),
                                            File.separator, docType.getDocTypeName(), File.separator, docTypeName,
                                            WebServiceConstants.LAST_PAGE);

                                    uploadInputImagesToLearningFolder(searchPathName, workingDir, fileNamesLast);
                                    LOGGER.info(
                                            "Sucessfully Uploaded Images for lucene-search-classification-sample");

                                    searchPathName = EphesoftStringUtil.concatenate(
                                            batchSchemaService.getImageMagickBaseFolderPath(
                                                    uploadLearningFileXML.getBatchClassId(), true),
                                            File.separator, docType.getDocTypeName(), File.separator, docTypeName,
                                            WebServiceConstants.LAST_PAGE);

                                    uploadInputImagesToLearningFolder(searchPathName, workingDir, fileNamesLast);
                                    LOGGER.info("Sucessfully Uploaded Images for image-classification-sample");
                                }
                            }
                        }
                    } else {
                        final RestError restError = createUnprocessableEntityRestError(
                                WebServiceConstants.INVALID_NUMBER_OF_FILES_FOR_UPLOAD_LEARNING,
                                WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_CODE);
                        LOGGER.error("Mismatch in the XML input and files sent.");
                        throw new ValidationException(
                                WebServiceConstants.INVALID_NUMBER_OF_FILES_FOR_UPLOAD_LEARNING, restError);
                    }
                } else {
                    final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                            WebServiceConstants.PARAMETER_XML_INCORRECT_CODE, inputXMLValidationRes,
                            inputXMLValidationRes + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                            WebServiceConstants.DEFAULT_URL);
                    LOGGER.error(WebServiceConstants.PARAMETER_XML_INCORRECT_MESSAGE
                            + WebServiceConstants.HTTP_STATUS + HttpStatus.UNPROCESSABLE_ENTITY);
                    throw new InternalServerException(inputXMLValidationRes, restError);
                }

            } catch (final FileNotFoundException fe) {

                respStr = WebServiceConstants.INPUT_XML_NOT_FOUND_MESSAGE;
                final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                        WebServiceConstants.INPUT_XML_NOT_FOUND_CODE, respStr,
                        WebServiceConstants.INPUT_XML_NOT_FOUND_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                LOGGER.error("Error response at server:" + respStr);

                final InternalServerException internalServerExcpetion = new InternalServerException(
                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
                LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS);
                throw internalServerExcpetion;
            } catch (final org.xml.sax.SAXParseException ex) {

                respStr = "Error in Parsing Input XML.Please try again" + ex.getMessage();
                final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                        WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_CODE, respStr,
                        WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                LOGGER.error("Error response at server:" + respStr);

                final InternalServerException internalServerExcpetion = new InternalServerException(
                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
                LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS);
                throw internalServerExcpetion;
                // JIRA-Bug-11130
            } catch (InternalServerException internalServerException) {
                throw internalServerException;
            } catch (ValidationException validationException) {
                throw validationException;
            } catch (final Exception exception) {
                final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                respStr = WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + exception;
                final RestError restError = new RestError(status, WebServiceConstants.INTERNAL_SERVER_ERROR_CODE,
                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE,
                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                LOGGER.error("Error response at server:" + respStr);

                final InternalServerException internalServerExcpetion = new InternalServerException(
                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
                LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
                throw internalServerExcpetion;
            }

            finally {
                try {
                    if (!workingDir.isEmpty()) {
                        FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
                    }
                } catch (final Exception ex) {
                    final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                    respStr = WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + ex.getMessage();
                    final RestError restError = new RestError(status,
                            WebServiceConstants.INTERNAL_SERVER_ERROR_CODE,
                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE,
                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE
                                    + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                            WebServiceConstants.DEFAULT_URL);
                    LOGGER.error("Error response at server:" + respStr);
                    final InternalServerException internalServerExcpetion = new InternalServerException(
                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
                    LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
                    throw internalServerExcpetion;
                }
            }
        } else {
            final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
            respStr = WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE;
            final RestError restError = new RestError(status, WebServiceConstants.IMPROPER_INPUT_TO_SERVER_CODE,
                    WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                    WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE
                            + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                    WebServiceConstants.DEFAULT_URL);
            LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
            throw new InternalServerException(WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE, restError);
        }

    }

    /**
     * This Method is Used to Check Input XML for the set of Validations based on evaluation of which Learning files are uploaded
     * 
     * @param uploadLearningInputXML
     * @return
     */
    private String validateInputXMLForLearning(final UploadLearningFiles uploadLearningInputXML) {
        String errorMsg = WebServiceConstants.EMPTY_STRING;
        try {
            if (uploadLearningInputXML.getBatchClassId() != null
                    && !uploadLearningInputXML.getBatchClassId().isEmpty()) {
                final BatchClass batchClass = batchClassService
                        .getBatchClassByIdentifier(uploadLearningInputXML.getBatchClassId());
                if (batchClass == null) {
                    errorMsg = "Input batch class doesn't exists.Please enter a valid batch class";
                    return errorMsg;
                }
                final List<DocType> docTypes = uploadLearningInputXML.getDocType();
                if (docTypes != null || !docTypes.isEmpty()) {
                    for (final DocType docType : docTypes) {
                        if (docType.getDocTypeName() == null || docType.getDocTypeName().isEmpty()) {
                            errorMsg = "Input document type name is null.Please enter a document name of batch class  "
                                    + uploadLearningInputXML.getBatchClassId();
                            return errorMsg;
                        } else {
                            final boolean isValidDocName = validateDocumentName(docType.getDocTypeName(),
                                    uploadLearningInputXML.getBatchClassId());
                            if (isValidDocName) {
                                errorMsg = "Input document type name doesn't exist.Please enter a valid document name of batch class identifier  "
                                        + uploadLearningInputXML.getBatchClassId();
                                return errorMsg;
                            }
                        }
                        if (docType.getLearningType() != null && !docType.getLearningType().isEmpty()) {
                            if (!LUCENE_SEARCH_CLASSIFICATION_TYPE.equalsIgnoreCase(docType.getLearningType())
                                    && !IMAGE_CLASSIFICATION_SAMPLE_TYPE.equalsIgnoreCase(docType.getLearningType())
                                    && !"Both".equalsIgnoreCase(docType.getLearningType())) {
                                errorMsg = "Input learning type name is invalid.Please enter learning type as lucene/image/both for batch class "
                                        + uploadLearningInputXML.getBatchClassId() + " and Document name is "
                                        + docType.getDocTypeName();
                                return errorMsg;
                            } else {
                                if (docType.getPageTypeFirst() == null && docType.getPageTypeMiddle() == null
                                        && docType.getPageTypeLast() == null) {
                                    errorMsg = "Input page type name is null.Please enter at least one page type with files for batch class identifier "
                                            + uploadLearningInputXML.getBatchClassId() + " and Document Nanme is  "
                                            + docType.getDocTypeName();
                                } else {
                                    if ((docType.getPageTypeFirst().getFilesToBeUploaded().getFileName() == null
                                            || docType.getPageTypeFirst().getFilesToBeUploaded().getFileName()
                                                    .size() < 0)
                                            && (docType.getPageTypeMiddle().getFilesToBeUploaded()
                                                    .getFileName() == null
                                                    || docType.getPageTypeMiddle().getFilesToBeUploaded()
                                                            .getFileName().size() < 0)
                                            && (docType.getPageTypeLast().getFilesToBeUploaded()
                                                    .getFileName() == null
                                                    || docType.getPageTypeFirst().getFilesToBeUploaded()
                                                            .getFileName().size() < 0)) {
                                        errorMsg = "No Images available for Learning for Batch Class "
                                                + uploadLearningInputXML.getBatchClassId() + " and Document Name is"
                                                + docType.getDocTypeName();
                                        return errorMsg;
                                    } else {
                                        boolean checkPageTypeExtFirst = false;
                                        boolean checkPageTypeExtMid = false;
                                        boolean checkPageTypeExtLast = false;
                                        if (docType.getPageTypeFirst() != null
                                                && docType.getPageTypeFirst().getFilesToBeUploaded()
                                                        .getFileName() != null
                                                && docType.getPageTypeFirst().getFilesToBeUploaded().getFileName()
                                                        .size() > 0) {

                                            checkPageTypeExtFirst = checkZipOrTiffExtensions(docType
                                                    .getPageTypeFirst().getFilesToBeUploaded().getFileName());
                                        }
                                        if (docType.getPageTypeMiddle() != null
                                                && docType.getPageTypeMiddle().getFilesToBeUploaded()
                                                        .getFileName() != null
                                                && docType.getPageTypeMiddle().getFilesToBeUploaded().getFileName()
                                                        .size() > 0) {
                                            checkZipOrTiffExtensions(docType.getPageTypeMiddle()
                                                    .getFilesToBeUploaded().getFileName());
                                        }
                                        if (docType.getPageTypeLast() != null
                                                && docType.getPageTypeLast().getFilesToBeUploaded()
                                                        .getFileName() != null
                                                && docType.getPageTypeLast().getFilesToBeUploaded().getFileName()
                                                        .size() > 0) {
                                            checkPageTypeExtLast = checkZipOrTiffExtensions(
                                                    docType.getPageTypeLast().getFilesToBeUploaded().getFileName());
                                        }
                                        if (!checkPageTypeExtFirst && !checkPageTypeExtLast
                                                && !checkPageTypeExtLast) {
                                            errorMsg = "Input file type should be either tiff/tiff or ZIP folder containig tiff/tif images"
                                                    + uploadLearningInputXML.getBatchClassId()
                                                    + "and Document Name is" + docType.getDocTypeName();
                                            return errorMsg;
                                        }
                                    }
                                }
                            }
                        } else {
                            errorMsg = "Input Learning Type Name is either  Null or empty. Please Enter a Learning Type for Batch Class "
                                    + uploadLearningInputXML.getBatchClassId() + " and Document Name is "
                                    + docType.getDocTypeName();
                            return errorMsg;
                        }
                    }
                } else {
                    errorMsg = "Input Document Type is Null.Please Enter Atleast one Documument Type for Batch Class  "
                            + uploadLearningInputXML.getBatchClassId();
                    return errorMsg;
                }
            } else {
                errorMsg = "Input batch class identifier is null.Please enter a valid indentifier";
            }
        } catch (final Exception e) {
            LOGGER.error("Exception Caught in Validating input XML for upload Files for Learning" + e);
            errorMsg = "Exception Caught in Validating input XML for upload Files for Learning.Please check Logs for Details";
        }
        return errorMsg;
    }

    /**
     * This Method is Used to Unzip uploaded file to a temporary putput Location
     * 
     * @param zipFilePath
     * @param workingDir
     * @return
     * @throws InternalServerException
     */
    private String unZipToTemporaryOutputLocation(final String zipFilePath, final String workingDir)
            throws InternalServerException {
        LOGGER.info("zip file path:" + zipFilePath);
        final File tempZipFile = new File(workingDir + File.separator + zipFilePath);
        final String tempOutputUnZipDir = tempZipFile.getParent() + File.separator
                + tempZipFile.getName().substring(0, tempZipFile.getName().indexOf(WebServiceUtil.DOT));
        LOGGER.info("temporary Output UnZip Directory:" + tempOutputUnZipDir);
        try {
            FileUtils.unzip(tempZipFile, tempOutputUnZipDir);
        } catch (final Exception e) {
            FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
            tempZipFile.delete();
            final String errorMessage = "Unable to unzip file. Returning without processing the results.";
            LOGGER.error(errorMessage);
            throw new InternalServerException(
                    WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + getAdditionalInfo(errorMessage),
                    new RestError(HttpStatus.INTERNAL_SERVER_ERROR, WebServiceConstants.INTERNAL_SERVER_ERROR_CODE,
                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE,
                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE
                                    + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                            WebServiceConstants.DEFAULT_URL));
        }
        return tempOutputUnZipDir;
    }

    /**
     * This Method Takes Input List of File Names Check for their Extensions if its Zip or Tiff this Method will return True else false
     * will be returned
     * 
     * @param fileNames
     * @return boolean
     */
    private boolean checkZipOrTiffExtensions(final List<String> fileNames) {
        boolean isZippOrTiffFile = false;
        if (!fileNames.isEmpty() || fileNames != null) {
            for (final String fileName : fileNames) {
                if (fileName.toLowerCase().indexOf(FileType.TIF.getExtension().toLowerCase()) > -1
                        || fileName.toLowerCase().indexOf(FileType.ZIP.getExtension().toLowerCase()) > -1
                        || fileName.toLowerCase().indexOf(FileType.TIFF.getExtension().toLowerCase()) > -1) {
                    isZippOrTiffFile = true;
                }
            }
        }
        return isZippOrTiffFile;
    }

    /**
     * This Method takes all the File Names as Input,checks whether they are .tif/.tiff , if ZIP folder is specified all the files
     * inside Zip folder are checked for .tif/.tiff extension are are copied to searchPath Name specified
     * 
     * @param searchPathName
     * @param workingDir
     * @param fileNames
     * @throws InternalServerException
     * @throws FileNotFoundException
     */
    private void uploadInputImagesToLearningFolder(final String searchPathName, final String workingDir,
            final List<String> fileNames) throws InternalServerException {
        String respStr = "";
        try {
            for (final String fileName : fileNames) {
                if (fileName.toLowerCase().indexOf(FileType.TIFF.getExtension()) > -1
                        || fileName.toLowerCase().indexOf(FileType.TIF.getExtension()) > -1) {
                    final File saveDirectory = new File(searchPathName);
                    saveDirectory.mkdirs();
                    FileUtils.copyFile(new File(workingDir + File.separator + fileName),
                            new File(searchPathName + File.separator + fileName));
                }
                if (fileName.toLowerCase().indexOf(FileType.ZIP.getExtension()) > -1) {
                    final String unZipFileLocation = unZipToTemporaryOutputLocation(fileName, workingDir);
                    final File fPageFolder = new File(
                            unZipFileLocation + File.separator + fileName.substring(0, fileName.indexOf(".")));
                    final String[] listOfImageFiles = fPageFolder.list(new CustomFileFilter(false,
                            FileType.TIF.getExtensionWithDot(), FileType.TIFF.getExtensionWithDot()));
                    if (listOfImageFiles != null && listOfImageFiles.length > 0) {
                        for (final String imageFile : listOfImageFiles) {
                            final File saveDirectory = new File(searchPathName);
                            saveDirectory.mkdirs();
                            FileUtils.copyFile(new File(unZipFileLocation + File.separator
                                    + fileName.substring(0, fileName.indexOf(".")) + File.separator + imageFile),
                                    new File(searchPathName + File.separator + imageFile));
                        }
                    } else {
                        LOGGER.error("No Image File Exists at Location Specified " + fileName);
                        final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                        respStr = "Input file" + fileName + " is not found.Please try again ";
                        final RestError restError = new RestError(status,
                                WebServiceConstants.INPUT_FILES_NOT_FOUND_CODE, respStr,
                                WebServiceConstants.INPUT_IMAGE_NOT_FOUND_MESSAGE
                                        + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                WebServiceConstants.DEFAULT_URL);
                        LOGGER.error("Error response at server:" + respStr);
                        ;
                        if (!workingDir.isEmpty()) {
                            FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
                        }
                        final InternalServerException internalServerExcpetion = new InternalServerException(
                                WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
                        LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
                        throw internalServerExcpetion;
                    }
                }
            }
        } catch (final FileNotFoundException e) {
            final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
            respStr = "Input file is not found.Please try again";
            final RestError restError = new RestError(status, WebServiceConstants.INPUT_FILES_NOT_FOUND_CODE,
                    respStr, WebServiceConstants.INPUT_IMAGE_NOT_FOUND_MESSAGE
                            + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                    WebServiceConstants.DEFAULT_URL);
            LOGGER.error("Error response at server:" + respStr);
            if (!workingDir.isEmpty()) {
                FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
            }
            final InternalServerException internalServerExcpetion = new InternalServerException(
                    WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
            LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
            throw internalServerExcpetion;

        } catch (final Exception Ex) {
            final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
            respStr = "Error while uploading images.Please try again";
            final RestError restError = new RestError(status, WebServiceConstants.INPUT_IMAGE_NOT_ABLE_TO_UPLOAD,
                    respStr, WebServiceConstants.INPUT_IMAGE_NOT_ABLE_TO_UPLOAD_MESSAGE
                            + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                    WebServiceConstants.DEFAULT_URL);
            LOGGER.error("Error response at server:" + respStr);
            ;
            if (!workingDir.isEmpty()) {
                FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
            }
            final InternalServerException internalServerExcpetion = new InternalServerException(
                    WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
            LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
            throw internalServerExcpetion;
        }
    }

    /**
     * This method is Added to process input XML to implement auto Learning for KV feature
     * 
     * @param req the {@link HttpServletRequest} the request header for this web service hit
     * @throws InternalServerException the internal server exception
     * @throws ValidationException the validation exception
     */

    public ExtractKV processKVLearningDocType(final HttpServletRequest req)
            throws InternalServerException, ValidationException {
        final com.ephesoft.dcma.batch.schema.ExtractKV extractKV = new com.ephesoft.dcma.batch.schema.ExtractKV();

        LOGGER.info("Inside autoLearningKV method for WebService");
        String respStr = WebServiceConstants.EMPTY_STRING;
        String workingDir = WebServiceConstants.EMPTY_STRING;
        Coordinates keyRectangleCoordinates = null;
        Coordinates valueRectangleCoordinates = null;
        if (req instanceof DefaultMultipartHttpServletRequest) {
            try {
                final String webServiceFolderPath = batchSchemaService.getWebServicesFolderPath();
                workingDir = WebServiceUtil.createWebServiceWorkingDir(webServiceFolderPath);
                final DefaultMultipartHttpServletRequest multiPartRequest = (DefaultMultipartHttpServletRequest) req;
                final MultiValueMap<String, MultipartFile> fileMap = multiPartRequest.getMultiFileMap();
                if (fileMap.size() != 2) {
                    final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                    respStr = "Improper input to server. Expected two files: hocrFileZip and xml parameter file.";
                    final RestError restError = new RestError(status,
                            WebServiceConstants.IMPROPER_INPUT_TO_SERVER_CODE, respStr,
                            WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE
                                    + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                            WebServiceConstants.DEFAULT_URL);
                    LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
                    throw new InternalServerException(WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                            restError);
                }
                String xmlFileName = WebServiceConstants.EMPTY_STRING;
                xmlFileName = getXMLFile(workingDir, multiPartRequest, fileMap);
                LOGGER.info("XML file name is" + xmlFileName);
                KVExtractionDocType kvExtract = null;
                final File xmlFile = new File(workingDir + File.separator + xmlFileName);
                if (xmlFile.exists()) {
                    final FileInputStream inputStream = new FileInputStream(xmlFile);
                    final Source source = XMLUtil.createSourceFromStream(inputStream);
                    kvExtract = (KVExtractionDocType) batchSchemaDao.getJAXB2Template().getJaxb2Marshaller()
                            .unmarshal(source);
                    if (kvExtract != null) {
                        final String inputXMLValidationRes = validateInputXMLForAutoKVExtraction(kvExtract);
                        if (inputXMLValidationRes.isEmpty()) {
                            final String documentName = kvExtract.getDocumentType();

                            final BatchClass batchClass = batchClassService
                                    .getBatchClassByIdentifier(kvExtract.getBatchClass());
                            DocumentType documentType = new DocumentType();
                            final List<DocumentType> docTypes = batchClass.getDocumentTypes();
                            if (docTypes != null && !docTypes.isEmpty()) {
                                for (final DocumentType docType : docTypes) {
                                    if (documentName.equalsIgnoreCase(docType.getName())) {
                                        documentType = batchClass
                                                .getDocumentTypeByIdentifier(docType.getIdentifier());
                                    }
                                }

                            } else {
                                respStr = "Document Type doesn't Exist.Please enter a valid document type of batch class"
                                        + batchClass;
                                final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                                        WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_CODE, respStr,
                                        WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_MESSAGE
                                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                        WebServiceConstants.DEFAULT_URL);
                                LOGGER.error("Error response at server:" + respStr);
                                throw new InternalServerException(respStr, restError);
                            }
                            final List<com.ephesoft.dcma.batch.schema.HOCRFile> hocrFileList = new ArrayList<com.ephesoft.dcma.batch.schema.HOCRFile>();
                            final String hocrFileZipFileName = kvExtract.getHOCRFile();

                            final String unZipFileLocation = unZipToTemporaryOutputLocation(hocrFileZipFileName,
                                    workingDir);

                            final File fPageFolder = new File(unZipFileLocation);
                            final String[] listOfHOCRFiles = fPageFolder
                                    .list(new CustomFileFilter(false, FileType.XML.getExtensionWithDot()));
                            for (final String hocrFileName : listOfHOCRFiles) {
                                final HOCRFile hocrFile1 = new HOCRFile();
                                final HOCRFile.DocumentLevelFields dlfs = new HOCRFile.DocumentLevelFields();

                                LOGGER.info("Number of HOCR files" + listOfHOCRFiles.length);
                                List<com.ephesoft.dcma.da.domain.FieldType> fieldTypes = null;
                                if (documentType != null) {
                                    fieldTypes = documentType.getFieldTypes();
                                } else {
                                    respStr = "Document Type doesn't Exist.Please enter a valid document type of batch class"
                                            + batchClass;
                                    final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                                            WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_CODE, respStr,
                                            WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_MESSAGE
                                                    + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                            WebServiceConstants.DEFAULT_URL);
                                    LOGGER.error("Error response at server:" + respStr);
                                    throw new InternalServerException(respStr, restError);
                                }
                                if (fieldTypes != null && !fieldTypes.isEmpty()) {
                                    for (final com.ephesoft.dcma.da.domain.FieldType fieldType : fieldTypes) {
                                        final List<com.ephesoft.dcma.da.domain.KVExtraction> kvExtracttion = fieldType
                                                .getKvExtraction();
                                        final List<DocField> updtDocList = new ArrayList<DocField>(5);
                                        if (kvExtracttion != null && !kvExtracttion.isEmpty()) {
                                            for (final com.ephesoft.dcma.da.domain.KVExtraction extractKVFields : kvExtracttion) {

                                                final ExtractKVParams params = new ExtractKVParams();

                                                final OutputStream outStream = null;
                                                final InputStream instream = null;

                                                final Params paramList = new Params();
                                                if (extractKVFields.getLocationType() != null) {
                                                    paramList.setLocationType(
                                                            extractKVFields.getLocationType().toString());
                                                }
                                                if (extractKVFields.getNoOfWords() != null) {
                                                    paramList.setNoOfWords(extractKVFields.getNoOfWords());
                                                }
                                                if (extractKVFields.getKeyPattern() != null) {
                                                    paramList.setKeyPattern(extractKVFields.getKeyPattern());
                                                }
                                                if (extractKVFields.getValuePattern() != null) {
                                                    paramList.setValuePattern(extractKVFields.getValuePattern());
                                                }
                                                if (extractKVFields.getFetchValue() != null) {
                                                    paramList.setKVFetchValue(
                                                            extractKVFields.getFetchValue().toString());
                                                }

                                                // Null values are allowed
                                                paramList.setWeight(extractKVFields.getWeight());
                                                paramList.setKeyFuzziness(extractKVFields.getKeyFuzziness());

                                                if (extractKVFields.getAdvancedKVExtraction() != null) {
                                                    paramList.setLength(extractKVFields.getLength());
                                                    paramList.setWidth(extractKVFields.getWidth());
                                                    paramList.setXoffset(extractKVFields.getXoffset());
                                                    paramList.setYoffset(extractKVFields.getYoffset());
                                                    paramList.setMultiplier(Float.valueOf(1));
                                                    paramList.setAdvancedKV(true);

                                                    final AdvancedKVExtraction advancedKVExtraction = extractKVFields
                                                            .getAdvancedKVExtraction();
                                                    if (advancedKVExtraction != null) {
                                                        keyRectangleCoordinates = new Coordinates();
                                                        valueRectangleCoordinates = new Coordinates();
                                                        keyRectangleCoordinates.setX0(BigInteger
                                                                .valueOf(advancedKVExtraction.getKeyX0Coord()));
                                                        keyRectangleCoordinates.setY0(BigInteger
                                                                .valueOf(advancedKVExtraction.getKeyY0Coord()));
                                                        keyRectangleCoordinates.setX1(BigInteger
                                                                .valueOf(advancedKVExtraction.getKeyX1Coord()));
                                                        keyRectangleCoordinates.setY1(BigInteger
                                                                .valueOf(advancedKVExtraction.getKeyY1Coord()));
                                                        valueRectangleCoordinates.setX0(BigInteger
                                                                .valueOf(advancedKVExtraction.getValueX0Coord()));
                                                        valueRectangleCoordinates.setY0(BigInteger
                                                                .valueOf(advancedKVExtraction.getValueY0Coord()));
                                                        valueRectangleCoordinates.setX1(BigInteger
                                                                .valueOf(advancedKVExtraction.getValueX1Coord()));
                                                        valueRectangleCoordinates.setY1(BigInteger
                                                                .valueOf(advancedKVExtraction.getValueY1Coord()));
                                                    }

                                                }
                                                params.getParams().add(paramList);
                                                final String filePath = unZipFileLocation + File.separator
                                                        + hocrFileName;
                                                final HocrPages hocrPages = batchSchemaService.getHOCR(filePath);

                                                final boolean isSuccess = kvService.extractKVDocumentFieldsFromHOCR(
                                                        updtDocList, hocrPages, params, keyRectangleCoordinates,
                                                        valueRectangleCoordinates);
                                                // final boolean
                                                // isSuccess=kvService.extractKVFromHOCRForBatchClass(updtDocList,hocrPages,kvDocTypeLearning.getBatchClass(),kvDocTypeLearning.getDocumentType());

                                                if (!isSuccess) {
                                                    respStr = "Unable to perform KV Extraction for HOCR file"
                                                            + hocrFileName;
                                                    final RestError restError = new RestError(
                                                            HttpStatus.UNPROCESSABLE_ENTITY,
                                                            WebServiceConstants.INTERNAL_SERVER_ERROR_CODE,
                                                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE,
                                                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE
                                                                    + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                                            WebServiceConstants.DEFAULT_URL);
                                                    LOGGER.error("Error response at server:" + respStr);
                                                    throw new InternalServerException(respStr, restError);
                                                }
                                                hocrFile1.setFileName(hocrFileName);

                                            }
                                        }

                                        final DocField docField = getDocLevelField(fieldType, updtDocList);
                                        dlfs.getDocumentLevelField().add(docField);
                                    }
                                } else {
                                    respStr = "No Field Type is Defined for the document.Please try again.";
                                    final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                                            WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_CODE, respStr,
                                            WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_MESSAGE
                                                    + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                            WebServiceConstants.DEFAULT_URL);
                                    LOGGER.error("Error response at server:" + respStr);
                                    throw new InternalServerException(respStr, restError);

                                }
                                hocrFile1.setDocumentLevelFields(dlfs);
                                extractKV.getHOCRFile().add(hocrFile1);
                            }
                        } else {
                            FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
                            final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                                    WebServiceConstants.PARAMETER_XML_INCORRECT_CODE, inputXMLValidationRes,
                                    WebServiceConstants.PARAMETER_XML_INCORRECT_MESSAGE
                                            + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                    WebServiceConstants.DEFAULT_URL);
                            LOGGER.error(WebServiceConstants.PARAMETER_XML_INCORRECT_MESSAGE
                                    + WebServiceConstants.HTTP_STATUS + HttpStatus.UNPROCESSABLE_ENTITY);
                            throw new InternalServerException(inputXMLValidationRes, restError);
                        }
                    } else {
                        respStr = WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE;
                        final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                                WebServiceConstants.INPUT_FILES_NOT_FOUND_CODE,
                                WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE,
                                WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE
                                        + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                WebServiceConstants.DEFAULT_URL);
                        LOGGER.error(WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE
                                + WebServiceConstants.HTTP_STATUS + HttpStatus.UNPROCESSABLE_ENTITY);
                        throw new ValidationException(WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE, restError);
                    }
                } else {
                    respStr = WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE;
                    final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                            WebServiceConstants.INPUT_FILES_NOT_FOUND_CODE,
                            WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE,
                            WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE
                                    + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                            WebServiceConstants.DEFAULT_URL);
                    LOGGER.error(WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE + WebServiceConstants.HTTP_STATUS
                            + HttpStatus.UNPROCESSABLE_ENTITY);
                    throw new ValidationException(WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE, restError);
                }

            } catch (final ValidationException validationException) {
                throw validationException;
            } catch (final InternalServerException internalServerError) {
                throw internalServerError;
            } catch (final java.io.FileNotFoundException ex) {
                respStr = "Input File not found.Please check logs for Exception";
                final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                        WebServiceConstants.INPUT_FILES_NOT_FOUND_CODE,
                        WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE,
                        WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                LOGGER.error(WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE + WebServiceConstants.HTTP_STATUS
                        + HttpStatus.UNPROCESSABLE_ENTITY + ex);
                throw new ValidationException(respStr, restError);
            } catch (final org.xml.sax.SAXParseException Ex) {
                respStr = "Error in Parsing Input XML.Please try again";
                final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                        WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_CODE, respStr,
                        WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                LOGGER.error("Error response at server:" + respStr);
                if (!workingDir.isEmpty()) {
                    FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
                }
                final InternalServerException internalServerExcpetion = new InternalServerException(
                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
                LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS);
                throw internalServerExcpetion;

            } catch (final Exception exception) {
                final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                respStr = WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + exception;
                final RestError restError = new RestError(status, WebServiceConstants.INTERNAL_SERVER_ERROR_CODE,
                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE,
                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                LOGGER.error("Error response at server:" + respStr);
                if (!workingDir.isEmpty()) {
                    FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
                }
                final InternalServerException internalServerExcpetion = new InternalServerException(
                        WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
                LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
                throw internalServerExcpetion;
            }
        }

        else {
            final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
            respStr = WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE;
            final RestError restError = new RestError(status, WebServiceConstants.IMPROPER_INPUT_TO_SERVER_CODE,
                    WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                    WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE
                            + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                    WebServiceConstants.DEFAULT_URL);
            LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
            throw new InternalServerException(WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE, restError);
        }
        if (!workingDir.isEmpty()) {
            FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
        }
        return extractKV;
    }

    private DocField getDocLevelField(final com.ephesoft.dcma.da.domain.FieldType fieldType,
            final List<DocField> updtDocList) {
        LOGGER.info("Getting DLF according to the defined KV rules");
        DocField finalDocField = null;

        final String fieldTypeName = fieldType.getName();
        final int fieldorderNumber = fieldType.getFieldOrderNumber();
        final String fieldDataType = fieldType.getDataType().toString();
        if (null != fieldType && !CollectionUtil.isEmpty(updtDocList)) {
            final AlternateValues finalAlternateValues = new AlternateValues();
            final List<Field> alternateValue = finalAlternateValues.getAlternateValue();
            float maxConf = 0;
            Field maxField = null;
            float confidence = 0;
            Field field = null;
            AlternateValues alternateValues = null;
            List<Field> alternateSubList = null;

            // to add other extracted DLF in the alternate tag
            for (DocField docField : updtDocList) {
                alternateValues = docField.getAlternateValues();
                if (null != alternateValues) {
                    alternateSubList = alternateValues.getAlternateValue();
                    for (Field alternateField : alternateSubList) {
                        alternateField.setName(fieldTypeName);
                        alternateField.setType(fieldTypeName);
                        alternateField.setFieldOrderNumber(fieldorderNumber);
                    }
                    alternateValue.addAll(alternateSubList);
                    docField.setAlternateValues(null);
                }

                docField.setName(fieldTypeName);
                docField.setFieldOrderNumber(fieldorderNumber);
                docField.setType(fieldDataType);
                field = convertDocFieldToField(docField, fieldorderNumber, fieldDataType);

                alternateValue.add(field);
                confidence = docField.getConfidence();
                if (maxConf < confidence) {
                    maxConf = confidence;
                    maxField = field;
                    finalDocField = docField;
                }
            }

            alternateValue.remove(maxField);
            if (null != finalDocField) {
                finalDocField.setAlternateValues(finalAlternateValues);
            }
        }

        if (null == finalDocField) {
            finalDocField = new DocField();
            finalDocField.setConfidence(0f);
            finalDocField.setOcrConfidence(0f);
            finalDocField.setOcrConfidenceThreshold(0f);
            finalDocField.setValue(WebServiceUtil.EMPTY_STRING);
            finalDocField.setPage(WebServiceUtil.EMPTY_STRING);
            finalDocField.setFieldOrderNumber(fieldorderNumber);
            finalDocField.setType(fieldDataType);
            finalDocField.setForceReview(Boolean.FALSE);
            // finalDocField.setCategory("Uncategorised");
            finalDocField.setCategory(CategoryType.GROUP_1.getCategoryName());
            finalDocField.setOverlayedImageFileName(WebServiceUtil.EMPTY_STRING);
        }

        finalDocField.setName(fieldTypeName);
        return finalDocField;
    }

    private Field convertDocFieldToField(final DocField docField, int fieldorderNumber, String fieldDataType) {
        final Field field = new Field();
        field.setName(docField.getName());
        field.setPage(docField.getPage());
        field.setValue(docField.getValue());
        field.setConfidence(docField.getConfidence());
        field.setCoordinatesList(docField.getCoordinatesList());
        field.setFieldOrderNumber(docField.getFieldOrderNumber());
        field.setForceReview(Boolean.FALSE);
        field.setFieldOrderNumber(fieldorderNumber);
        field.setType(fieldDataType);
        return field;
    }

    /**
     * This Method is used to check input XML for for set to validations based on evaluation of which AutoLearning is performed
     * 
     * @param Input XML on which Validation is performed
     * @return If input XML violates any constraint then Error message is returned else empty string is returned
     */

    private String validateInputXMLForAutoKVExtraction(final KVExtractionDocType autoLearningKV) {
        String errorMsg = WebServiceConstants.EMPTY_STRING;
        try {
            if (autoLearningKV.getBatchClass() != null && !autoLearningKV.getBatchClass().isEmpty()) {
                final BatchClass batchClass = batchClassService
                        .getBatchClassByIdentifier(autoLearningKV.getBatchClass());
                if (batchClass == null) {
                    return errorMsg;
                }
                if (autoLearningKV.getDocumentType() != null && !autoLearningKV.getDocumentType().isEmpty()) {
                    final boolean isValidDocName = validateDocumentName(autoLearningKV.getDocumentType(),
                            autoLearningKV.getBatchClass());
                    if (!isValidDocName) {
                        final String hocrFileNameZip = autoLearningKV.getHOCRFile();
                        if (hocrFileNameZip == null || hocrFileNameZip.isEmpty()) {
                            errorMsg = "Input HOCR Files is null.Please enter a ZIP file containing HOCR Files and try again";
                            return errorMsg;
                        }
                    } else {
                        errorMsg = "Input document type name doesn't exist.Please enter a valid document name of batch class identifier "
                                + autoLearningKV.getBatchClass();
                        return errorMsg;
                    }
                } else {
                    errorMsg = "Input Document Type is null.Please enter a valid Document Type";
                    return errorMsg;
                }
            } else {
                errorMsg = "Input batch class identifier is null.Please enter a valid identifier";
            }
        } catch (final Exception ex) {
            LOGGER.error("Error in Validating Input XML, Exception Caught is " + ex.getMessage() + "'\n'" + "Reason"
                    + ex);
            errorMsg = "Exception Caught in Validating input XML for upload Files for Learning.Please check Logs for Details";
        }
        return errorMsg;
    }

    /**
     * This Method contains functionality to copy document type of batch Class passed as an input
     * 
     * @param req {@link HttpServletRequest} the request header for this web service hit
     * @param resp {@link HttpServletResponse} the response header for this web service.
     */
    public void processCopyDocumentType(final HttpServletRequest req)
            throws InternalServerException, ValidationException {
        {
            LOGGER.info("Processing Copy Document Type for Batch Class Web Service.");
            String respStr = WebServiceUtil.EMPTY_STRING;
            String workingDir = WebServiceUtil.EMPTY_STRING;
            DocumentType existingDoctype = new DocumentType();
            if (req instanceof DefaultMultipartHttpServletRequest) {
                try {
                    final String webServiceFolderPath = batchSchemaService.getWebServicesFolderPath();
                    workingDir = WebServiceUtil.createWebServiceWorkingDir(webServiceFolderPath);

                    final DefaultMultipartHttpServletRequest multiPartRequest = (DefaultMultipartHttpServletRequest) req;
                    final MultiValueMap<String, MultipartFile> fileMap = multiPartRequest.getMultiFileMap();
                    String xmlFileName = WebServiceConstants.EMPTY_STRING;
                    LOGGER.info("Retreiving xml file.");
                    CopyDocumentType copyDocType = null;
                    xmlFileName = getXMLFile(workingDir, multiPartRequest, fileMap);
                    LOGGER.info("XML file name is" + xmlFileName);
                    final File xmlFile = new File(workingDir + File.separator + xmlFileName);
                    if (xmlFile.exists()) {
                        final FileInputStream inputStream = new FileInputStream(xmlFile);
                        final Source source = XMLUtil.createSourceFromStream(inputStream);
                        copyDocType = (CopyDocumentType) batchSchemaDao.getJAXB2Template().getJaxb2Marshaller()
                                .unmarshal(source);
                        if (copyDocType != null && respStr.isEmpty()) {
                            // Create Method to Validate Input XML
                            respStr = validateCopyDocTypeInputXML(copyDocType);

                            if (respStr.isEmpty()) {
                                final DocumentType newDocumentType = new DocumentType();
                                final BatchClass batchClass = batchClassService
                                        .getBatchClassByIdentifier(copyDocType.getBatchClassId());
                                final List<DocumentType> documentList = batchClass.getDocumentTypes();
                                if (documentList != null) {
                                    for (final DocumentType docType : documentList) {
                                        if (docType.getName().equals(copyDocType.getExistingDocTypeName())) {
                                            existingDoctype = batchClass
                                                    .getDocumentTypeByIdentifier(docType.getIdentifier());
                                        }
                                    }
                                }
                                newDocumentType.setName(copyDocType.getNewDocumentType().getName());
                                newDocumentType.setDescription(copyDocType.getNewDocumentType().getDescription());
                                newDocumentType.setMinConfidenceThreshold(Float
                                        .parseFloat(copyDocType.getNewDocumentType().getConfidenceThreshold()));
                                if (existingDoctype.getFirstPageProjectFileName() != null) {
                                    newDocumentType.setFirstPageProjectFileName(
                                            existingDoctype.getFirstPageProjectFileName());
                                }
                                if (existingDoctype.getSecondPageProjectFileName() != null) {
                                    newDocumentType.setFirstPageProjectFileName(
                                            existingDoctype.getSecondPageProjectFileName());
                                }
                                if (existingDoctype.getThirdPageProjectFileName() != null) {
                                    newDocumentType.setFirstPageProjectFileName(
                                            existingDoctype.getThirdPageProjectFileName());
                                }
                                if (existingDoctype.getFourthPageProjectFileName() != null) {
                                    newDocumentType.setFirstPageProjectFileName(
                                            existingDoctype.getFourthPageProjectFileName());
                                }
                                docTypeService.copyDocumentType(existingDoctype, newDocumentType);
                                batchClass.addDocumentType(newDocumentType);
                                batchClassService.merge(batchClass);
                            } else {
                                final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                                        WebServiceConstants.PARAMETER_XML_INCORRECT_CODE, respStr,
                                        WebServiceConstants.PARAMETER_XML_INCORRECT_MESSAGE
                                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                        WebServiceConstants.DEFAULT_URL);
                                LOGGER.error(WebServiceConstants.PARAMETER_XML_INCORRECT_MESSAGE
                                        + WebServiceConstants.HTTP_STATUS + HttpStatus.UNPROCESSABLE_ENTITY);
                                throw new InternalServerException(respStr, restError);
                            }
                        } else {
                            respStr = WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE;
                            final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                                    WebServiceConstants.INPUT_FILES_NOT_FOUND_CODE,
                                    WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE,
                                    WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE
                                            + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                    WebServiceConstants.DEFAULT_URL);
                            LOGGER.error(WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE
                                    + WebServiceConstants.HTTP_STATUS + HttpStatus.UNPROCESSABLE_ENTITY);
                            throw new ValidationException(WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE,
                                    restError);
                        }
                    } else {
                        respStr = WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE;
                        final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                                WebServiceConstants.INPUT_FILES_NOT_FOUND_CODE,
                                WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE,
                                WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE
                                        + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                                WebServiceConstants.DEFAULT_URL);
                        LOGGER.error(WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE
                                + WebServiceConstants.HTTP_STATUS + HttpStatus.UNPROCESSABLE_ENTITY);
                        throw new ValidationException(WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE, restError);

                    }
                } catch (final XmlMappingException xmle) {
                    respStr = "Error in mapping input XML. Please send it in the specified format.";
                    final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY,
                            WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_CODE, respStr,
                            WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_MESSAGE
                                    + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                            WebServiceConstants.DEFAULT_URL);
                    LOGGER.error(WebServiceConstants.INPUT_XML_NOT_ABLE_TO_PARSE_MESSAGE
                            + WebServiceConstants.HTTP_STATUS + HttpStatus.UNPROCESSABLE_ENTITY);
                    throw new ValidationException(WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE, restError);

                } catch (final ValidationException validationException) {
                    throw validationException;
                } catch (final InternalServerException internalServerError) {
                    throw internalServerError;
                } catch (final Exception exception) {
                    final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                    respStr = WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + exception;
                    final RestError restError = new RestError(status,
                            WebServiceConstants.INTERNAL_SERVER_ERROR_CODE,
                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE,
                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE
                                    + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                            WebServiceConstants.DEFAULT_URL);
                    LOGGER.error("Error response at server:" + respStr);

                    final InternalServerException internalServerExcpetion = new InternalServerException(
                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE, restError);
                    LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
                    throw internalServerExcpetion;
                } finally {
                    FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
                }
            } else {
                final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                respStr = WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE;
                final RestError restError = new RestError(status, WebServiceConstants.IMPROPER_INPUT_TO_SERVER_CODE,
                        WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE,
                        WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE
                                + WebServiceConstants.CLASS_WEB_SERVICE_UTILITY,
                        WebServiceConstants.DEFAULT_URL);
                LOGGER.error(respStr + WebServiceConstants.HTTP_STATUS + status);
                throw new InternalServerException(WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE, restError);
            }
        }
    }

    /**
     * This Method is added to validate input XML
     * 
     * @param copyDocType contaiOns input values for copying a document type
     * @return string containing result of validation of input XML
     */
    private String validateCopyDocTypeInputXML(final CopyDocumentType copyDocType) {
        String respStr = WebServiceUtil.EMPTY_STRING;
        final String batchClassId = copyDocType.getBatchClassId();
        if (batchClassId != null & !batchClassId.isEmpty()) {
            final BatchClass batchClass = batchClassService.getBatchClassByIdentifier(batchClassId);
            if (batchClass != null) {
                // Validate new document type name already doesn't exist for
                // batchClass
                final List<DocumentType> documentList = batchClass.getDocumentTypes();
                boolean isNewDocTypeNameUnique = true;
                boolean isNewDocTypeDescUnique = true;
                boolean isDocTypeExist = false;
                final String newDocTypeName = copyDocType.getNewDocumentType().getName();
                final String existingdocTypeName = copyDocType.getExistingDocTypeName();
                if (documentList != null) {
                    for (final DocumentType docType : documentList) {
                        if (existingdocTypeName != null && existingdocTypeName.equals(docType.getName())) {
                            isDocTypeExist = true;
                            break;
                        }
                    }
                    for (final DocumentType docTypeList : documentList) {
                        if (newDocTypeName != null && newDocTypeName.equals(docTypeList.getName())) {
                            isNewDocTypeNameUnique = false;
                            break;
                        }
                    }
                }
                if (!isDocTypeExist) {
                    respStr = "Input document type to be copied doesn't exist.Please enter Valid Document type name for batch class"
                            + batchClassId;
                }
                if (respStr.isEmpty() && !isNewDocTypeNameUnique) {
                    respStr = "Name entered for new Doc Type already exist.Please enter a unique document name";
                }
                if (respStr.isEmpty() && (copyDocType.getNewDocumentType().getDescription().isEmpty()
                        || copyDocType.getNewDocumentType().getDescription() == null)) {
                    respStr = "Description for new Doc Type is Empty.Please enter description for new Document type";
                }
                if (respStr.isEmpty() && !isNewDocTypeDescUnique) {
                    respStr = "Description entered for new Doc Type already exist.Please enter a unique document type description.";
                }
                try {
                    final float confidenceThreshold = Float
                            .parseFloat(copyDocType.getNewDocumentType().getConfidenceThreshold());
                    if (confidenceThreshold < 0.0 || confidenceThreshold > 100.0) {
                        respStr = "Please enter confidence threshold value between 0.0 to 100.0 for new document type";
                    }
                } catch (final Exception ex) {
                    respStr = "Confidence threshold should be a number for new doc type between 0.0 to 100.0";
                }
            } else {
                respStr = "Batch Class Identifer doesn't exist.Please enter a valid batchClassId";
            }

        } else {
            respStr = "Batch Class Identifer is empty.Please enter a valid batchClassId";
        }
        return respStr;
    }

    public void processCreateHOCRXML(final HttpServletRequest req, final HttpServletResponse resp)
            throws InternalServerException, ValidationException {
        LOGGER.info("Start processing web service for create HOCR-XML for Batch Class");
        String respStr = WebServiceUtil.EMPTY_STRING;
        String workingDir = WebServiceUtil.EMPTY_STRING;
        File zipInFolder = null;
        File zipOutFolder = null;
        int responseCode = 0;
        WebServiceParams webServiceParams = null;
        if (req instanceof DefaultMultipartHttpServletRequest) {
            try {
                final String webServiceFolderPath = batchSchemaService.getWebServicesFolderPath();
                workingDir = WebServiceUtil.createWebServiceWorkingDir(webServiceFolderPath);
                final String outputDir = WebServiceUtil.createWebServiceOutputDir(workingDir);
                final DefaultMultipartHttpServletRequest multiPartRequest = (DefaultMultipartHttpServletRequest) req;
                final MultiValueMap<String, MultipartFile> fileMap = multiPartRequest.getMultiFileMap();
                if (fileMap.size() != 2) {
                    LOGGER.error("Invalid Number of files sent to the server");
                    respStr = WebServiceConstants.INVALID_ARGUMENTS_FOR_CREATE_HOCR;
                    responseCode = WebServiceConstants.INVALID_PARAMETERS_CODE;
                } else {
                    String xmlFileName = WebServiceUtil.EMPTY_STRING;
                    String zipOutputLocation = WebServiceUtil.EMPTY_STRING;
                    String zipFileNameWithOutExt = WebServiceUtil.EMPTY_STRING;
                    for (final String fileName : fileMap.keySet()) {
                        InputStream instream = null;
                        OutputStream outStream = null;
                        ZipInputStream zipstream = null;
                        try {

                            if (!(fileName.endsWith(FileType.ZIP.getExtensionWithDot())
                                    || fileName.endsWith(FileType.XML.getExtensionWithDot())
                                    || fileName.endsWith(FileType.TIF.getExtensionWithDot())
                                    || fileName.endsWith(FileType.TIFF.getExtensionWithDot()))) {
                                respStr = WebServiceConstants.INVALID_ARGUMENTS_FOR_CREATE_OCR_BATCH_CLASS;
                                responseCode = WebServiceConstants.INVALID_PARAMETERS_CODE;
                            }
                            final MultipartFile multiPartFile = multiPartRequest.getFile(fileName);
                            instream = multiPartFile.getInputStream();

                            if (fileName.endsWith(FileType.XML.getExtensionWithDot())) {
                                xmlFileName = fileName;
                                final File file = new File(workingDir + File.separator + fileName);
                                outStream = new FileOutputStream(file);
                                final byte[] buf = new byte[WebServiceUtil.bufferSize];
                                int len;
                                while ((len = instream.read(buf)) > 0) {
                                    outStream.write(buf, 0, len);
                                }
                            }
                            if (fileName.endsWith(FileType.ZIP.getExtensionWithDot())) {
                                zipFileNameWithOutExt = FilenameUtils.removeExtension(fileName);
                                zipInFolder = new File(workingDir + File.separator + zipFileNameWithOutExt);
                                if (zipInFolder != null) {
                                    zipInFolder.mkdirs();
                                }
                                zipstream = new ZipInputStream(instream);
                                ZipEntry ze = zipstream.getNextEntry();
                                if (ze == null) {
                                    respStr = WebServiceConstants.NO_FILES_IN_ZIP_DIR;
                                    responseCode = WebServiceConstants.NO_FILES_IN_ZIP_DIR_CODE;
                                    LOGGER.error(respStr + " No files in the zip directory ");
                                }
                                while (ze != null) {
                                    String upzipFileName = ze.getName();
                                    LOGGER.info("Unzipping " + upzipFileName);

                                    if (!(upzipFileName.endsWith(FileType.TIF.getExtensionWithDot())
                                            || upzipFileName.endsWith(FileType.TIFF.getExtensionWithDot())
                                            || upzipFileName.endsWith(FileType.PDF.getExtensionWithDot()))) {
                                        respStr = WebServiceConstants.UNSUPPORTED_FILE_TYPE_EXCEPTION_MESSAGE;
                                        responseCode = WebServiceConstants.UNSUPPORTED_FILE_TYPE_EXCEPTION_CODE;
                                        LOGGER.error("File name should be a valid tif, tiff or pdf file name only");
                                    }
                                    final File filePath = new File(zipInFolder + File.separator + upzipFileName);
                                    outStream = new FileOutputStream(filePath);
                                    final byte[] buf = new byte[WebServiceUtil.bufferSize];
                                    int len;
                                    while ((len = zipstream.read(buf)) > 0) {
                                        outStream.write(buf, 0, len);
                                    }
                                    final int pageCount = TIFFUtil
                                            .getTIFFPageCount(zipInFolder + File.separator + upzipFileName);
                                    if (pageCount > 1
                                            || upzipFileName.endsWith(FileType.PDF.getExtensionWithDot())) {
                                        final BatchInstanceThread threadList = new BatchInstanceThread(
                                                new File(zipInFolder.toString()).getName() + Math.random());
                                        LOGGER.info(
                                                "Start spliting multipage tiff/pdf file into tiffs using image magick");
                                        imService.convertPdfOrMultiPageTiffToTiffUsingIM("", filePath, "",
                                                new File(EphesoftStringUtil.concatenate(zipInFolder.toString(),
                                                        File.separator, upzipFileName)),
                                                threadList);
                                        threadList.execute();
                                    }
                                    ze = zipstream.getNextEntry();
                                }
                            }
                            if (fileName.endsWith(FileType.TIFF.getExtensionWithDot())
                                    || fileName.endsWith(FileType.TIF.getExtensionWithDot())) {
                                zipFileNameWithOutExt = WebServiceUtil.EMPTY_STRING;
                                final File file = new File(workingDir + File.separator + fileName);
                                zipInFolder = new File(workingDir);
                                outStream = new FileOutputStream(file);
                                final byte[] buf = new byte[WebServiceUtil.bufferSize];
                                int len;
                                while ((len = instream.read(buf)) > 0) {
                                    outStream.write(buf, 0, len);
                                }
                                final int pageCount = TIFFUtil
                                        .getTIFFPageCount(workingDir + File.separator + fileName);
                                if (pageCount > 1) {
                                    final BatchInstanceThread threadList = new BatchInstanceThread(
                                            zipInFolder.getName() + Math.random());
                                    LOGGER.info(
                                            "Start spliting multipage tiff/pdf file into tiffs using image magick");
                                    imService.convertPdfOrMultiPageTiffToTiffUsingIM(WebServiceUtil.EMPTY_STRING,
                                            file, WebServiceUtil.EMPTY_STRING, new File(EphesoftStringUtil
                                                    .concatenate(workingDir.toString(), File.separator, fileName)),
                                            threadList);
                                    threadList.execute();
                                }
                            }
                        } finally {
                            IOUtils.closeQuietly(instream);
                            IOUtils.closeQuietly(outStream);
                            IOUtils.closeQuietly(zipstream);
                        }
                    }
                    final File xmlFile = new File(workingDir + File.separator + xmlFileName);
                    if (StringUtils.isNotEmpty(xmlFileName) && xmlFile.exists()) {
                        final FileInputStream inputStream = new FileInputStream(xmlFile);
                        final Source source = XMLUtil.createSourceFromStream(inputStream);
                        final Object unmarshelledObject = batchSchemaDao.getJAXB2Template().getJaxb2Marshaller()
                                .unmarshal(source);
                        if (!(unmarshelledObject instanceof WebServiceParams)) {
                            respStr = WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_MESSAGE;
                            responseCode = WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_CODE;
                        } else {
                            webServiceParams = (WebServiceParams) unmarshelledObject;
                            if (null != webServiceParams.getParams()) {
                                final List<Param> paramList = webServiceParams.getParams().getParam();
                                if (paramList == null || paramList.isEmpty()) {
                                    final HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
                                    respStr = WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_MESSAGE;
                                    responseCode = WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_CODE;
                                    LOGGER.error(respStr + "\n No Parameters in the request" + status);
                                } else {
                                    String batchClassId = WebServiceUtil.EMPTY_STRING;
                                    for (final Param param : paramList) {
                                        if (WebServiceConstants.BATCH_CLASS_IDENTIFIER
                                                .equalsIgnoreCase(param.getName())) {
                                            batchClassId = param.getValue();
                                            continue;
                                        }
                                        if (WebServiceUtil.ZIP_OUTPUT_LOCATION.equalsIgnoreCase(param.getName())) {
                                            zipOutputLocation = param.getValue();
                                            if (StringUtils.isBlank(zipOutputLocation)
                                                    || !(new File(zipOutputLocation).isDirectory())) {
                                                respStr = WebServiceConstants.ZIP_OUTPUT_LOCATION_INVALID_MESSAGE;
                                                responseCode = WebServiceConstants.ZIP_OUTPUT_LOCATION_INVALID_CODE;
                                                LOGGER.error(
                                                        "Zip output location is blank or invalid in xml input file");
                                            }
                                            continue;
                                        }
                                        if (WebServiceUtil.ZIP_NAME.equalsIgnoreCase(param.getName())) {
                                            if (!((zipFileNameWithOutExt + FileType.ZIP.getExtensionWithDot())
                                                    .equals(param.getValue()))) {
                                                respStr = WebServiceConstants.INPUT_ZIP_NOT_FOUND_MESSAGE;
                                                responseCode = WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_CODE;
                                                LOGGER.error(
                                                        "Zip file name doesn't match zip file name in xml input file");
                                            } else
                                                continue;
                                        }
                                    }
                                    if (respStr == null || respStr.isEmpty()) {
                                        if (batchClassId != null && !batchClassId.isEmpty()) {
                                            final BatchClass batchClass = batchClassService
                                                    .getBatchClassByIdentifier(batchClassId);
                                            if (batchClass != null) {

                                                final String ocrEngine = getDefaultHOCRPlugin(batchClassId);
                                                String colorSwitch = WebServiceUtil.EMPTY_STRING;
                                                String cmdLanguage = WebServiceUtil.EMPTY_STRING;
                                                LOGGER.info(EphesoftStringUtil.concatenate("Ocr engine used is : ",
                                                        ocrEngine));

                                                if (WebServiceConstants.TESSERACT_HOCR_PLUGIN
                                                        .equalsIgnoreCase(ocrEngine)) {
                                                    final File dir = new File(zipInFolder + "");
                                                    File[] directoryListing = dir.listFiles();
                                                    if (directoryListing != null) {
                                                        zipOutFolder = new File(
                                                                outputDir + File.separator + zipFileNameWithOutExt);
                                                        if (zipOutFolder != null) {
                                                            zipOutFolder.mkdirs();
                                                        }
                                                        for (File inputFile : directoryListing) {
                                                            String inputFileName = inputFile.getName();
                                                            if (inputFileName != null && !inputFileName.isEmpty()) {
                                                                if (inputFileName.endsWith(
                                                                        FileType.TIFF.getExtensionWithDot())
                                                                        || inputFileName.endsWith(FileType.TIF
                                                                                .getExtensionWithDot())) {
                                                                    final int pageCountTiff = TIFFUtil
                                                                            .getTIFFPageCount(inputFile.toString());
                                                                    if (pageCountTiff > 1) {
                                                                        continue;
                                                                    }

                                                                    if (WebServiceConstants.TESSERACT_HOCR_PLUGIN
                                                                            .equalsIgnoreCase(ocrEngine)) {
                                                                        final BatchPlugin pluginProperties = classPluginPropertiesService
                                                                                .getPluginProperties(batchClassId,
                                                                                        WebServiceConstants.TESSERACT_HOCR_PLUGIN);
                                                                        if (pluginProperties != null) {
                                                                            if (pluginProperties
                                                                                    .getPluginConfigurations(
                                                                                            TesseractProperties.TESSERACT_COLOR_SWITCH) != null) {
                                                                                colorSwitch = classPluginPropertiesService
                                                                                        .getPropertyValue(
                                                                                                batchClassId,
                                                                                                WebServiceConstants.TESSERACT_HOCR_PLUGIN,
                                                                                                TesseractProperties.TESSERACT_COLOR_SWITCH);
                                                                                if (pluginProperties
                                                                                        .getPluginConfigurations(
                                                                                                TesseractProperties.TESSERACT_LANGUAGE) != null) {
                                                                                    cmdLanguage = classPluginPropertiesService
                                                                                            .getPropertyValue(
                                                                                                    batchClassId,
                                                                                                    WebServiceConstants.TESSERACT_HOCR_PLUGIN,
                                                                                                    TesseractProperties.TESSERACT_LANGUAGE);
                                                                                    tesseractService.createOCR(
                                                                                            zipInFolder.toString(),
                                                                                            colorSwitch,
                                                                                            inputFileName,
                                                                                            zipOutFolder.toString(),
                                                                                            cmdLanguage,
                                                                                            WebServiceConstants.TESSERACT_CURRENT_VERSION);
                                                                                } else {
                                                                                    respStr = WebServiceConstants.NO_TESSERACT_LANGUAGE_SUPPORT;
                                                                                    responseCode = WebServiceConstants.INTERNAL_SERVER_ERROR_CODE;
                                                                                    LOGGER.error(
                                                                                            "No Language Support");
                                                                                }

                                                                            } else {
                                                                                respStr = WebServiceConstants.NO_TESSERACT_COLOR_SWITCH;
                                                                                responseCode = WebServiceConstants.INTERNAL_SERVER_ERROR_CODE;
                                                                                LOGGER.error(
                                                                                        "Colour Switch Not Found");
                                                                            }
                                                                        } else {
                                                                            respStr = WebServiceConstants.NO_PROPERTY_FOR_TESSERACT_HOCR;
                                                                            responseCode = WebServiceConstants.INTERNAL_SERVER_ERROR_CODE;
                                                                        }
                                                                    }

                                                                }
                                                            } else {
                                                                respStr = WebServiceConstants.INVALID_FILE_NAME;
                                                                responseCode = WebServiceConstants.INVALID_PARAMETERS_CODE;
                                                                LOGGER.error(
                                                                        "File Name should not be NULL or empty ");
                                                            }
                                                        } // End of for loop

                                                    }

                                                    else {
                                                        respStr = WebServiceConstants.NO_FILES_IN_ZIP_DIR;
                                                        responseCode = WebServiceConstants.NO_FILES_IN_ZIP_DIR_CODE;
                                                        LOGGER.error(respStr + " No files in the zip directory ");
                                                    }

                                                }
                                                if (respStr.isEmpty()) {
                                                    ServletOutputStream out = null;
                                                    ZipOutputStream zout = null;
                                                    final String zipFileName = WebServiceUtil.serverOutputFolderName;
                                                    resp.setContentType(WebServiceUtil.APPLICATION_X_ZIP);
                                                    resp.setHeader(WebServiceUtil.CONTENT_DISPOSITION,
                                                            WebServiceUtil.ATTACHMENT_FILENAME + zipFileName
                                                                    + FileType.ZIP.getExtensionWithDot()
                                                                    + "\"\r\n");
                                                    resp.setStatus(HttpServletResponse.SC_OK);
                                                    try {
                                                        out = resp.getOutputStream();
                                                        zout = new ZipOutputStream(out);
                                                        FileUtils.zipDirectory(zipOutFolder.toString(), zout,
                                                                zipFileName);
                                                    } catch (final FileNotFoundException fileNotFoundException) {
                                                        String messageString = fileNotFoundException.getMessage();
                                                        messageString = messageString.substring(
                                                                messageString.lastIndexOf(File.separator));
                                                        respStr = WebServiceConstants.FILE_NOT_FOUND
                                                                + messageString;
                                                        responseCode = WebServiceConstants.INTERNAL_SERVER_ERROR_CODE;
                                                        LOGGER.error("Could Not Copy the File "
                                                                + fileNotFoundException.getMessage());
                                                    } catch (final IOException ioExcpetion) {
                                                        respStr = WebServiceConstants.ERROR_WHILE_CREATING_ZIPPED_FILE
                                                                + ioExcpetion;
                                                        responseCode = WebServiceConstants.INTERNAL_SERVER_ERROR_CODE;
                                                        LOGGER.error(respStr);
                                                    } finally {
                                                        IOUtils.closeQuietly(zout);
                                                        IOUtils.closeQuietly(out);
                                                    }
                                                }
                                                if (respStr.isEmpty()) {
                                                    FileOutputStream fos = null;
                                                    ZipOutputStream zos = null;
                                                    final File out = new File(zipOutputLocation + File.separator
                                                            + zipFileNameWithOutExt
                                                            + FileType.ZIP.getExtensionWithDot());
                                                    try {
                                                        fos = new FileOutputStream(out);
                                                        zos = new ZipOutputStream(fos);
                                                        FileUtils.zipDirectory(zipOutFolder.toString(), zos,
                                                                zipFileNameWithOutExt);

                                                    } catch (final FileNotFoundException fileNotFoundException) {
                                                        String messageString = fileNotFoundException.getMessage();
                                                        messageString = messageString.substring(
                                                                messageString.lastIndexOf(File.separator));
                                                        respStr = WebServiceConstants.FILE_NOT_FOUND
                                                                + messageString;
                                                        responseCode = WebServiceConstants.INTERNAL_SERVER_ERROR_CODE;
                                                        LOGGER.error("Could Not Copy the File "
                                                                + fileNotFoundException.getMessage());
                                                    } catch (final IOException ioExcpetion) {
                                                        respStr = WebServiceConstants.ERROR_WHILE_CREATING_ZIPPED_FILE
                                                                + ioExcpetion;
                                                        responseCode = WebServiceConstants.INTERNAL_SERVER_ERROR_CODE;
                                                        LOGGER.error(respStr);
                                                    } finally {
                                                        IOUtils.closeQuietly(zos);
                                                        IOUtils.closeQuietly(fos);
                                                    }
                                                }

                                            } else {
                                                respStr = WebServiceConstants.INVALID_BATCH_CLASS_ID_MESSAGE;
                                                responseCode = WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_CODE;
                                                LOGGER.error(respStr + " Batch Class ID doesnot exist ");
                                            }
                                        } else {
                                            respStr = WebServiceConstants.INVALID_BATCH_CLASS_ID_MESSAGE;
                                            responseCode = WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_CODE;
                                            LOGGER.error(respStr + " No input of Batch Class ID ");
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        respStr = WebServiceConstants.INPUT_FILES_NOT_FOUND_MESSAGE;
                        responseCode = WebServiceConstants.INVALID_PARAMETERS_CODE;
                    }
                }
            } catch (final FileNotFoundException fileNotFoundException) {
                String message = fileNotFoundException.getMessage();
                message = message.substring(message.lastIndexOf(File.separator));
                respStr = WebServiceConstants.FILE_NOT_FOUND + message;
            } catch (final ValidationException validationException) {
                throw validationException;
            } catch (final InternalServerException internalServerError) {
                throw internalServerError;
            } catch (final Exception exception) {
                respStr = WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE + exception;
                responseCode = WebServiceConstants.INTERNAL_SERVER_ERROR_CODE;
                exception.printStackTrace();
            } finally {
                FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir));
            }
        } else {
            respStr = WebServiceConstants.INVALID_MULTIPART_REQUEST;
            responseCode = WebServiceConstants.INVALID_PARAMETERS_CODE;
        }
        validateResponse(responseCode, respStr);
    }

    /**
     * Processes a batch instance further its workflow from READY_FOR_REVIEW or READY_FOR_VALIDATION state.
     * 
     * @param loggedInUserRole the logged in user role
     * @param identifier the batch instance identifier
     * @throws ValidationException the validation exception - in case some parameter is not valid.
     * @throws UnAuthorisedAccessException the unauthorised access exception - in case user does not have access to the passed batch
     *             class.
     */
    public void runBatchInstance(final Set<String> loggedInUserRole, final String identifier)
            throws ValidationException, UnAuthorisedAccessException, InternalServerException {
        String responseString = WebServiceConstants.EMPTY_STRING;
        int responseCode = 0;
        try {
            if (StringUtils.isNotBlank(identifier)) {
                final BatchInstance batchInstance = batchInstanceService.getBatchInstanceByIdentifier(identifier);
                if (CollectionUtils.isEmpty(loggedInUserRole)) {
                    responseString = WebServiceConstants.UNAUTHORISED_ACCESS_EXCEPTION_MESSAGE;
                    responseCode = WebServiceConstants.UNAUTHORISED_ACCESS_EXCEPTION_CODE;
                } else {
                    if (batchInstance != null) {
                        final String batchInstanceStatus = batchInstance.getStatus().name();
                        if (batchInstanceStatus.equalsIgnoreCase(BatchInstanceStatus.READY_FOR_REVIEW.toString())
                                || batchInstanceStatus
                                        .equalsIgnoreCase(BatchInstanceStatus.READY_FOR_VALIDATION.toString())) {
                            workflowService.signalWorkflow(identifier);
                        } else {
                            responseString = EphesoftStringUtil.concatenate(
                                    WebServiceConstants.BATCH_INSTANCE_STATUS_INVALID_MESSAGE, identifier);
                            responseCode = WebServiceConstants.BATCH_INSTANCE_STATUS_INVALID_CODE;
                        }
                    } else {
                        responseString = EphesoftStringUtil.concatenate(
                                WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_MESSAGE, identifier);
                        responseCode = WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_CODE;
                    }
                }
            }
        } catch (final Exception exception) {
            responseString = EphesoftStringUtil.concatenate(WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE,
                    exception.getMessage());
            responseCode = WebServiceConstants.INTERNAL_SERVER_ERROR_CODE;
        }
        validateResponse(responseCode, responseString);
    }

    /**
     * Creates the UNPROCESSABLE Entity Rest Error with the Response Code and the response Message.
     * 
     * @param responseString {@link String}
     * @param responseCode int
     */
    public static RestError createUnprocessableEntityRestError(final String responseString,
            final int responseCode) {
        final RestError restError = new RestError(HttpStatus.UNPROCESSABLE_ENTITY, responseCode, responseString,
                responseString, WebServiceConstants.DEFAULT_URL);
        return restError;
    }

    /**
     * A utility function which check that the request is an MultiPart HTTP Request or not. If its a multiPart request then returns the
     * multipartHTTPServletRequest else throws a validation Exception
     * 
     * @param request {@link HttpServletRequest}
     * @return {@link DefaultMultipartHttpServletRequest}
     * @throws ValidationException {@link ValidationException}
     */
    public static DefaultMultipartHttpServletRequest getDefaultMultipartHttpServletRequest(
            final HttpServletRequest request) throws ValidationException {
        DefaultMultipartHttpServletRequest defaultRequest = null;
        if (null != request && request instanceof DefaultMultipartHttpServletRequest) {
            defaultRequest = (DefaultMultipartHttpServletRequest) request;
        } else {
            final String errorMessage = WebServiceConstants.IMPROPER_INPUT_TO_SERVER_MESSAGE;
            final int errorCode = WebServiceConstants.IMPROPER_INPUT_TO_SERVER_CODE;
            final RestError validationRestError = WebServiceHelper.createUnprocessableEntityRestError(errorMessage,
                    errorCode);
            throw new ValidationException(errorMessage, validationRestError);
        }
        return defaultRequest;
    }

    /**
     * Checks whether or not the RSP File actually Exist under the BatchClass.
     * <p>
     * It accepts the name of the filename and the Batch Class ID. and returns false when any of them is invalid or null.
     * </p>
     * 
     * @param fileName : name of the File to be searched should be a valid fileName
     * @param batchClassID : the identifier of the Batch Class.
     * @return : true if the file exist , else false.
     */
    public boolean isExistingFixedFormExtractionFile(final String fileName, final String batchClassID) {
        boolean containsFile = false;
        if (StringUtils.isNotBlank(fileName) && StringUtils.isNotEmpty(batchClassID)) {
            final String fixedFormFolderLocation = EphesoftStringUtil.concatenate(
                    batchSchemaService.getBaseFolderLocation(), File.separator, batchClassID, File.separator,
                    WebServiceConstants.FIXED_FORM_EXTRACTION_FOLDER);
            final File fixedFormFolder = new File(fixedFormFolderLocation);
            containsFile = FileUtils.isFileExists(fileName, fixedFormFolder);
        }
        return containsFile;
    }

    private void validateResponse(final int responseCode, final String respStr)
            throws ValidationException, InternalServerException {
        if (!respStr.isEmpty()) {
            final RestError error = new RestError(HttpStatus.UNPROCESSABLE_ENTITY, responseCode, respStr, respStr,
                    WebServiceConstants.DEFAULT_URL);
            if (responseCode == WebServiceConstants.INTERNAL_SERVER_ERROR_CODE) {
                throw new ValidationException(respStr, error);
            } else {
                throw new InternalServerException(respStr, error);
            }
        }
    }

    /**
     * Helper method for generating error message.
     * 
     * @param errorMessage is the error message
     * @param errorDeveloperMessage is more detailed message
     * @param errorCode is the error code
     * @return RestError which encapsulates all the above
     */
    public RestError generateRestError(final String errorMessage, final String errorDeveloperMessage,
            final int errorCode) {

        final int statusCode = errorCode / WebServiceConstants.DIVISOR_ERROR_CODE;

        final RestError restError = new RestError(HttpStatus.valueOf(statusCode), errorCode, errorMessage,
                errorDeveloperMessage, WebServiceConstants.DEFAULT_URL);
        return restError;

    }

    /**
     * This method will return the number of files available in MultiValueMap for a particular extention
     * 
     * @param fileExtension {@link String} the extension of the file whose count is required
     * @param fileMap {@link MultiValueMap} the MultiValuemapMultiValueMap<String, MultipartFile>
     * @return count {@link int } the number of files present in the MultiValueMap
     */

    private int checkFileCountForExtentionType(String fileExtension, MultiValueMap<String, MultipartFile> fileMap) {
        // TODO Auto-generated method stub
        LOGGER.info("Getting number of files present with speified file type in multi part request");
        int count = 0;
        if (fileExtension != null && !fileExtension.isEmpty() && !fileExtension.trim().equalsIgnoreCase("")
                && fileMap != null) {
            for (final String fileName : fileMap.keySet()) {
                if (fileName.toLowerCase().indexOf(FileType.XML.getExtension()) > -1) {
                    count++;
                }
            }
        }
        return count;
    }

    /**
     * Validates the input string to be a rsp file.
     * 
     * @param processingFile {@link String} is the name of rsp file
     * @return <code> errorMessage </code> with the cause of error
     */
    private String validateProcessingFile(final String processingFile, final String batchClassIdentifier) {
        boolean hasError = false;
        String errorMessage = WebServiceConstants.EMPTY_STRING;

        if (!(hasError) && !((processingFile.toLowerCase().indexOf(FileType.RSP.getExtension().toLowerCase()) > -1)
                || (processingFile.toLowerCase().indexOf(FileType.ZON.getExtension().toLowerCase()) > -1))) {
            errorMessage = "The form processing project file should be either .rsp file or .zon file";
            hasError = true;
        }

        if (!(hasError) && !isExistingFixedFormExtractionFile(processingFile.toLowerCase(), batchClassIdentifier)) {
            errorMessage = "This RSP file does not exist";
            hasError = true;
        }
        return errorMessage;
    }

    /**
     * Validates keyFuzziness for extractKV webservice
     * 
     * @param keyFuzziness {@link Float} parameter required during KV extraction
     */
    public boolean isValidKeyFuzziness(final Float keyFuzziness) {
        boolean isValid = true;
        if (keyFuzziness != null && (!(keyFuzziness == WebServiceConstants.KEY_FUZZINESS_FIRST_VALUE
                || keyFuzziness == WebServiceConstants.KEY_FUZZINESS_SECOND_VALUE
                || keyFuzziness == WebServiceConstants.KEY_FUZZINESS_THIRD_VALUE))) {
            isValid = false;
        }
        return isValid;
    }

    public Batch batchXMLDecryption(HttpServletRequest httpRequest)
            throws InternalServerException, NoUserRoleException, ValidationException {
        final String webServiceFolderPath = batchSchemaService.getWebServicesFolderPath();
        org.jdom.Document document = null;
        Batch unmarshalledObject = null;
        try {
            String workingDir = WebServiceUtil.createWebServiceWorkingDir(webServiceFolderPath);
            final DefaultMultipartHttpServletRequest multiPartRequest = (DefaultMultipartHttpServletRequest) httpRequest;
            final MultiValueMap<String, MultipartFile> fileMap = multiPartRequest.getMultiFileMap();
            LOGGER.info("Retreiving xml file.");
            final byte[] applicationLevelKey = encryptionKeyService.getApplicationKey();
            String xmlFileName = WebServiceConstants.EMPTY_STRING;
            xmlFileName = WebServiceHelper.getXMLFile(workingDir, multiPartRequest, fileMap);
            final File xmlFile = new File(workingDir + File.separator + xmlFileName);
            if (xmlFile.exists()) {
                LOGGER.info("Input xml file found, decrypting it.");
                final FileInputStream inputStream = new FileInputStream(xmlFile);
                // final Source source =
                // XMLUtil.createSourceFromStream(inputStream);
                if (null != applicationLevelKey) {
                    document = XMLUtil.createJDOMDocumentFromInputStream(inputStream);
                    unmarshalledObject = unmarshallXmlDocument(applicationLevelKey, document, httpRequest);
                } else {
                    createAndThrowValidationException(null,
                            WebServiceConstants.PARAMETER_APPLICATION_KEY_INCORRECT_CODE,
                            WebServiceConstants.WRONG_APP_KEY_EXCEPTION_MESSAGE);
                }
            } else {
                createAndThrowMissingXmlException(WebServiceConstants.INPUT_XML_NOT_FOUND_CODE,
                        WebServiceConstants.INPUT_XML_NOT_FOUND_MESSAGE);
            }
        } catch (NoUserRoleException noUserRoleException) {
            throw noUserRoleException;
        } catch (Exception exception) {
            exception.printStackTrace();
            throw new InternalServerException(
                    WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE.concat(exception.getMessage()),
                    createUnprocessableEntityRestError(
                            WebServiceConstants.INTERNAL_SERVER_ERROR_MESSAGE.concat(exception.getMessage()),
                            WebServiceConstants.INTERNAL_SERVER_ERROR_CODE));
        }

        return unmarshalledObject;
    }

    /**
     * Gets the user roles.
     * 
     * @param req the req
     * @return the user roles
     */
    public Set<String> getUserRoles(final HttpServletRequest req) {
        LOGGER.info("========Getting the user roles=========");

        Set<String> allGroups = userConnectivityService.getAllGroups();
        if (null == allGroups || allGroups.isEmpty()) {
            LOGGER.error("No groups fetched from Authenticated User.....All groups is empty.Returning null");
            return null;
        }

        Set<String> userGroups = new HashSet<String>();
        for (String group : allGroups) {
            if (null != group && !group.isEmpty()) {
                if (req.isUserInRole(group)) {
                    LOGGER.info("Added group is: " + group);
                    userGroups.add(group);
                }
            }
        }

        LOGGER.info("List of fetched user roles:");
        for (String userRole : userGroups) {
            LOGGER.info(userRole + ",");
        }

        if (userGroups.isEmpty()) {
            String userName = WebServiceUtil.EMPTY_STRING;
            if (req.getUserPrincipal() != null) {
                userName = req.getUserPrincipal().getName();
            }
            LOGGER.error("No roles found in Authenticated User for " + userName);
            userGroups = null;
        }

        return userGroups;
    }

    /**
     * Decrypts plugin batch xml file of a batch instance folder located in report-data backup.
     * 
     * @param batchInstanceIdentifier {@link String} The batch instance identifier.
     * @param moduleName {@link String} The name of plugin.
     * @param httpRequest {@link HttpServletRequest} The request Object from the client.
     * 
     * @return {@link Batch} object for plugin xml file.
     * @throws InternalServerException if xml file is not found.
     * @throws NoUserRoleException if logged in user has not enough permissions to perform the operations.
     * @throws ValidationException if batchInstanceIdentifier and pluginName is invalid.
     * @throws IOException if report-data folder path is not resolved.
     * @throws KeyNotFoundException if encryption key is not found.
     * @throws Exception if any other error condition occurs.
     */
    public Batch decryptReportingBatchXML(final String batchInstanceIdentifier, final String moduleName,
            final HttpServletRequest httpRequest) throws Exception, InternalServerException, NoUserRoleException,
            ValidationException, IOException, KeyNotFoundException {
        Batch unmarshalledObject = null;
        if (!EphesoftStringUtil.isNullOrEmpty(batchInstanceIdentifier)) {
            if (!EphesoftStringUtil.isNullOrEmpty(moduleName)) {
                final Properties backUpFileConfig = WebServiceUtil.fetchConfig();
                final String reportDataFolderPath = backUpFileConfig
                        .getProperty(WebServiceConstants.REPORT_BASE_FOL_LOC);
                if (!EphesoftStringUtil.isNullOrEmpty(reportDataFolderPath)) {
                    final String batchInstanceFolderPath = EphesoftStringUtil.concatenate(reportDataFolderPath,
                            File.separator, batchInstanceIdentifier);
                    try {
                        final File batchInstanceFolder = new File(batchInstanceFolderPath);
                        if (batchInstanceFolder.exists()) {
                            File moduleXmlFile = null;
                            final File[] fileList = batchInstanceFolder.listFiles();
                            for (final File xmlFile : fileList) {
                                final String fileName = xmlFile.getName();
                                // Change to accomodate new naming convention of xml files created per Module in Report Data Folder
                                if (xmlFile.isFile()
                                        && (fileName.toUpperCase().contains(moduleName.toUpperCase()))) {
                                    moduleXmlFile = xmlFile;
                                    break;
                                }
                            }
                            if (null != moduleXmlFile) {
                                final byte[] applicationLevelKey = this.encryptionKeyService.getApplicationKey();
                                if (null != applicationLevelKey) {
                                    org.jdom.Document document = null;
                                    final String moduleFilePath = moduleXmlFile.getAbsolutePath();
                                    if (moduleFilePath
                                            .endsWith(com.ephesoft.dcma.util.FileType.ZIP.getExtension())) {
                                        final String xmlFilePath = moduleFilePath.replaceAll(
                                                com.ephesoft.dcma.util.FileType.ZIP.getExtensionWithDot(),
                                                WebServiceConstants.EMPTY_STRING);
                                        final InputStream inputStream = FileUtils.getInputStreamFromZip(xmlFilePath,
                                                EphesoftStringUtil.concatenate(
                                                        batchInstanceIdentifier.toUpperCase(),
                                                        ICommonConstants.UNDERSCORE_BATCH_XML));
                                        document = XMLUtil.createJDOMDocumentFromInputStream(inputStream);
                                    } else if (moduleFilePath
                                            .endsWith(com.ephesoft.dcma.util.FileType.XML.getExtension())) {
                                        document = XMLUtil.createJDOMDocumentFromFile(new File(moduleFilePath));
                                    } else {
                                        this.createAndThrowMissingXmlException(
                                                WebServiceConstants.INPUT_XML_NOT_FOUND_CODE,
                                                WebServiceConstants.INPUT_XML_NOT_FOUND_MESSAGE);
                                    }
                                    LOGGER.info("Plugin xml file found, decrypting it.");
                                    unmarshalledObject = this.unmarshallXmlDocument(applicationLevelKey, document,
                                            httpRequest);
                                } else {
                                    this.createAndThrowValidationException(null,
                                            WebServiceConstants.PARAMETER_APPLICATION_KEY_INCORRECT_CODE,
                                            WebServiceConstants.WRONG_APP_KEY_EXCEPTION_MESSAGE);
                                }
                            } else {
                                this.createAndThrowMissingXmlException(WebServiceConstants.INPUT_XML_NOT_FOUND_CODE,
                                        WebServiceConstants.INPUT_XML_NOT_FOUND_MESSAGE);
                            }
                        } else {
                            this.createAndThrowMissingXmlException(WebServiceConstants.INPUT_XML_NOT_FOUND_CODE,
                                    WebServiceConstants.INPUT_XML_NOT_FOUND_MESSAGE);
                        }
                    } catch (final NoUserRoleException noUserRoleException) {
                        throw noUserRoleException;
                    }
                } else {
                    this.createAndThrowValidationException(batchInstanceIdentifier,
                            WebServiceConstants.INVALID_REPORT_DATA_PATH_CODE,
                            WebServiceConstants.INVALID_REPORT_DATA_PATH_MESSAGE);
                }
            } else {
                this.createAndThrowValidationException(batchInstanceIdentifier,
                        WebServiceConstants.INVALID_PLUGIN_NAME_PARAM_FOR_DECRYPTION_CODE,
                        WebServiceConstants.INVALID_PLUGIN_NAME_PARAM_FOR_DECRYPTION_MESSAGE);
            }
        } else {
            this.createAndThrowValidationException(batchInstanceIdentifier,
                    WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_CODE,
                    WebServiceConstants.INVALID_BATCH_INSTANCE_IDENTIFIER_MESSAGE);
        }
        return unmarshalledObject;
    }

    /**
     * Creates and throws {@link InternalServerException} with specified error code and error message.
     * 
     * @param code for error.
     * @param message for error.
     * @throws InternalServerException with specified message and error.
     */
    private void createAndThrowMissingXmlException(final int code, final String message)
            throws InternalServerException {
        final RestError restError = new RestError(HttpStatus.NOT_FOUND, code, message,
                EphesoftStringUtil.concatenate(message, WebServiceConstants.CLASS_WEB_SERVICE_UTILITY),
                WebServiceConstants.DEFAULT_URL);
        LOGGER.error(EphesoftStringUtil.concatenate(message, code, WebServiceConstants.HTTP_STATUS,
                HttpStatus.NOT_FOUND));
        throw new InternalServerException(message, restError);
    }

    /**
     * Creates and throws {@link ValidationException} with specified batch instance, error code and error message.
     * 
     * @param batchClassIdentifier to be logged in error message.
     * @param code for error.
     * @param message for error.
     * @throws ValidationException with specified message and error.
     */
    private void createAndThrowValidationException(final String batchClassIdentifier, final int code,
            final String message) throws ValidationException {
        if (null == batchClassIdentifier) {
            LOGGER.error(EphesoftStringUtil.concatenate(message, WebServiceConstants.ERROR_CODE_MESSAGE, code));
            throw new ValidationException(message,
                    new RestError(HttpStatus.INTERNAL_SERVER_ERROR, code, message,
                            EphesoftStringUtil.concatenate(message, WebServiceConstants.CLASS_WEB_SERVICE_UTILITY),
                            WebServiceConstants.DEFAULT_URL));
        } else {
            LOGGER.error(EphesoftStringUtil.concatenate(message, code, batchClassIdentifier));
            throw new ValidationException(
                    EphesoftStringUtil.concatenate(message, getAdditionalInfo(batchClassIdentifier)),
                    new RestError(HttpStatus.UNPROCESSABLE_ENTITY, code,
                            EphesoftStringUtil.concatenate(message, getAdditionalInfo(batchClassIdentifier)),
                            EphesoftStringUtil.concatenate(message, getAdditionalInfo(batchClassIdentifier),
                                    WebServiceConstants.CLASS_WEB_SERVICE_UTILITY),
                            WebServiceConstants.DEFAULT_URL));
        }
    }

    /**
     * Returns unmarshalled {@link Batch} object from specified {@link InputStream} using application level key.
     * 
     * @param applicationLevelKey {@link String}.
     * @param jdom document corrosponding to Plugin XML file.
     * @param httpRequest {@link HttpServletRequest} The request Object from the client.
     * 
     * @return unmarshalled {@link Batch} object.
     * @throws Exception in case of errornous condition occurs.
     * @throws HexDecoderException in case some error occures while decoding.
     * @throws UnsupportedEncodingException if the named charset is not supported
     * @throws JDOMException if some error occures while parsing xml file.
     * @throws XmlMappingException if some error occurs while unmarshalling the batch object.
     * @throws ValidationException if input validations fails.
     * @throws NoUserRoleException if logged in user has not enough permissions to perform the operations.
     */
    private Batch unmarshallXmlDocument(final byte[] applicationLevelKey, final org.jdom.Document document,
            final HttpServletRequest httpRequest)
            throws Exception, HexDecoderException, UnsupportedEncodingException, JDOMException, XmlMappingException,
            ValidationException, NoUserRoleException {
        Batch unmarshalledBatchObject = null;
        final org.jdom.Element signature = document.getRootElement().getChild(WebServiceConstants.SIGNATURE);
        if (null != signature && !EphesoftStringUtil.isNullOrEmpty(signature.getText())) {
            final String decodedSignature = BatchEncryptionUtil.decryptXMLStringContent(signature.getText(),
                    PrivateKeyEncryptionAlgorithm.AES_128, applicationLevelKey);
            // decoded signature: 1.encoded application key 2. encoded batch key
            // 3. encoded groups(hex form) 4. encryption
            // algorithm(not encoded)
            final String[] signatureparts = decodedSignature.split("#");
            final byte[] extractedAppKey = EphesoftStringUtil.decodeHexString(signatureparts[0]);
            final byte[] extractedBatchInstanceKey = EphesoftStringUtil.decodeHexString(signatureparts[1]);
            final byte[] extractedGroups = EphesoftStringUtil.decodeHexString(signatureparts[2]);
            final String groups = new String(extractedGroups, BatchConstants.UTF_8_ENCODER);
            // check if both app key equal or not.
            if (Arrays.equals(applicationLevelKey, extractedAppKey)) {
                document.getRootElement().removeChild(WebServiceConstants.SIGNATURE);
                final Set<String> rolesOfRequest = getUserRoles(httpRequest);
                final String[] listOfGropus = groups.split(",");
                boolean isPresent = false;
                if (null != listOfGropus && rolesOfRequest != null) {
                    for (final String group : listOfGropus) {
                        if (rolesOfRequest.contains(group)) {
                            isPresent = true;
                            break;
                        }
                    }
                }
                if (isPresent) {
                    DOMEncryptionUtil.decryptDocument(document, PrivateKeyEncryptionAlgorithm.AES_128,
                            extractedBatchInstanceKey);
                    final DOMOutputter xmlOutputter = new DOMOutputter();
                    final Document w3cDocument = xmlOutputter.output(document);
                    final DOMSource domSource = new DOMSource(w3cDocument);
                    unmarshalledBatchObject = (Batch) batchSchemaDao.getJAXB2Template().getJaxb2Marshaller()
                            .unmarshal(domSource);
                } else {
                    LOGGER.error(WebServiceConstants.NO_USER_ROLE_EXCEPTION_MESSAGE);
                    throw new NoUserRoleException();
                }
            } else {
                createAndThrowValidationException(null,
                        WebServiceConstants.PARAMETER_APPLICATION_KEY_INCORRECT_CODE,
                        WebServiceConstants.WRONG_APP_KEY_EXCEPTION_MESSAGE);
            }
        } else {
            createAndThrowValidationException(null, WebServiceConstants.SIGNATURE_NOT_FOUND_ERROR_CODE,
                    WebServiceConstants.SIGNATURE_NOT_FOUND_ERROR_MESSAGE);
        }
        return unmarshalledBatchObject;
    }

    /**
     * Returns unmarshalled {@link HocrPages} object after decrypting specified HOCR xml file.
     * 
     * @param xmlFilePath {@link String} HOCR xml file's path.
     * 
     * @return unmarshalled {@link HocrPages} object.
     * @throws Exception in case of errornous condition occurs.
     */
    public HocrPages decryptHocrXML(final String xmlFilePath) throws Exception {
        Source source = null;
        if (EphesoftStringUtil.isNullOrEmpty(xmlFilePath)) {
            this.createAndThrowMissingXmlException(WebServiceConstants.INPUT_XML_NOT_FOUND_CODE,
                    WebServiceConstants.INPUT_XML_NOT_FOUND_MESSAGE);
        } else {
            final File xmlFile = new File(xmlFilePath);
            if (xmlFile.exists() && xmlFile.isFile()) {
                LOGGER.info(EphesoftStringUtil.concatenate("Path of HOCR file to decrypt is : ", xmlFilePath));
                final InputStream inputStream = new FileInputStream(xmlFile);
                source = XMLUtil.createSourceFromStream(inputStream, xmlFile);
            } else {
                this.createAndThrowMissingXmlException(WebServiceConstants.INPUT_XML_NOT_FOUND_CODE,
                        WebServiceConstants.INPUT_XML_NOT_FOUND_MESSAGE);
            }
        }
        return (HocrPages) cryptoMarshaller.unmarshal(source);
    }

    /**
     * Validates user for specified batchInstanceIdentifier.
     * 
     * @param batchInstanceIdentifier
     * @param httpRequest
     * @return true if user has permissions to perform operations on specified batchInstanceIdentifier.
     */
    public boolean validateUserForBatchInstance(final String batchInstanceIdentifier,
            final HttpServletRequest httpRequest) {
        boolean isValidUser = false;
        if (!EphesoftStringUtil.isNullOrEmpty(batchInstanceIdentifier) && null != httpRequest) {
            final Set<String> rolesOfRequest = getUserRoles(httpRequest);
            Set<String> batchInstanceIdentifiers = batchInstanceGroupsService
                    .getBatchInstanceIdentifierForUserRoles(rolesOfRequest);
            if (batchInstanceIdentifiers.contains(batchInstanceIdentifier)) {
                isValidUser = true;
            }
        }
        return isValidUser;
    }

    /**
     * Validates user for specified batchClassIdentifier.
     * 
     * @param batchClassIdentifier
     * @param httpRequest
     * @return true if user has permissions to perform operations on specified batchClassIdentifier.
     */
    public boolean validateUserForBatchClass(final String batchClassIdentifier,
            final HttpServletRequest httpRequest) {
        boolean isPresent = false;
        if (!EphesoftStringUtil.isNullOrEmpty(batchClassIdentifier) && null != httpRequest) {
            final Set<String> userRoles = batchClassGroupsService.getRolesForBatchClass(batchClassIdentifier);
            final Set<String> rolesOfRequest = getUserRoles(httpRequest);
            if (null != userRoles && rolesOfRequest != null) {
                for (final String group : userRoles) {
                    if (rolesOfRequest.contains(group)) {
                        isPresent = true;
                        break;
                    }
                }
            }
        }
        return isPresent;
    }

    /**
     * performs table extraction on the HOCR file provided ,accepts input xml with HOCR page and document type classification along
     * with HOCR pages on whuich extraction is to be performed
     * 
     * @param req
     * @param resp
     * @return
     * @throws ValidationException
     * @throws InternalServerException
     */
    public Batch.Documents processtableExtractionHOCR(final HttpServletRequest req, final HttpServletResponse resp)
            throws ValidationException, InternalServerException {
        LOGGER.info("Start processing web service for table extraction....");
        String respStr = WebServiceUtil.EMPTY_STRING;
        String xmlFileName = WebServiceUtil.EMPTY_STRING;
        String workingDir = WebServiceUtil.EMPTY_STRING;
        Batch.Documents documents = null;
        InputStream instream = null;
        int responseCode = 0;
        if (req instanceof DefaultMultipartHttpServletRequest) {
            final String webServiceFolderPath = bsService.getWebServicesFolderPath();
            try {
                workingDir = WebServiceUtil.createWebServiceWorkingDir(webServiceFolderPath);
                final DefaultMultipartHttpServletRequest multiPartRequest = (DefaultMultipartHttpServletRequest) req;
                final MultiValueMap<String, MultipartFile> fileMap = multiPartRequest.getMultiFileMap();
                boolean isFileHOCR = false;
                boolean isFilePlainXML = false;
                if (fileMap.size() >= WebServiceConstants.MINIMUM_FILE_COUNT_FOR_TABLE_EXTRACTION) {
                    for (final String inputFileName : fileMap.keySet()) {
                        try {
                            isFileHOCR = inputFileName.trim().endsWith(WebServiceConstants.HOCR_EXTENSION);
                            isFilePlainXML = inputFileName.toLowerCase()
                                    .endsWith(FileType.XML.getExtensionWithDot());
                            if (!(isFileHOCR || isFilePlainXML)) {
                                respStr = WebServiceConstants.INVALID_FILES_TABLE_EXTRACTION;
                                responseCode = WebServiceConstants.INVALID_PARAMETERS_CODE;
                                createAndThrowValidationException(null, responseCode, respStr);
                            }
                            if (!isFileHOCR) {
                                xmlFileName = inputFileName;
                            }
                            final MultipartFile multiPartFile = multiPartRequest.getFile(inputFileName);
                            instream = multiPartFile.getInputStream();
                            WebServiceUtil.copyFile(workingDir, inputFileName, instream);
                        } catch (FileNotFoundException fileNotFoundException) {
                            respStr = WebServiceConstants.ERROR;
                            responseCode = WebServiceConstants.INTERNAL_SERVER_ERROR_CODE;
                        }
                    }
                    LOGGER.info("XML file name is" + xmlFileName);
                    final File xmlFile = new File(
                            EphesoftStringUtil.concatenate(workingDir, File.separator, xmlFileName));
                    final FileInputStream inputStream = new FileInputStream(xmlFile);
                    final Source source = XMLUtil.createSourceFromStream(inputStream);
                    String response = WebServiceUtil.EMPTY_STRING;
                    ExtractTableParam extractTableParams = (ExtractTableParam) batchSchemaDao.getJAXB2Template()
                            .getJaxb2Marshaller().unmarshal(source);
                    List<com.ephesoft.dcma.batch.schema.ExtractTableParam.Documents.Document> docList = extractTableParams
                            .getDocuments().getDocument();
                    final String batchClassIdentifier = extractTableParams.getBatchClassId();
                    Map<DocumentType, List<HocrPages>> documentHOCRMap = new HashMap<DocumentType, List<HocrPages>>();
                    if (EphesoftStringUtil.isNullOrEmpty(batchClassIdentifier)) {
                        responseCode = WebServiceConstants.INVALID_PARAMETERS_CODE;
                        respStr = WebServiceConstants.UNDEFINED_BATCH_IDENTIFIER;
                        createAndThrowValidationException(null, responseCode, respStr);
                    }
                    final BatchClass batchClass = bcService.getBatchClassByIdentifier(batchClassIdentifier);
                    if (null == batchClass) {
                        response = WebServiceUtil.BATCH_NOT_EXISTS;
                    }
                    if (EphesoftStringUtil.isNullOrEmpty(response)) {
                        String tableExtractionSwitch = WebServiceConstants.EMPTY_STRING;
                        try {
                            tableExtractionSwitch = batchClassPPService.getPropertyValue(batchClassIdentifier,
                                    WebServiceConstants.TABLE_EXTRACTION_PLUGIN,
                                    TableExtractionProperties.TABLE_EXTRACTION_SWITCH);
                        } catch (NullPointerException nullPointerException) {
                            responseCode = WebServiceConstants.INVALID_PARAMETERS_CODE;
                            respStr = EphesoftStringUtil.concatenate(
                                    WebServiceConstants.UNDEFINED_TABLE_EXTRACTION_SWITCH, batchClassIdentifier);
                            createAndThrowConfigurationException(responseCode, respStr);
                        }
                        if (WebServiceUtil.OFF_STRING.equals(tableExtractionSwitch)) {
                            respStr = EphesoftStringUtil.concatenate(
                                    WebServiceConstants.TABLE_EXTRACCTION_SWITCH_OFF_MESSAGE, batchClassIdentifier);
                            responseCode = WebServiceConstants.TABLE_EXTRACTION_SWITCH_OFF_CODE;
                            createAndThrowConfigurationException(responseCode, respStr);
                        }
                        final List<DocumentType> docTypeList = batchClass.getDocumentTypes();
                        List<String> docTypesName = obtainDocumentNameList(docTypeList);
                        documentHOCRMap = generateDocumentMapHOCR(docList, workingDir, docTypesName,
                                batchClassIdentifier);
                        if (documentHOCRMap.isEmpty()) {
                            respStr = WebServiceConstants.INVALID_MAPPING_DOCUMENT_HOCR_PAGES;
                            responseCode = WebServiceConstants.INVALID_PARAMETERS_CODE;
                            createAndThrowValidationException(null, responseCode, respStr);
                        }
                        final int gapBetweenColumnWords = tableFinderService.getGapBetweenColumnWords();
                        documents = tableExtraction.processDocPageForTableExtractionWebService(
                                gapBetweenColumnWords, documentHOCRMap, docTypeList, docTypesName);
                    } else {
                        respStr = response;
                        responseCode = WebServiceConstants.INVALID_PARAMETERS_CODE;
                        createAndThrowValidationException(null, responseCode, respStr);
                    }

                } else {
                    respStr = WebServiceConstants.TABLE_EXTRACTION_MINIMUM_PARAMETERS_REQUIRED_ERROR_MESSAGE;
                    responseCode = WebServiceConstants.INVALID_PARAMETERS_CODE;
                    createAndThrowValidationException(null, responseCode, respStr);
                }
            } catch (ClassCastException classCastException) {
                LOGGER.error(EphesoftStringUtil.concatenate("Not an Object of extract table Params",
                        classCastException.getMessage()));
                respStr = WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_MESSAGE;
                responseCode = WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_CODE;
            } catch (DCMABusinessException dcmaBusinessException) {
                LOGGER.error(EphesoftStringUtil.concatenate("Invalid HOCR xml file uploaded",
                        dcmaBusinessException.getMessage()));
                respStr = WebServiceConstants.INVALID_HOCR_FILE_UPLOAD_MESSAGE;
                responseCode = WebServiceConstants.INVALID_HOCR_FILE_UPLOADED_CODE;
            } catch (org.springframework.oxm.UnmarshallingFailureException unmarshallingFailureException) {
                LOGGER.error(EphesoftStringUtil.concatenate("Not an Object of extract table Params",
                        unmarshallingFailureException.getMessage()));
                respStr = WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_MESSAGE;
                responseCode = WebServiceConstants.INVALID_ARGUMENTS_IN_XML_INPUT_CODE;
            } catch (Exception exception) {
                LOGGER.error(EphesoftStringUtil.concatenate("Error generated is ", exception.getMessage()));
                if (EphesoftStringUtil.isNullOrEmpty(respStr)) {
                    respStr = WebServiceConstants.INVALID_MULTIPART_REQUEST;
                    responseCode = WebServiceConstants.INTERNAL_SERVER_ERROR_CODE;
                }
            } finally {
                if (!workingDir.isEmpty()) {
                    FileUtils.deleteDirectoryAndContentsRecursive(new File(workingDir).getParentFile());
                }
            }
        } else {
            if (EphesoftStringUtil.isNullOrEmpty(respStr)) {
                respStr = WebServiceConstants.INVALID_MULTIPART_REQUEST;
                responseCode = WebServiceConstants.INTERNAL_SERVER_ERROR_CODE;
            }
        }
        validateResponse(responseCode, respStr);
        return documents;
    }

    /**
     * returns a map with document type as key and list of HOCR pages as value
     * 
     * @param inputDocList list of documents in the input xml
     * @param workingDir working directory
     * @return map with document type and a list of HOCR belonging to that document
     */
    private Map<DocumentType, List<HocrPages>> generateDocumentMapHOCR(
            List<com.ephesoft.dcma.batch.schema.ExtractTableParam.Documents.Document> inputDocList,
            String workingDir, List<String> docTypesName, String batchClassIdentifier) {
        Map<DocumentType, List<HocrPages>> documentHOCRMap = new HashMap<DocumentType, List<HocrPages>>();
        for (com.ephesoft.dcma.batch.schema.ExtractTableParam.Documents.Document inputDocument : inputDocList) {
            if (null != inputDocument.getName()) {
                String inputDocumentName = inputDocument.getName().trim();
                if (!EphesoftStringUtil.isNullOrEmpty(inputDocumentName)) {
                    if (docTypesName.contains(inputDocumentName)) {
                        List<HocrPages> documentHOCRPages = new ArrayList<HocrPages>();
                        List<String> pageList = inputDocument.getPage();
                        if (null == pageList || pageList.size() == 0) {
                            continue;
                        } else {
                            for (String page : pageList) {
                                if (!EphesoftStringUtil.isNullOrEmpty(page)) {
                                    String filePath = EphesoftStringUtil.concatenate(workingDir, File.separator,
                                            page);
                                    File file = new File(filePath);
                                    if (!file.exists()) {
                                        continue;
                                    }
                                    final HocrPages hocrPages = bsService.getHOCR(filePath);
                                    if (null != hocrPages) {
                                        documentHOCRPages.add(hocrPages);
                                    }
                                }
                            }
                        }
                        if (!documentHOCRPages.isEmpty()) {
                            DocumentType documentType = docTypeService
                                    .getDocTypeByBatchClassAndDocTypeName(batchClassIdentifier, inputDocumentName);
                            documentHOCRMap.put(documentType, documentHOCRPages);
                        }
                    }
                }
            }
        }
        return documentHOCRMap;
    }

    /**
     * returns a list of document names present in the batch class
     * 
     * @param docTypeList list of document type
     * @return list of document names
     */
    private List<String> obtainDocumentNameList(List<DocumentType> docTypeList) {
        List<String> docTypesName = new ArrayList<String>();
        for (DocumentType doctype : docTypeList) {
            docTypesName.add(doctype.getName());
        }
        return docTypesName;
    }

    /**
     * throws a configuration exception
     * 
     * @param code error code
     * @param message error message
     * @throws ConfigurationException
     */
    private void createAndThrowConfigurationException(final int code, final String message)
            throws ConfigurationException {
        throw new ConfigurationException(message,
                new RestError(HttpStatus.INTERNAL_SERVER_ERROR, code, message,
                        EphesoftStringUtil.concatenate(message, WebServiceConstants.CLASS_WEB_SERVICE_UTILITY),
                        WebServiceConstants.DEFAULT_URL));
    }

    /**
     * Method to delete batch instance folder from ephesoft-system-folder
     * 
     * @param {@link BatchInstance}
     */
    private void deleteBatchFolder(final BatchInstance batchInstance) {
        LOGGER.info("Deleting batch instance folder from ephesoft system folder");
        final File batchInstanceFolder = new File(EphesoftStringUtil.concatenate(batchInstance.getLocalFolder(),
                File.separator, batchInstance.getIdentifier()));
        if (batchInstanceFolder.exists()) {
            FileUtils.deleteDirectoryAndContentsRecursive(batchInstanceFolder);
        }
    }

    /**
     * Method to delete .ser file from properties folder of ephesoft-system-folder
     * 
     * @param {@link BatchInstance}
     */
    private void deleteSerFile(final BatchInstance batchInstance) {
        LOGGER.info("Deleting .ser file from properties folder");
        final File batchInstanceFolder = new File(EphesoftStringUtil.concatenate(batchInstance.getLocalFolder(),
                File.separator, WebServiceConstants.PROPERTIES_FOLDER, File.separator,
                batchInstance.getIdentifier(), WebServiceConstants.SER_FILE));
        if (batchInstanceFolder.exists()) {
            batchInstanceFolder.delete();
        }

    }

}