com.clustercontrol.jobmanagement.factory.JobSessionJobImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.clustercontrol.jobmanagement.factory.JobSessionJobImpl.java

Source

/*
    
Copyright (C) 2012 NTT DATA Corporation
    
This program is free software; you can redistribute it and/or
Modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, version 2.
    
This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the GNU General Public License for more details.
    
 */

package com.clustercontrol.jobmanagement.factory;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.clustercontrol.bean.EndStatusConstant;
import com.clustercontrol.bean.StatusConstant;
import com.clustercontrol.calendar.session.CalendarControllerBean;
import com.clustercontrol.commons.util.AbstractCacheManager;
import com.clustercontrol.commons.util.CacheManagerFactory;
import com.clustercontrol.commons.util.HinemosEntityManager;
import com.clustercontrol.commons.util.ICacheManager;
import com.clustercontrol.commons.util.ILock;
import com.clustercontrol.commons.util.ILockManager;
import com.clustercontrol.commons.util.JpaTransactionManager;
import com.clustercontrol.commons.util.LockManagerFactory;
import com.clustercontrol.fault.CalendarNotFound;
import com.clustercontrol.fault.FacilityNotFound;
import com.clustercontrol.fault.HinemosUnknown;
import com.clustercontrol.fault.InvalidRole;
import com.clustercontrol.fault.JobInfoNotFound;
import com.clustercontrol.jobmanagement.bean.ConditionTypeConstant;
import com.clustercontrol.jobmanagement.bean.DecisionObjectConstant;
import com.clustercontrol.jobmanagement.bean.DelayNotifyConstant;
import com.clustercontrol.jobmanagement.bean.EndStatusCheckConstant;
import com.clustercontrol.jobmanagement.bean.JobConstant;
import com.clustercontrol.jobmanagement.bean.JudgmentObjectConstant;
import com.clustercontrol.jobmanagement.bean.OperationConstant;
import com.clustercontrol.jobmanagement.bean.ProcessingMethodConstant;
import com.clustercontrol.jobmanagement.model.JobInfoEntity;
import com.clustercontrol.jobmanagement.model.JobSessionEntity;
import com.clustercontrol.jobmanagement.model.JobSessionJobEntity;
import com.clustercontrol.jobmanagement.model.JobSessionNodeEntity;
import com.clustercontrol.jobmanagement.model.JobStartJobInfoEntity;
import com.clustercontrol.jobmanagement.model.JobStartParamInfoEntity;
import com.clustercontrol.jobmanagement.util.ParameterUtil;
import com.clustercontrol.jobmanagement.util.QueryUtil;
import com.clustercontrol.util.HinemosTime;

public class JobSessionJobImpl {
    /** ? */
    private static Log m_log = LogFactory.getLog(JobSessionJobImpl.class);

    /** */
    private static final long TIMEZONE = HinemosTime.getTimeZoneOffset();

    private static final ILock _lock;

    static {
        ILockManager lockManager = LockManagerFactory.instance().create();
        _lock = lockManager.create(JobSessionJobImpl.class.getName());

        try {
            _lock.writeLock();

            ArrayList<String> cache = getForceCheckCache();
            if (cache == null) { // not null when clustered
                storeForceCheckCache(new ArrayList<String>());
            }
        } finally {
            _lock.writeUnlock();
        }
    }

    // ?runningCheck??????
    // ???????(????)?????runnincCheck????
    @SuppressWarnings("unchecked")
    private static ArrayList<String> getForceCheckCache() {
        ICacheManager cm = CacheManagerFactory.instance().create();
        Serializable cache = cm.get(AbstractCacheManager.KEY_JOB_FORCE_CHECK);
        if (m_log.isDebugEnabled())
            m_log.debug("get cache " + AbstractCacheManager.KEY_JOB_FORCE_CHECK + " : " + cache);
        return cache == null ? null : (ArrayList<String>) cache;
    }

    private static void storeForceCheckCache(ArrayList<String> newCache) {
        ICacheManager cm = CacheManagerFactory.instance().create();
        if (m_log.isDebugEnabled())
            m_log.debug("store cache " + AbstractCacheManager.KEY_JOB_FORCE_CHECK + " : " + newCache);
        cm.store(AbstractCacheManager.KEY_JOB_FORCE_CHECK, newCache);
    }

    public static void addForceCheck(String sessionId) {
        try {
            _lock.writeLock();

            ArrayList<String> cache = getForceCheckCache();
            if (cache.contains(sessionId)) {
                return;
            }

            cache.add(sessionId);
            storeForceCheckCache(cache);
        } finally {
            _lock.writeUnlock();
        }
    }

    public static boolean checkRemoveForceCheck(String sessionId) {
        try {
            _lock.writeLock();

            ArrayList<String> cache = getForceCheckCache();
            boolean flag = cache.remove(sessionId);
            if (flag) {
                m_log.debug("checkRemoveForceCheck " + sessionId);
            }
            return flag; // forceCheck???????true?
        } finally {
            _lock.writeUnlock();
        }
    }

    private static ConcurrentHashMap<String, Long> checkTimeMap = new ConcurrentHashMap<String, Long>();

    /**
     * ???
     * 
     * @param sessionId ID
     * @return ?
     */
    public static Long getCheckDate(String sessionId) {
        return checkTimeMap.get(sessionId);
    }

    public static boolean isSkipCheck(String sessionId) {
        Long time = checkTimeMap.get(sessionId);
        if (time == null) {
            return false;
        }
        if (time <= HinemosTime.currentTimeMillis()) {
            return false;
        }
        return true;
    }

    /**
     * inputDate???????????inputDate??
     * isCheckDate???inputDate?????true?????
     * @param sessionId
     * @param inputTime
     */
    private static void addCheckDate(String sessionId, Long inputTime) {
        Long time = checkTimeMap.get(sessionId);
        if (time == null || inputTime < time) {
            Date date = null;
            if (time != null) {
                date = new Date(time);
            }
            m_log.info("addCheckDate " + sessionId + ", input=" + new Date(inputTime) + ", date=" + date);
            checkTimeMap.put(sessionId, inputTime);
        }
    }

    /**
     * ????????????
     * ???????????
     * (????????????addCheckDate???
     *  ????)
     * @param sessionId
     */
    public static void maxCheckDate(String sessionId) {
        m_log.debug("maxCheckDate " + sessionId);
        checkTimeMap.put(sessionId, Long.MAX_VALUE);
    }

