com.stgmastek.core.logic.ExecutionOrder.java Source code

Java tutorial

Introduction

Here is the source code for com.stgmastek.core.logic.ExecutionOrder.java

Source

/*
 * Copyright (c) 2014 Mastek Ltd. All rights reserved.
 * 
 * This file is part of JBEAM. JBEAM is free software: you can
 * redistribute it and/or modify it under the terms of the GNU Lesser
 * General Public License as published by the Free Software Foundation.
 *
 * JBEAM 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 Lesser General
 * Public License for the specific language governing permissions and 
 * limitations.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with JBEAM. If not, see <http://www.gnu.org/licenses/>.
 */
package com.stgmastek.core.logic;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

import com.stgmastek.core.dao.DaoFactory;
import com.stgmastek.core.dao.IBatchDao;
import com.stgmastek.core.exception.BatchException;
import com.stgmastek.core.util.BatchContext;
import com.stgmastek.core.util.BatchInfo;
import com.stgmastek.core.util.ColumnLookup;
import com.stgmastek.core.util.Configurations;
import com.stgmastek.core.util.EntityParams;
import com.stgmastek.core.util.ExecutionStatus;
import com.stgmastek.core.util.GroupInfo;
import com.stgmastek.core.util.LookupTable;
import com.stgmastek.core.util.ProgressLevel;

/**
 * Final class that sets up the execution order of the current batch
 * 
 * @author grahesh.shanbhag
 * @author Kedar Raybagkar
 *
 */
public final class ExecutionOrder {

    private final static Logger logger = Logger.getLogger(ExecutionOrder.class);

    /**
     * Default constructor 
     */
    private ExecutionOrder() {
    }

    /**
     * Static method to setup the execution order.
     * This method essentially looks up in to the setup table BATCH_COLUMN_MAP to 
     * get the details.Using the details it would setup the execution order for the batch 
     * Once the execution order is set, it sets the order into the {@link BatchInfo#setOrderedMap(TreeMap)}
     * for all other objects to derive knowledge from. 
     * Note: The batch could be run for - 
     * <OL>
     * <LI> For a date i.e. all entities and all values for those entities. 
     * <LI> For an entity i.e. batch for only policy records and all its values 
     *        i.e. P1, P2 ... Pn
     * <LI> For a single object identified as GENERAL type of job with a 
     *       sequence number i.e. JOB_SCHEDULE.job_seq
     * <LI> For only Meta events like ALL PRE and ALL POST
     * <LI> For any combination of above, a few given - 
     *       <UL>
     *          <LI> Policy P1 and ALL PRE 
     *          <LI> ALL Agency records and Policy P1
     *         <LI> Policy P1 and Agency A1
     *       </UL>  
     * </OL>
     *  
     * Every step has inline comments associated with it. 
     * 
     * @param batchContext
     *         The context for the batch 
     * @return true 
     *          If the setup is done successfully 
     * @throws BatchException
     *          Any database I/O exception 
     */
    public synchronized static Boolean setExecutionOrder(BatchContext batchContext) throws BatchException {

        //Get request parameters
        HashMap<String, Object> params = batchContext.getRequestParams().getProcessRequestParams();

        //Check whether it is a date batch run or specific batch run         
        if (params.size() < 1) {
            batchContext.getBatchInfo().setDateRun(true);
        }
        Connection con = batchContext.getBATCHConnection();
        IBatchDao bDao = DaoFactory.getBatchDao();
        try {
            //Query the setup table to get the setup values
            LookupTable lookupTable = bDao.getLookupTable(con);
            Map<String, String> orderByLookupTable = bDao.getOrderByLookupTable(con);

            TreeMap<Integer, EntityParams> orderedMap = new TreeMap<Integer, EntityParams>();

            //If it is date batch run, then for all entities, populate "ALL" 
            if (batchContext.getBatchInfo().isDateRun()) {
                Iterator<String> lTableIter = lookupTable.keySet().iterator();
                while (lTableIter.hasNext()) {
                    String entity = lTableIter.next();
                    params.put(entity + "_1", "ALL");
                }
            }

            //Iterate over each parameters set 
            for (Entry<String, Object> entry : params.entrySet()) {
                String paramName = entry.getKey();
                Object paramValue = entry.getValue();
                if (logger.isDebugEnabled()) {
                    logger.debug("In ExecutionOrder >>>> paramName  ==>" + paramName);
                }

                String entity = null;

                //Strip the last occurrence of _ and get the entity name
                entity = paramName.substring(0, paramName.lastIndexOf("_"));
                if (logger.isDebugEnabled()) {
                    logger.debug("In ExecutionOrder >>>> Entity  ==>" + entity);
                }
                //Validate whether the entity is setup appropriately in 
                //the BATCH_COLUMN_MAP table 
                if (!lookupTable.containsKey(entity)) {
                    //If the entity is not set, raise an exception and exit 
                    throw new BatchException("The entity " + entity + " is not set up in the COLUMN_MAP table.");
                } else {

                    //Get the lookup record 
                    //Once found, get the details and set it against the entity 
                    List<ColumnLookup> lookupColumns = lookupTable.get(entity);
                    Integer order = lookupColumns.get(0).getPrecedenceOrder();
                    if (!orderedMap.containsKey(order)) {
                        EntityParams entityParams = new EntityParams(entity);
                        orderedMap.put(order, entityParams);
                    }
                    EntityParams entityParams = orderedMap.get(order);
                    entityParams.setLookupColumns(lookupColumns);
                    entityParams.setOrderByMap(orderByLookupTable);//Added on 01-OCT-2013 - Mandar

                    //Check 'ALL' or for specific entity values. 
                    //Note: Batch could be run for a date i.e. all entities (and all values) 
                    // or for any combination of entity and values 
                    if (!paramValue.equals("ALL")) {
                        List<GroupInfo> list = entityParams.getValues();
                        //check if all exists. If exists do not write the new value
                        if (list.size() == 0 || !list.get(0).getEntityValue().equals("ALL"))
                            entityParams.getValues().add(new GroupInfo((String) paramValue));
                    } else {
                        entityParams.setAll(new GroupInfo((String) paramValue));
                    }
                }
            }

            batchContext.getBatchInfo().setOrderedMap(orderedMap);
        } finally {
            bDao.releaseResources(null, null, con);
        }

        return true;
    }