    /**
     * ?1???
     *
     * @param sessionId
     * @param jobId
     * @throws JobInfoNotFound
     * @throws HinemosUnknown
     * @throws InvalidRole
     * @throws FacilityNotFound 
     */
    public void startJob(String sessionId, String jobunitId, String jobId)
            throws JobInfoNotFound, HinemosUnknown, InvalidRole, FacilityNotFound {
        m_log.debug("startJob() : sessionId=" + sessionId + ", jobunitId=" + jobunitId + ", jobId=" + jobId);

        //ID?ID???
        JobSessionJobEntity sessionJob = QueryUtil.getJobSessionJobPK(sessionId, jobunitId, jobId);

        //?
        if (sessionJob.getStatus() == StatusConstant.TYPE_WAIT) {
            //??
            //????
            if (checkWaitCondition(sessionId, jobunitId, jobId) && checkCalendar(sessionId, jobunitId, jobId)
                    && sessionJob.getStatus() == StatusConstant.TYPE_WAIT) {
                //???????1????????
                addForceCheck(sessionId);
                //??
                sessionJob.setStatus(StatusConstant.TYPE_RUNNING);
                //?
                sessionJob.setStartDate(HinemosTime.currentTimeMillis());
                //?
                new Notice().notify(sessionId, jobunitId, jobId, EndStatusConstant.TYPE_BEGINNING);
                if (sessionJob.getJobInfoEntity().getJobType() == JobConstant.TYPE_JOB
                        || sessionJob.getJobInfoEntity().getJobType() == JobConstant.TYPE_APPROVALJOB
                        || sessionJob.getJobInfoEntity().getJobType() == JobConstant.TYPE_MONITORJOB) {
                    //??
                    new JobSessionNodeImpl().startNode(sessionId, jobunitId, jobId);
                } else {
                    //??????
                    startJob(sessionId, jobunitId, jobId);
                }
            } else {
                //???????????
                checkStartDelayRecursive(sessionId, jobunitId, jobId);
            }
        } else if (sessionJob.getStatus() == StatusConstant.TYPE_RUNNING) {
            //??
            if (!checkEndDelay(sessionId, jobunitId, jobId)) {
                //?????????????
                Collection<JobSessionJobEntity> collection = QueryUtil.getChildJobSessionJob(sessionId, jobunitId,
                        jobId);
                for (JobSessionJobEntity execJob : collection) {
                    String childJobId = execJob.getId().getJobId();
                    //?
                    startJob(sessionId, jobunitId, childJobId);
                }
            }
            if (sessionJob.getJobInfoEntity().getJobType() == JobConstant.TYPE_JOB
                    || sessionJob.getJobInfoEntity().getJobType() == JobConstant.TYPE_APPROVALJOB
                    || sessionJob.getJobInfoEntity().getJobType() == JobConstant.TYPE_MONITORJOB) {
                //??(????endJob)
                // ????????????????
                // RUNNING??????????
                // ?????????
                if (new JobSessionNodeImpl().startNode(sessionId, jobunitId, jobId)) {
                    endJob(sessionId, jobunitId, jobId, "", true);
                }
            }
        } else if (sessionJob.getStatus() == StatusConstant.TYPE_SKIP) {
            //??
            //???
            Integer endStatus = 0;
            Integer endValue = 0;
            Integer status = 0;
            JobInfoEntity job = sessionJob.getJobInfoEntity();
            if (job.getStartDelay().booleanValue() && job.getStartDelayOperation().booleanValue()
                    && job.getStartDelayOperationType() == OperationConstant.TYPE_STOP_SKIP) {
                // ????
                endStatus = job.getStartDelayOperationEndStatus();
                endValue = job.getStartDelayOperationEndValue();
                status = StatusConstant.TYPE_END_START_DELAY;
            } else {
                // ?or?[]??
                endStatus = job.getSkipEndStatus();
                endValue = job.getSkipEndValue();
                status = StatusConstant.TYPE_END_SKIP;
            }
            if (checkWaitCondition(sessionId, jobunitId, jobId)) {
                //???
                setEndStatus(sessionId, jobunitId, jobId, status, endStatus, endValue, null);
                //?
                endJob(sessionId, jobunitId, jobId, null, false);
            }
        }
    }

    /**
     * ????????
     *
     * @param sessionId ID
     * @param jobId ID
     * @return true??false??
     * @throws JobInfoNotFound
     * @throws InvalidRole
     * @throws HinemosUnknown
     * @throws FacilityNotFound 
     */
    private boolean checkWaitCondition(String sessionId, String jobunitId, String jobId)
            throws JobInfoNotFound, InvalidRole, HinemosUnknown, FacilityNotFound {
        m_log.debug(
                "checkWaitCondition() : sessionId=" + sessionId + ", jobunitId=" + jobunitId + ", jobId=" + jobId);

        //ID?ID???
        JobSessionJobEntity sessionJob = QueryUtil.getJobSessionJobPK(sessionId, jobunitId, jobId);
        //??
        JobInfoEntity job = sessionJob.getJobInfoEntity();
        //???
        Collection<JobStartJobInfoEntity> startJobs = job.getJobStartJobInfoEntities();
        ArrayList<Boolean> jobResult = new ArrayList<Boolean>();

        //statusCheck ?????
        //AND??????? :false??????? :true
        //OR??? :true
        //????????true
        boolean statusCheck = true;

        //startCheck ?????????
        //AND?????????????ture
        //OR?????????????????true
        boolean startCheck = true;

        //allEndCheck ???????
        boolean allEndCheck = true;

        //possibilityCheck ??
        //??????
        //AND???????1??NG???
        //OR????????????????NG???
        boolean possibilityCheck = true;

        //???
        List<JobStartParamInfoEntity> jobStartParamInfonList = job.getJobStartParamInfoEntities();

        //replaceCheck ????????
        boolean replaceCheck = true;

        //?????????
        if ((startJobs == null || startJobs.size() == 0) && job.getStartTime() == null
                && job.getStartMinute() == null
                && (jobStartParamInfonList == null || jobStartParamInfonList.size() == 0)) {
            return true;
        }

        //??
        for (JobStartJobInfoEntity startJob : startJobs) {
            //???

            //ID?ID???
            JobSessionJobEntity targetSessionJob = QueryUtil.getJobSessionJobPK(sessionJob.getId().getSessionId(),
                    startJob.getId().getTargetJobunitId(), startJob.getId().getTargetJobId());

            //()??
            if (StatusConstant.isEndGroup(targetSessionJob.getStatus())) {
                //??????

                if (startJob.getId().getTargetJobType() == JudgmentObjectConstant.TYPE_JOB_END_STATUS) {
                    //??

                    Integer endStatus = targetSessionJob.getEndStatus();
                    if (endStatus != null) {
                        //?????
                        if ((startJob.getId().getTargetJobEndValue() == EndStatusConstant.TYPE_ANY)
                                || (endStatus.equals(startJob.getId().getTargetJobEndValue()))) {
                            jobResult.add(true);
                            //OR??????????
                            if (job.getConditionType() == ConditionTypeConstant.TYPE_OR) {
                                break;
                            }
                        } else {
                            jobResult.add(false);
                        }
                    } else {
                        jobResult.add(false);
                    }
                } else if (startJob.getId().getTargetJobType() == JudgmentObjectConstant.TYPE_JOB_END_VALUE) {
                    //??
                    Integer endValue = targetSessionJob.getEndValue();
                    if (endValue != null) {
                        //?????
                        if (endValue.equals(startJob.getId().getTargetJobEndValue())) {
                            jobResult.add(true);
                            //OR??????????
                            if (job.getConditionType() == ConditionTypeConstant.TYPE_OR) {
                                break;
                            }
                        } else {
                            jobResult.add(false);
                        }
                    } else {
                        jobResult.add(false);
                    }
                } else {
                    jobResult.add(false);
                }
            } else {
                // ??????????allEndCheckfalse?
                allEndCheck = false;
                if (job.getConditionType() == ConditionTypeConstant.TYPE_AND) {
                    // ???AND???????
                    statusCheck = false;
                    startCheck = false;
                    break;
                } else {
                    // ???OR???
                    jobResult.add(false);
                }
            }
        }

        // ??
        for (JobStartParamInfoEntity jobStartParamInfoEntity : jobStartParamInfonList) {

            // 1???
            String decisionValue01 = "";
            // 2???
            String decisionValue02 = "";
            String regex = "#\\[[a-zA-Z0-9-_:]+\\]";
            Pattern pattern = Pattern.compile(regex);
            // 1????????
            if (pattern.matcher(jobStartParamInfoEntity.getId().getStartDecisionValue01()).find()) {
                // 1??
                decisionValue01 = ParameterUtil.replaceSessionParameterValue(sessionId, job.getFacilityId(),
                        jobStartParamInfoEntity.getId().getStartDecisionValue01());

                // 1???????????????????????
                if (pattern.matcher(decisionValue01).find()) {
                    replaceCheck = false;
                    jobResult.add(false);
                    continue;
                }
            } else {
                decisionValue01 = jobStartParamInfoEntity.getId().getStartDecisionValue01();
            }

            // 2????????
            if (pattern.matcher(jobStartParamInfoEntity.getId().getStartDecisionValue02()).find()) {
                // 2??
                decisionValue02 = ParameterUtil.replaceSessionParameterValue(sessionId, job.getFacilityId(),
                        jobStartParamInfoEntity.getId().getStartDecisionValue02());

                // 2???????????????????????
                if (pattern.matcher(decisionValue02).find()) {
                    replaceCheck = false;
                    jobResult.add(false);
                    continue;
                }
            } else {
                decisionValue02 = jobStartParamInfoEntity.getId().getStartDecisionValue02();
            }

            if (jobStartParamInfoEntity.getId()
                    .getStartDecisionCondition() == DecisionObjectConstant.EQUAL_NUMERIC) {
                try {
                    if (checkDecisionValue(decisionValue01, decisionValue02) == 0) {
                        jobResult.add(true);
                        //OR??????????
                        if (job.getConditionType() == ConditionTypeConstant.TYPE_OR) {
                            break;
                        }
                    } else {
                        jobResult.add(false);
                    }
                } catch (NumberFormatException e) {
                    jobResult.add(false);
                }
            } else if (jobStartParamInfoEntity.getId()
                    .getStartDecisionCondition() == DecisionObjectConstant.NOT_EQUAL_NUMERIC) {
                try {
                    if (checkDecisionValue(decisionValue01, decisionValue02) != 0) {
                        jobResult.add(true);
                        //OR??????????
                        if (job.getConditionType() == ConditionTypeConstant.TYPE_OR) {
                            break;
                        }
                    } else {
                        jobResult.add(false);
                    }
                } catch (NumberFormatException e) {
                    jobResult.add(false);
                }
            } else if (jobStartParamInfoEntity.getId()
                    .getStartDecisionCondition() == DecisionObjectConstant.GREATER_THAN) {
                try {
                    if (checkDecisionValue(decisionValue01, decisionValue02) > 0) {
                        jobResult.add(true);
                        //OR??????????
                        if (job.getConditionType() == ConditionTypeConstant.TYPE_OR) {
                            break;
                        }
                    } else {
                        jobResult.add(false);
                    }
                } catch (NumberFormatException e) {
                    jobResult.add(false);
                }
            } else if (jobStartParamInfoEntity.getId()
                    .getStartDecisionCondition() == DecisionObjectConstant.GREATER_THAN_OR_EQUAL_TO) {
                try {
                    if (checkDecisionValue(decisionValue01, decisionValue02) >= 0) {
                        jobResult.add(true);
                        //OR??????????
                        if (job.getConditionType() == ConditionTypeConstant.TYPE_OR) {
                            break;
                        }
                    } else {
                        jobResult.add(false);
                    }
                } catch (NumberFormatException e) {
                    jobResult.add(false);
                }
            } else if (jobStartParamInfoEntity.getId()
                    .getStartDecisionCondition() == DecisionObjectConstant.LESS_THAN) {
                try {
                    if (checkDecisionValue(decisionValue01, decisionValue02) < 0) {
                        jobResult.add(true);
                        //OR??????????
                        if (job.getConditionType() == ConditionTypeConstant.TYPE_OR) {
                            break;
                        }
                    } else {
                        jobResult.add(false);
                    }
                } catch (NumberFormatException e) {
                    jobResult.add(false);
                }
            } else if (jobStartParamInfoEntity.getId()
                    .getStartDecisionCondition() == DecisionObjectConstant.LESS_THAN_OR_EQUAL_TO) {
                try {
                    if (checkDecisionValue(decisionValue01, decisionValue02) <= 0) {
                        jobResult.add(true);
                        //OR??????????
                        if (job.getConditionType() == ConditionTypeConstant.TYPE_OR) {
                            break;
                        }
                    } else {
                        jobResult.add(false);
                    }
                } catch (NumberFormatException e) {
                    jobResult.add(false);
                }
            } else if (jobStartParamInfoEntity.getId()
                    .getStartDecisionCondition() == DecisionObjectConstant.EQUAL_STRING) {
                if (decisionValue01.equals(decisionValue02)) {
                    jobResult.add(true);
                    //OR??????????
                    if (job.getConditionType() == ConditionTypeConstant.TYPE_OR) {
                        break;
                    }
                } else {
                    jobResult.add(false);
                }
            } else if (jobStartParamInfoEntity.getId()
                    .getStartDecisionCondition() == DecisionObjectConstant.NOT_EQUAL_STRING) {
                if (!decisionValue01.equals(decisionValue02)) {
                    jobResult.add(true);
                    //OR??????????
                    if (job.getConditionType() == ConditionTypeConstant.TYPE_OR) {
                        break;
                    }
                } else {
                    jobResult.add(false);
                }
            } else {
                m_log.warn("Outside of DecisionCondition : "
                        + jobStartParamInfoEntity.getId().getStartDecisionCondition());
            }
            m_log.debug("DecisionInfo " + jobStartParamInfoEntity.getId().getStartDecisionCondition()
                    + ", value01 : " + decisionValue01 + ", value02 : " + decisionValue02);
        }

        // ??
        if (statusCheck) {
            //AND???OR?????
            if (job.getConditionType() == ConditionTypeConstant.TYPE_AND) {
                //AND???
                startCheck = true;
                for (Boolean flag : jobResult) {
                    if (!flag) {
                        startCheck = false;
                        break;
                    }
                }
            } else {
                //OR???
                startCheck = false;
                for (Boolean flag : jobResult) {
                    if (flag) {
                        startCheck = true;
                        break;
                    }
                }
            }

            //???
            //AND???OR?????????
            if (!startCheck) {
                if (job.getConditionType() == ConditionTypeConstant.TYPE_AND) {
                    //AND???????1??NG???(startCheck?false?????)
                    possibilityCheck = false;
                } else {
                    //OR????????????????NG???
                    if (job.getStartTime() == null && allEndCheck && job.getStartMinute() == null) {
                        possibilityCheck = false;
                    }
                }
            }

            // ????
            if (job.getConditionType() == ConditionTypeConstant.TYPE_AND) {
                // ???AND???
                //???????????
                if (startCheck && job.getStartTime() != null) {
                    startCheck = checkWaitTime(startCheck, sessionId, job.getStartTime());
                }
            } else {
                // ???OR???
                // ?????????????
                if (!startCheck && job.getStartTime() != null) {
                    startCheck = checkWaitTime(startCheck, sessionId, job.getStartTime());
                }
            }

            // ??????
            if (job.getConditionType() == ConditionTypeConstant.TYPE_AND) {
                // ???AND???
                //?????????????
                if (startCheck && job.getStartMinute() != null) {
                    startCheck = checkStartMinute(startCheck, sessionId, job.getStartMinute());
                }
            } else {
                // ???OR???
                //?????????????
                if (!startCheck && job.getStartMinute() != null) {
                    startCheck = checkStartMinute(startCheck, sessionId, job.getStartMinute());
                }
            }
        }

        //???NG??
        //????????
        //????????
        if (!startCheck && !possibilityCheck && job.getUnmatchEndFlg().booleanValue() && replaceCheck) {
            m_log.debug("checkStartCondition() : unmatch end flg is true. end job : " + " jobid : " + jobId
                    + " : status :" + sessionJob.getStatus());
            //??????????
            Integer endStatus = job.getUnmatchEndStatus();
            // 
            Integer endValue = job.getUnmatchEndValue();

            //???
            setEndStatus(sessionId, jobunitId, jobId, StatusConstant.TYPE_END_UNMATCH, endStatus, endValue, null);
            //?
            endJob(sessionId, jobunitId, jobId, null, false);
        }
        return startCheck;
    }