    /**
     * Saves the state of the batch for revision runs usage 
     * If the current batch is 1000 and revision is 1 then the file would 
     * be saved as '1000_1.savepoint' 
     * 
     * @param batchContext
     *         The job batchContext of the batch 
     * @throws BatchException
     *          Any exception occurred during the serialization process 
     */
    public static synchronized void saveBatchState(BatchContext batchContext) throws BatchException {
        BatchInfo toSaveBatchInfo = batchContext.getBatchInfo();
        toSaveBatchInfo.setProgressLevelAtLastSavePoint(
                (ProgressLevel) ProgressLevel.getProgressLevel(toSaveBatchInfo.getBatchNo()).clone()); //clone is necessary as ProgresLevel is static
        if (logger.isDebugEnabled()) {
            logger.debug("Saving Current Batch progress level as ==>"
                    + ProgressLevel.getProgressLevel(toSaveBatchInfo.getBatchNo()).toString());
        }
        String savepointFilePath = Configurations.getConfigurations().getConfigurations("CORE", "SAVEPOINT",
                "DIRECTORY");
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream(FilenameUtils.concat(savepointFilePath,
                    toSaveBatchInfo.getBatchNo() + "_" + toSaveBatchInfo.getBatchRevNo() + ".savepoint")));
            oos.writeObject(toSaveBatchInfo);
            oos.flush();
            batchContext.setBatchStateSaved(true);
        } catch (FileNotFoundException e) {
            batchContext.setBatchStateSaved(false);
            logger.error(e);
            throw new BatchException(e.getMessage(), e);
        } catch (IOException e) {
            batchContext.setBatchStateSaved(false);
            logger.error(e);
            throw new BatchException(e.getMessage(), e);
        } finally {
            IOUtils.closeQuietly(oos);
        }
    }

    /**
     * Reads the saved state of the batch for revision runs 
     * If the current batch number it 1000 and revision is 5, 
     * then this method would look for saved state of batch 1000 
     * with revision (5 - 1) i.e. '1000_4.savepoint' 
     * 
     * @param batchContext
     *         The context for the batch 
     * @throws BatchException
     *          Any exception thrown during reading of the serialized file 
     */
    public static synchronized void updateBatchState(BatchContext batchContext) throws BatchException {
        BatchInfo newBatchInfo = batchContext.getBatchInfo();
        String savepointFilePath = Configurations.getConfigurations().getConfigurations("CORE", "SAVEPOINT",
                "DIRECTORY");
        String savePointFile = FilenameUtils.concat(savepointFilePath,
                newBatchInfo.getBatchNo() + "_" + (newBatchInfo.getBatchRevNo() - 1) + ".savepoint");
        if (logger.isDebugEnabled()) {
            logger.debug("Reading the saved state from file : " + savePointFile);
        }
        FileInputStream fis = null;
        try {

            //Check whether the file exists
            File f = new File(savePointFile);
            if (!f.exists())
                throw new BatchException("Cannot locate the the save point file named :" + savePointFile);

            fis = new FileInputStream(f);
            ObjectInputStream ois = new ObjectInputStream(fis);
            BatchInfo savedBatchInfo = (BatchInfo) ois.readObject();
            newBatchInfo.setOrderedMap(savedBatchInfo.getOrderedMap());
            newBatchInfo.setProgressLevelAtLastSavePoint(
                    (ProgressLevel) savedBatchInfo.getProgressLevelAtLastSavePoint()); //This object is different but still cloned.
            newBatchInfo.setBatchRunDate(savedBatchInfo.getBatchRunDate());
            newBatchInfo.setDateRun(savedBatchInfo.isDateRun());

            if (logger.isDebugEnabled()) {
                logger.debug(
                        "Last batch saved state is " + savedBatchInfo.getProgressLevelAtLastSavePoint().toString());
            }
            //Set the ExecutionStatus in the ProgressLevel
            ExecutionStatus savedExecutionStatus = newBatchInfo.getProgressLevelAtLastSavePoint()
                    .getExecutionStatus();
            ProgressLevel.getProgressLevel(newBatchInfo.getBatchNo())
                    .setExecutionStatus(savedExecutionStatus.getEntity(), savedExecutionStatus.getStageCode());
            fis.close();
            fis = null;
            ois.close();
            ois = null;
        } catch (FileNotFoundException e) {
            logger.error(e);
            throw new BatchException(e.getMessage(), e);
        } catch (IOException e) {
            logger.error(e);
            throw new BatchException(e.getMessage(), e);
        } catch (ClassNotFoundException e) {
            logger.error(e);
            throw new BatchException(e.getMessage(), e);
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                }
            }
        }
    }
}