    /**
     * ?????
     * @param startCheck
     * @param sessionId
     * @param startMinute
     * @return true or false
     * @throws JobInfoNotFound
     */
    private Boolean checkStartMinute(Boolean startCheck, String sessionId, Integer startMinute)
            throws JobInfoNotFound {

        m_log.trace("startCheck : " + startCheck);

        //ID???
        JobSessionEntity session = QueryUtil.getJobSessionPK(sessionId);
        //?
        Long sessionDate = session.getScheduleDate();
        m_log.trace("sessionDate : " + sessionDate);

        Calendar work = HinemosTime.getCalendarInstance();
        work.setTimeInMillis(sessionDate);
        work.getTime();
        work.add(Calendar.MINUTE, startMinute);
        Long check = work.getTimeInMillis();
        Boolean startMinuteCheck = check <= HinemosTime.currentTimeMillis();
        /*
         * ????????
         * checkDateMap??
         */
        if (!startMinuteCheck) {
            addCheckDate(sessionId, check);
        }

        return startMinuteCheck;
    }

    /**
     * ????
     * @param startCheck
     * @param sessionId
     * @param startTime
     * @return true or false ( + ??() + TIMEZONE <= ?)
     * @throws JobInfoNotFound
     */
    private Boolean checkWaitTime(Boolean startCheck, String sessionId, Long startTime) throws JobInfoNotFound {

        m_log.trace("startCheck : " + startCheck);

        //ID???
        JobSessionEntity session = QueryUtil.getJobSessionPK(sessionId);
        //?
        Long sessionDate = session.getScheduleDate();
        m_log.trace("sessionDate : " + sessionDate);

        //??00:00:00?
        Calendar sessionCal = HinemosTime.getCalendarInstance();
        sessionCal.setTimeInMillis(sessionDate);
        sessionCal.set(Calendar.HOUR_OF_DAY, 0);
        sessionCal.set(Calendar.MINUTE, 0);
        sessionCal.set(Calendar.SECOND, 0);
        sessionCal.set(Calendar.MILLISECOND, 0);
        Date sessionDate0h = sessionCal.getTime();
        m_log.trace("sessionDate0h : " + sessionDate0h);

        /*
         *  + ??() + TIMEZONE
         * 
         * 2013/01/09 00:00:00
         * ??40:00:00(1970/01/02 16:00:00)
         *
         *  +??() + TIMEZONE = 2013/01/10 16:00:00
         */
        long overMidnight = sessionDate0h.getTime() + startTime + TIMEZONE;
        m_log.trace("overMidnight : " + new Date(overMidnight));

        //?
        startCheck = overMidnight <= HinemosTime.currentTimeMillis();
        m_log.trace("startCheck2 : " + startCheck);

        /*
         * ????????????checkDateMap??
         */
        if (!startCheck) {
            addCheckDate(sessionId, overMidnight);
        }
        return startCheck;
    }

    /**
     * ?????
     *
     * @param sessionId ID
     * @param jobId ID
     * @return true=??, false=???
     * @throws JobInfoNotFound
     * @throws InvalidRole
     */
    private void checkStartDelayRecursive(String sessionId, String jobunitId, String jobId)
            throws JobInfoNotFound, InvalidRole {
        m_log.debug(
                "checkStartDelayMain() : sessionId=" + sessionId + ", jobunitId=" + jobunitId + ", jobId=" + jobId);

        //ID?ID???
        JobSessionJobEntity sessionJob = QueryUtil.getJobSessionJobPK(sessionId, jobunitId, jobId);

        //?
        if (sessionJob.getStatus() == StatusConstant.TYPE_WAIT) {
            //??
            checkStartDelaySub(sessionId, jobunitId, jobId);
        }

        //ID?ID????
        Collection<JobSessionJobEntity> collection = null;
        collection = QueryUtil.getChildJobSessionJob(sessionId, jobunitId, jobId);

        if (collection == null) {
            m_log.trace("collection is null. " + sessionId + "," + jobunitId + "," + jobId);
            return;
        }
        for (JobSessionJobEntity childSessionJob : collection) {
            String childSessionId = childSessionJob.getId().getSessionId();
            String childJobUnitId = childSessionJob.getId().getJobunitId();
            String childJobId = childSessionJob.getId().getJobId();

            //???????
            checkStartDelayRecursive(childSessionId, childJobUnitId, childJobId);
        }
    }

    /**
     * ?????
     *
     * @param sessionId ID
     * @param jobId ID
     * @return true=??, false=???
     * @throws JobInfoNotFound
     * @throws InvalidRole
     */
    private void checkStartDelaySub(String sessionId, String jobunitId, String jobId)
            throws JobInfoNotFound, InvalidRole {
        m_log.debug("checkStartDelay() : sessionId=" + sessionId + ", jobunitId=" + jobunitId + ", jobId=" + jobId);

        //ID?ID???
        JobSessionJobEntity sessionJob = QueryUtil.getJobSessionJobPK(sessionId, jobunitId, jobId);
        JobInfoEntity job = sessionJob.getJobInfoEntity();
        ArrayList<Boolean> result = new ArrayList<Boolean>();
        boolean delayCheck = true;

        if (!job.getStartDelay().booleanValue()) {
            return;
        }
        //??????
        Long sessionDate = null;

        if (job.getStartDelaySession().booleanValue()) {
            //??????
            //?
            JobSessionEntity session = QueryUtil.getJobSessionPK(sessionId);
            sessionDate = session.getScheduleDate();
            Calendar work = HinemosTime.getCalendarInstance();
            work.setTimeInMillis(sessionDate);
            work.getTime();
            work.add(Calendar.MINUTE, job.getStartDelaySessionValue());
            Long check = work.getTimeInMillis();
            Boolean startDelayCheck = check <= HinemosTime.currentTimeMillis();
            /*
             * ?(?)???????
             * checkDateMap??
             */
            if (!startDelayCheck) {
                addCheckDate(sessionId, check);
            }
            result.add(startDelayCheck);
        }

        if (job.getStartDelayTime().booleanValue()) {
            //?????
            if (job.getStartDelayTimeValue() != null) {
                //?
                if (sessionDate == null) {
                    JobSessionEntity session = QueryUtil.getJobSessionPK(sessionId);
                    sessionDate = session.getScheduleDate();
                }
                //??00:00:00?
                Calendar sessionCal = HinemosTime.getCalendarInstance();
                sessionCal.setTimeInMillis(sessionDate);
                sessionCal.set(Calendar.HOUR_OF_DAY, 0);
                sessionCal.set(Calendar.MINUTE, 0);
                sessionCal.set(Calendar.SECOND, 0);
                sessionCal.set(Calendar.MILLISECOND, 0);
                Date sessionDate0h = sessionCal.getTime();
                m_log.trace("sessionDate0h : " + sessionDate0h);

                //  + ?() + TIMEZONE
                long startDelay = sessionDate0h.getTime() + job.getStartDelayTimeValue() + TIMEZONE;
                m_log.trace("himatagiDate : " + new Date(startDelay));

                //??
                boolean startDelayCheck = startDelay <= HinemosTime.currentTimeMillis();
                m_log.trace("startDelayCheck : " + startDelayCheck);
                /*
                 * ?()???????
                 * checkDateMap??
                 */
                if (!startDelayCheck) {
                    addCheckDate(sessionId, startDelay);
                }
                result.add(startDelayCheck);
            } else {
                result.add(false);
            }
        }

        //AND???OR?????
        if (result.size() > 0) {
            if (job.getStartDelayConditionType() == ConditionTypeConstant.TYPE_AND) {
                //AND???
                delayCheck = true;
                for (Boolean flag : result) {
                    if (!flag) {
                        delayCheck = false;
                        break;
                    }
                }
            } else {
                //OR???
                delayCheck = false;
                for (Boolean flag : result) {
                    if (flag) {
                        delayCheck = true;
                        break;
                    }
                }
            }
        } else {
            delayCheck = false;
        }

        //???????
        if (delayCheck) {

            //
            if (job.getStartDelayNotify().booleanValue()) {
                //??
                int flg = sessionJob.getDelayNotifyFlg();
                //????
                int notifyFlg = DelayNotifyConstant.getNotify(flg);

                if (notifyFlg == DelayNotifyConstant.NONE || notifyFlg == DelayNotifyConstant.END) {
                    //?????????????

                    //?
                    new Notice().delayNotify(sessionId, jobunitId, jobId, true);

                    if (notifyFlg == DelayNotifyConstant.NONE) {
                        sessionJob.setDelayNotifyFlg(DelayNotifyConstant.START);
                    } else if (notifyFlg == DelayNotifyConstant.END) {
                        sessionJob.setDelayNotifyFlg(DelayNotifyConstant.START_AND_END);
                    }
                }
            }

            //?
            if (job.getStartDelayOperation().booleanValue()) {
                int type = job.getStartDelayOperationType();

                if (type == OperationConstant.TYPE_STOP_SKIP) {
                    //??????
                    if (sessionJob.getStatus() == StatusConstant.TYPE_WAIT) {
                        sessionJob.setStatus(StatusConstant.TYPE_SKIP);
                    }
                } else if (type == OperationConstant.TYPE_STOP_WAIT) {
                    //???????
                    if (sessionJob.getStatus() == StatusConstant.TYPE_WAIT) {
                        sessionJob.setStatus(StatusConstant.TYPE_RESERVING);
                    }
                }
            }
        }
    }