/*
* Revision Log
* -------------------------------
* $Log:: /Product_Base/Projects/Batch/Code/Java/Core/src/com/stgmastek/core/logic/ExecutionOrder.java                                                                                $
 * 
 * 11    4/28/10 10:22a Kedarr
 * Updated javadoc
 * 
 * 10    4/27/10 9:27a Kedarr
 * Saves the state saved flag to true in batch context.
 * 
 * 9     4/21/10 12:07p Kedarr
 * Changes made to save the cloned progress level in batch info and subsequently load the same.
 * 
 * 8     3/09/10 2:51p Kedarr
 * Changes made to use java sql connection as now CConnection implements java sql connection. Also, Dao Factory is used to fetch the appropriate dao
 * 
 * 7     3/03/10 5:33p Grahesh
 * Removed batchContext.getBATCHConnection() from called IBatchDao constructor and added in called methods.
 * 
 * 6     2/24/10 5:01p Grahesh
 * Changes made to remove warnings as PRE was upgraded to use generics.
 * 
 * 5     2/17/10 9:15a Grahesh
 * Added synchronization to the methods used for saving / loading the state.
 * 
 * 4     12/23/09 11:55a Grahesh
 * Changes done to separate batch run date from batch execution date time
 * 
 * 3     12/22/09 11:06a Grahesh
 * Fetching the save point directory from the configurations
 * 
 * 2     12/17/09 11:46a Grahesh
 * Initial Version
*
*
*/