    /**
     * ?????
     *
     * @param sessionId ID
     * @param jobId ID
     * @return true=??, false=???
     * @throws HinemosUnknown
     * @throws JobInfoNotFound
     * @throws InvalidRole
     * @throws FacilityNotFound 
     */
    private boolean checkEndDelay(String sessionId, String jobunitId, String jobId)
            throws HinemosUnknown, JobInfoNotFound, InvalidRole, FacilityNotFound {
        m_log.debug("checkEndDelay() : sessionId=" + sessionId + ", jobId=" + jobId);

        //ID?ID???
        JobSessionJobEntity sessionJob = QueryUtil.getJobSessionJobPK(sessionId, jobunitId, jobId);

        JobInfoEntity job = sessionJob.getJobInfoEntity();

        ArrayList<Boolean> result = new ArrayList<Boolean>();
        boolean delayCheck = true;

        //????????
        if (!job.getEndDelay().booleanValue()) {
            return false;
        }

        long sessionDate = -1;

        if (job.getEndDelaySession().booleanValue()) {
            //??????

            //?
            JobSessionEntity session = QueryUtil.getJobSessionPK(sessionId);
            sessionDate = session.getScheduleDate();
            Calendar work = HinemosTime.getCalendarInstance();
            work.setTimeInMillis(sessionDate);
            work.getTime();
            work.add(Calendar.MINUTE, job.getEndDelaySessionValue());
            Long check = work.getTimeInMillis();
            Boolean endDelayCheck = check <= HinemosTime.currentTimeMillis();
            /*
             * ?(?)???????
             * checkDateMap??
             */
            if (!endDelayCheck) {
                addCheckDate(sessionId, check);
            }
            result.add(endDelayCheck);
        }

        if (job.getEndDelayJob().booleanValue()) {
            //??????

            //?
            Long startDate = sessionJob.getStartDate();
            Calendar work = HinemosTime.getCalendarInstance();
            work.setTimeInMillis(startDate);
            work.getTime();
            work.add(Calendar.MINUTE, job.getEndDelayJobValue());
            Long check = work.getTimeInMillis();
            Boolean endDelayCheck = check <= HinemosTime.currentTimeMillis();
            /*
             * ?(?)???????
             * checkDateMap??
             */
            if (!endDelayCheck) {
                addCheckDate(sessionId, check);
            }
            result.add(endDelayCheck);
        }

        if (job.getEndDelayTime().booleanValue()) {
            //?????

            if (job.getEndDelayTimeValue() != null) {
                //?
                if (sessionDate < 0) {
                    JobSessionEntity session = QueryUtil.getJobSessionPK(sessionId);
                    sessionDate = session.getScheduleDate();
                }
                //??00:00:00?
                Calendar sessionCal = HinemosTime.getCalendarInstance();
                sessionCal.setTimeInMillis(sessionDate);
                sessionCal.set(Calendar.HOUR_OF_DAY, 0);
                sessionCal.set(Calendar.MINUTE, 0);
                sessionCal.set(Calendar.SECOND, 0);
                sessionCal.set(Calendar.MILLISECOND, 0);
                Date sessionDate0h = sessionCal.getTime();
                m_log.trace("sessionDate0h : " + sessionDate0h);

                //  + ?() + TIMEZONE
                long endDelay = sessionDate0h.getTime() + job.getEndDelayTimeValue() + TIMEZONE;
                m_log.trace("endDelayDate : " + new Date(endDelay));

                //??
                boolean endDelayCheck = endDelay <= HinemosTime.currentTimeMillis();
                m_log.trace("endDelayCheck : " + endDelayCheck);
                /*
                 * ?()???????
                 * checkDateMap??
                 */
                if (!endDelayCheck) {
                    addCheckDate(sessionId, endDelay);
                }
                result.add(endDelayCheck);
            } else {
                result.add(false);
            }
        }

        //AND???OR?????
        if (result.size() > 0) {
            if (job.getEndDelayConditionType() == ConditionTypeConstant.TYPE_AND) {
                //AND???
                delayCheck = true;
                for (Boolean flag : result) {
                    if (!flag) {
                        delayCheck = false;
                        break;
                    }
                }
            } else {
                //OR???
                delayCheck = false;
                for (Boolean flag : result) {
                    if (flag) {
                        delayCheck = true;
                        break;
                    }
                }
            }
        } else {
            delayCheck = false;
        }
        if (!delayCheck) {
            return false;
        }

        boolean operation = false;

        //
        if (job.getEndDelayNotify().booleanValue()) {
            //??
            int flg = sessionJob.getDelayNotifyFlg();
            //????
            int notifyFlg = DelayNotifyConstant.getNotify(flg);
            if (notifyFlg == DelayNotifyConstant.NONE || notifyFlg == DelayNotifyConstant.START) {
                //?????????????
                //?
                new Notice().delayNotify(sessionId, jobunitId, jobId, false);
                if (notifyFlg == DelayNotifyConstant.NONE) {
                    sessionJob.setDelayNotifyFlg(DelayNotifyConstant.END);
                } else if (notifyFlg == DelayNotifyConstant.START) {
                    sessionJob.setDelayNotifyFlg(DelayNotifyConstant.START_AND_END);
                }
            }
        }

        //?
        if (job.getEndDelayOperation().booleanValue()) {
            int type = job.getEndDelayOperationType();
            //??
            int flg = sessionJob.getDelayNotifyFlg();
            if (type == OperationConstant.TYPE_STOP_AT_ONCE) {
                //?[]
                //????
                int notifyFlg = DelayNotifyConstant.addOperation(flg, DelayNotifyConstant.STOP_AT_ONCE);
                sessionJob.setDelayNotifyFlg(notifyFlg);
                new OperateStopOfJob().stopJob(sessionId, jobunitId, jobId);
            } else if (type == OperationConstant.TYPE_STOP_SUSPEND) {
                //?[]
                //?????
                int operationFlg = DelayNotifyConstant.getOperation(flg);
                if (operationFlg != DelayNotifyConstant.STOP_SUSPEND) {
                    //????[]??
                    //????
                    int notifyFlg = DelayNotifyConstant.addOperation(flg, DelayNotifyConstant.STOP_SUSPEND);
                    sessionJob.setDelayNotifyFlg(notifyFlg);
                    new OperateSuspendOfJob().suspendJob(sessionId, jobunitId, jobId);
                }
            } else if (type == OperationConstant.TYPE_STOP_SET_END_VALUE) {
                //?[]
                //????
                int notifyFlg = DelayNotifyConstant.addOperation(flg, DelayNotifyConstant.STOP_SET_END_VALUE);
                sessionJob.setDelayNotifyFlg(notifyFlg);
                new OperateStopOfJob().stopJob(sessionId, jobunitId, jobId);
            }
            operation = true;
        }

        return operation;
    }

    /**
     * ????
     *
     * @param sessionId ID
     * @param jobId ID
     * @return 
     * @throws JobInfoNotFound
     */
    protected Integer checkEndStatus(String sessionId, String jobunitId, String jobId)
            throws JobInfoNotFound, InvalidRole {

        HinemosEntityManager em = new JpaTransactionManager().getEntityManager();

        m_log.debug("checkEndStatus() : sessionId=" + sessionId + ", jobId=" + jobId);

        //ID?ID???
        JobSessionJobEntity sessionJob = QueryUtil.getJobSessionJobPK(sessionId, jobunitId, jobId);
        // ?
        JobInfoEntity job = sessionJob.getJobInfoEntity();

        ArrayList<Integer> statusList = new ArrayList<Integer>();

        if (sessionJob.getJobInfoEntity().getJobType() == JobConstant.TYPE_JOB
                || sessionJob.getJobInfoEntity().getJobType() == JobConstant.TYPE_APPROVALJOB
                || sessionJob.getJobInfoEntity().getJobType() == JobConstant.TYPE_MONITORJOB) {
            //??

            //??
            Collection<JobSessionNodeEntity> collection = sessionJob.getJobSessionNodeEntities();
            for (JobSessionNodeEntity sessionNode : sessionJob.getJobSessionNodeEntities()) {

                Integer endValue = sessionNode.getEndValue();
                if (endValue == null) {
                    continue;
                }
                Integer status = null;
                if (endValue >= job.getNormalEndValueFrom() && endValue <= job.getNormalEndValueTo()) {
                    //??????
                    status = EndStatusConstant.TYPE_NORMAL;
                    statusList.add(status);
                } else if (endValue >= job.getWarnEndValueFrom() && endValue <= job.getWarnEndValueTo()) {
                    //??????
                    status = EndStatusConstant.TYPE_WARNING;
                    statusList.add(status);
                } else {
                    //??????
                    status = EndStatusConstant.TYPE_ABNORMAL;
                    statusList.add(status);
                }

                //???????
                if (job.getProcessMode() == ProcessingMethodConstant.TYPE_RETRY
                        && status == EndStatusConstant.TYPE_NORMAL) {
                    statusList.clear();
                    statusList.add(EndStatusConstant.TYPE_NORMAL);
                    break;
                }
            }
            //???????
            if (collection.size() == 0) {
                statusList.clear();
                statusList.add(EndStatusConstant.TYPE_ABNORMAL);
            }
        } else {
            //??

            Integer endStatusCheck = sessionJob.getEndStausCheckFlg();
            if (endStatusCheck == null || endStatusCheck == EndStatusCheckConstant.NO_WAIT_JOB) {
                //???????????

                //ID?ID???
                Collection<JobSessionJobEntity> collection = QueryUtil.getChildJobSessionJob(sessionId, jobunitId,
                        jobId);

                for (JobSessionJobEntity childSessionJob : collection) {

                    //????????
                    Collection<JobStartJobInfoEntity> targetJobList = null;
                    targetJobList = em
                            .createNamedQuery("JobStartJobInfoEntity.findByTargetJobId",
                                    JobStartJobInfoEntity.class)
                            .setParameter("sessionId", sessionId)
                            .setParameter("targetJobId", childSessionJob.getId().getJobId()).getResultList();

                    if (targetJobList.size() > 0) {
                        continue;
                    }

                    //?????????????
                    Integer endValue = childSessionJob.getEndValue();
                    if (endValue >= job.getNormalEndValueFrom() && endValue <= job.getNormalEndValueTo()) {
                        //??????
                        statusList.add(EndStatusConstant.TYPE_NORMAL);
                    } else if (endValue >= job.getWarnEndValueFrom() && endValue <= job.getWarnEndValueTo()) {
                        //??????
                        statusList.add(EndStatusConstant.TYPE_WARNING);
                    } else {
                        //??????
                        statusList.add(EndStatusConstant.TYPE_ABNORMAL);
                    }
                }
                //???????
                if (collection.size() == 0) {
                    statusList.clear();
                    statusList.add(EndStatusConstant.TYPE_ABNORMAL);
                }
            } else {
                //?

                //ID?ID???
                Collection<JobSessionJobEntity> collection = QueryUtil.getChildJobSessionJob(sessionId, jobunitId,
                        jobId);

                for (JobSessionJobEntity childSessionJob : collection) {

                    Integer endValue = childSessionJob.getEndValue();
                    if (endValue >= job.getNormalEndValueFrom() && endValue <= job.getNormalEndValueTo()) {
                        //??????
                        statusList.add(EndStatusConstant.TYPE_NORMAL);
                    } else if (endValue >= job.getWarnEndValueFrom() && endValue <= job.getWarnEndValueTo()) {
                        //??????
                        statusList.add(EndStatusConstant.TYPE_WARNING);
                    } else {
                        //??????
                        statusList.add(EndStatusConstant.TYPE_ABNORMAL);
                    }
                }
                //???????
                if (collection.size() == 0) {
                    statusList.clear();
                    statusList.add(EndStatusConstant.TYPE_ABNORMAL);
                }
            }
        }

        //?
        Integer endStatus = EndJudgment.judgment(statusList);

        return endStatus;
    }

    /**
     * ????
     *
     * @param sessionId ID
     * @param jobId ID
     * @return true:? false:??
     * @throws JobInfoNotFound
     * @throws InvalidRole
     * @throws HinemosUnknown
     * @throws FacilityNotFound 
     */
    private boolean checkCalendar(String sessionId, String jobunitId, String jobId)
            throws JobInfoNotFound, InvalidRole, HinemosUnknown, FacilityNotFound {
        m_log.debug("checkCalendar() : sessionId=" + sessionId + ", jobunitId=" + jobunitId + ", jobId=" + jobId);

        boolean check = false;

        //ID?ID???
        JobSessionJobEntity sessionJob = QueryUtil.getJobSessionJobPK(sessionId, jobunitId, jobId);

        JobSessionEntity session = sessionJob.getJobSessionEntity();
        JobInfoEntity job = sessionJob.getJobInfoEntity();

        //?
        if (job.getCalendar().booleanValue()) {
            try {
                //??/????
                if (new CalendarControllerBean().isRun(job.getCalendarId(), session.getScheduleDate())) {
                    check = true;
                }
            } catch (CalendarNotFound e) {
                // ???
            } catch (HinemosUnknown e) {
                // ???
            }
        } else {
            check = true;
        }

        //????
        if (!check) {
            // 
            Integer endStatus = job.getCalendarEndStatus();
            // 
            Integer endValue = job.getCalendarEndValue();
            //???
            setEndStatus(sessionId, jobunitId, jobId, StatusConstant.TYPE_END_CALENDAR, endStatus, endValue, null);
            //?
            endJob(sessionId, jobunitId, jobId, null, false);
        }
        return check;
    }

    /**
     * ???
     *
     * @param sessionId ID
     * @param jobId ID
     * @param status 
     * @param endStatus 
     * @param result ?
     * @throws JobInfoNotFound
     */
    private void setEndStatus(String sessionId, String jobunitId, String jobId, Integer status, Integer endStatus,
            Integer endValue, String result) throws JobInfoNotFound, InvalidRole {
        m_log.debug("setEndStaus() : sessionId=" + sessionId + ", jobId=" + jobId);

        //ID?ID???
        JobSessionJobEntity sessionJob = QueryUtil.getJobSessionJobPK(sessionId, jobunitId, jobId);
        // ??
        JobInfoEntity jobInfo = sessionJob.getJobInfoEntity();
        //
        sessionJob.setStatus(status);
        //
        Integer preEndStatus = sessionJob.getEndStatus();
        sessionJob.setEndStatus(endStatus);
        if (endValue != null) {
            sessionJob.setEndValue(endValue);
        } else {
            //
            if (Integer.valueOf(EndStatusConstant.TYPE_NORMAL).equals(endStatus)) {
                sessionJob.setEndValue(jobInfo.getNormalEndValue());
            } else if (Integer.valueOf(EndStatusConstant.TYPE_WARNING).equals(endStatus)) {
                sessionJob.setEndValue(jobInfo.getWarnEndValue());
            } else if (Integer.valueOf(EndStatusConstant.TYPE_ABNORMAL).equals(endStatus)) {
                sessionJob.setEndValue(jobInfo.getAbnormalEndValue());
            }
        }
        //
        sessionJob.setEndDate(HinemosTime.currentTimeMillis());
        //?
        sessionJob.setResult(result);

        //?
        //??????????
        if (preEndStatus == null || !preEndStatus.equals(endStatus)) {
            new Notice().notify(sessionId, jobunitId, jobId, endStatus);
        }
    }

    /**
     * ????
     *
     * @param sessionId ID
     * @param jobId ID
     * @throws JobInfoNotFound
     * @throws InvalidRole
     * @throws HinemosUnknown
     * @throws FacilityNotFound 
     */
    protected void endJob(String sessionId, String jobunitId, String jobId, String result, boolean normalEndFlag)
            throws JobInfoNotFound, InvalidRole, HinemosUnknown, FacilityNotFound {
        HinemosEntityManager em = new JpaTransactionManager().getEntityManager();
        m_log.info("endJob() : sessionId=" + sessionId + ", jobunitId=" + jobunitId + ", jobId=" + jobId);

        ////////// ?? //////////
        if (normalEndFlag) {
            //???
            Integer endStatus = checkEndStatus(sessionId, jobunitId, jobId);
            //???
            setEndStatus(sessionId, jobunitId, jobId, StatusConstant.TYPE_END, endStatus, null, result);
        }

        ////////// ???? //////////
        // (endJob?)????????
        Collection<JobStartJobInfoEntity> collection;
        collection = em.createNamedQuery("JobStartJobInfoEntity.findByTargetJobId", JobStartJobInfoEntity.class)
                .setParameter("sessionId", sessionId).setParameter("targetJobId", jobId).getResultList();
        ArrayList<JobSessionJobEntity> list = new ArrayList<JobSessionJobEntity>();
        for (JobStartJobInfoEntity startJob : collection) {
            //ID?ID???
            JobSessionJobEntity sessionJob = QueryUtil.getJobSessionJobPK(startJob.getId().getSessionId(),
                    startJob.getId().getJobunitId(), startJob.getId().getJobId());
            if (list.contains(sessionJob)) {
                m_log.debug("duplicate " + sessionJob.getId().toString());
            } else {
                list.add(sessionJob);
            }
        }
        for (JobSessionJobEntity sessionJob : list) {
            String startSessionId = sessionJob.getId().getSessionId();
            String startJobUnitId = sessionJob.getId().getJobunitId();
            String startJobId = sessionJob.getId().getJobId();
            int status = sessionJob.getStatus();
            if (status == StatusConstant.TYPE_WAIT || status == StatusConstant.TYPE_SKIP) {
                //???
                //??
                startJob(startSessionId, startJobUnitId, startJobId);
            }
        }

        ////////// ???endJob()? //////////
        //ID?ID???
        JobSessionJobEntity sessionJob = QueryUtil.getJobSessionJobPK(sessionId, jobunitId, jobId);
        //?ID?
        String parentJobunitId = null;
        String parentJobId = null;
        QueryUtil.getJobSessionJobPK(sessionId, sessionJob.getParentJobunitId(), sessionJob.getParentJobId());
        parentJobunitId = sessionJob.getParentJobunitId();
        parentJobId = sessionJob.getParentJobId();
        //????????
        boolean endAll = true;
        for (JobSessionJobEntity sessionJob1 : QueryUtil.getChildJobSessionJob(sessionId, parentJobunitId,
                parentJobId)) {
            //??????????
            if (!StatusConstant.isEndGroup(sessionJob1.getStatus())) {
                endAll = false;
                break;
            }
        }
        if (!endAll) {
            return;
        }
        //??????
        if (!CreateJobSession.TOP_JOB_ID.equals(parentJobId)) {
            //ID?ID???
            //????
            endJob(sessionId, parentJobunitId, parentJobId, null, true);
        }
    }

    /**
     * ??Double???????
     * @param value1 1
     * @param value2 2
     * @return ?
     */
    private int checkDecisionValue(String value1, String value2) {
        Double dValue01 = Double.parseDouble(value1);
        Double dValue02 = Double.parseDouble(value2);

        return dValue01.compareTo(dValue02);
    }
}