SchedulePlanServiceImpl.java 12.7 KB
package com.bsth.service.schedule.impl;

import com.bsth.entity.schedule.SchedulePlan;
import com.bsth.repository.BusinessRepository;
import com.bsth.repository.LineRepository;
import com.bsth.repository.schedule.*;
import com.bsth.service.schedule.SchedulePlanService;
import com.bsth.service.schedule.exception.ScheduleException;
import com.bsth.service.schedule.impl.plan.DroolsSchedulePlan;
import com.bsth.service.schedule.impl.plan.ScheduleRuleService;
import com.bsth.service.schedule.plan.process._1_validate._1_timetable.PlanProcessValidateTimetableService;
import com.bsth.service.schedule.plan.process._1_validate._1_timetable.PlanProcessValidateTimetableServiceDroolsImpl;
import com.bsth.service.schedule.plan.process._1_validate._2_rule.PlanProcessValidateRuleService;
import com.bsth.service.schedule.plan.process._1_validate._2_rule.PlanProcessValidateRuleServiceDroolsImpl;
import org.joda.time.DateTime;
import org.kie.api.KieBase;
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.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by xu on 16/6/16.
 */
@Service
public class SchedulePlanServiceImpl extends BServiceImpl<SchedulePlan, Long> implements SchedulePlanService {
    @Autowired
    @Qualifier("coreKBase")
    private KieBase coreKBase;

    @Autowired
    @Qualifier("preKBase")
    private KieBase preKBase;

    @Autowired
    private ScheduleRule1FlatRepository scheduleRule1FlatRepository;
    @Autowired
    private TTInfoRepository ttInfoRepository;
    @Autowired
    private TTInfoDetailRepository ttInfoDetailRepository;
    @Autowired
    private LineRepository lineRepository;
    @Autowired
    private CarConfigInfoRepository carConfigInfoRepository;
    @Autowired
    private GuideboardInfoRepository guideboardInfoRepository;
    @Autowired
    private EmployeeConfigInfoRepository employeeConfigInfoRepository;
    @Autowired
    private BusinessRepository businessRepository;
    @Autowired
    private ScheduleRuleService scheduleRuleService;
    @Autowired
    private RerunRuleRepository rerunRuleRepository;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /** 日志记录器 */
    private Logger logger = LoggerFactory.getLogger(SchedulePlanServiceImpl.class);

    /** 线路独占锁 */
    private ConcurrentHashMap<Integer, ReentrantLock> lineXLatchMaps = new ConcurrentHashMap<>();
    private ReentrantLock getLineXLatch(Integer xlid) {
        ReentrantLock lineXLatch = lineXLatchMaps.get(xlid);
        if (lineXLatch == null) {
            lineXLatch = new ReentrantLock();
            ReentrantLock pre = lineXLatchMaps.putIfAbsent(xlid, lineXLatch);
            if (pre != null) {
                lineXLatch = pre;
            }
        }
        return lineXLatch;
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    public SchedulePlan save(SchedulePlan schedulePlan) {
        ReentrantLock lineXLatch = getLineXLatch(schedulePlan.getXl().getId());
        try {
            if (lineXLatch.tryLock(1, TimeUnit.SECONDS)) {
                // pre、如果排班的数据之前已经有了,删除之前的数据
                Date startPre = new Date();
                scheduleRuleService.deleteSchedulePlanInfo(
                        schedulePlan.getXl().getLineCode(),
                        schedulePlan.getScheduleFromTime(),
                        schedulePlan.getScheduleToTime());
                Date endPre = new Date();
                logger.info("删除数据 {} ms --->", endPre.getTime() - startPre.getTime());

                // core、生成排班计划
                DroolsSchedulePlan droolsSchedulePlan = new DroolsSchedulePlan(
                        schedulePlan,
                        lineRepository, scheduleRule1FlatRepository,
                        ttInfoRepository, ttInfoDetailRepository,
                        carConfigInfoRepository, employeeConfigInfoRepository,
                        rerunRuleRepository, businessRepository,
                        scheduleRuleService,
                        preKBase, coreKBase,
                        logger
                );
                droolsSchedulePlan.generatePlan();

                return new SchedulePlan();
            } else {
                throw new ScheduleException("当前线路正在排班,请稍后再操作...");
            }
        } catch (Exception exp) {
            throw new RuntimeException(exp);
        } finally {
            try {
                lineXLatch.unlock();
            } catch (Exception exp2) {

            }

        }

    }

    @Override
    public void delete(Long aLong) throws ScheduleException {
        scheduleRuleService.deleteSchedulePlanAll(aLong);
    }

    @Override
    public SchedulePlan findSchedulePlanTommorw() {
        DateTime today = new DateTime(new Date());
        DateTime tommorw = new DateTime(
                today.getYear(), today.getMonthOfYear(),
                today.getDayOfMonth(), 0, 0).plusDays(1);
        Map<String, Object> param = new HashMap<>();
        param.put("scheduleFromTime_le", tommorw.toDate());
        param.put("scheduleToTime_ge", tommorw.toDate());
        Iterator<SchedulePlan> schedulePlanIterator = this.list(param).iterator();
        if (schedulePlanIterator.hasNext()) {
            return schedulePlanIterator.next();
        }
        return null;
    }

    @Autowired
    @Qualifier("kBaseValidateTimetable_plus")
    private KieBase kBaseValidateTimetable;
    @Override
    public PlanProcessValidateTimetableService.Result validateTTInfo(Integer xlId, Date from, Date to) {
        // 使用builder创建服务
        PlanProcessValidateTimetableService planProcessValidateTimetableService =
                PlanProcessValidateTimetableServiceDroolsImpl.getBuilder()
                        .setkBaseValidateTimetable(kBaseValidateTimetable)
                        .setJdbcTemplate(jdbcTemplate)
                        .build();
        PlanProcessValidateTimetableService.Result result =
                planProcessValidateTimetableService.validateTTInfovalidateTTInfo(xlId, from, to);
        return result;

//        // 构造drools session->载入数据->启动规则->计算->销毁session
//        // 创建session,内部配置的是stateful
//        KieSession session = validateKBase.newKieSession();
//        // 设置gloable对象,在drl中通过别名使用
//        session.setGlobal("log", logger);
//        session.setGlobal("tTInfoDetailRepository", ttInfoDetailRepository);
//
//        Result rs = new Result(); // 输出gloable对象
//        session.setGlobal("rs", rs);
//
//        // 载入数据
//        Line line = lineRepository.findOne(xlid);
//        session.insert(line);
//
//        CalcuParam calcuParam = new CalcuParam(
//                new DateTime(from), new DateTime(to), xlid);
//        session.insert(calcuParam);
//        List<TTInfo> ttInfos = ttInfoRepository.findByXlId(xlid);
//        for (TTInfo ttInfo: ttInfos) {
//            session.insert(ttInfo);
//        }
//
//        // 执行rule
//        session.fireAllRules();
//
//        // 执行完毕销毁,有日志的也要关闭
//        session.dispose();
//
//        return rs;
    }

    @Autowired
    @Qualifier("kBaseValidateRule_plus")
    private KieBase kBaseValidateRule;
    @Override
    public PlanProcessValidateRuleService.Result validateRule(Integer xlId, Date from, Date to) {
        // 使用builder创建服务
        PlanProcessValidateRuleService planProcessValidateRuleService =
                PlanProcessValidateRuleServiceDroolsImpl.getBuilder()
                        .setkBaseValidateRule(kBaseValidateRule)
                        .setJdbcTemplate(jdbcTemplate)
                        .build();

        PlanProcessValidateRuleService.Result result =
                planProcessValidateRuleService.validateRule(xlId, from, to);
        return result;


//        KieSession session = validateKBase.newKieSession();
//        session.setGlobal("LOG", logger);
//        session.setGlobal("ccRepo", carConfigInfoRepository);
//        session.setGlobal("lpRepo", guideboardInfoRepository);
//        session.setGlobal("ecRepo", employeeConfigInfoRepository);
//        session.setGlobal("ruleRepo", scheduleRule1FlatRepository);
//
//        ValidateRuleResult result = new ValidateRuleResult();
//        session.setGlobal("result", result);
//
//        com.bsth.service.schedule.impl.plan.kBase3.validate.rule.CalcuParam calcuParam =
//                new com.bsth.service.schedule.impl.plan.kBase3.validate.rule.CalcuParam();
//        calcuParam.setXlId(xlId);
//        calcuParam.setFromDate(new DateTime(from));
//        calcuParam.setToDate(new DateTime(to));
//        session.insert(calcuParam);
//
//        session.fireAllRules();
//
//        session.dispose();;
//
//        return result;
    }


    public Map<String,Object> listwest(Map map){

        SimpleDateFormat sfd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String line = map.get("line").toString();
        String page = map.get("page").toString();
        Map<String, Object> modelMap = new HashMap<String, Object>();
        String fgs="";
        if(map.get("fgsdm")!=null){
            fgs=map.get("fgsdm").toString();
        }

        String sql ="" +
                "SELECT sp.xl as xl,sp.tt_info_names as tt_info_name, " +
                "  sp.schedule_from_time as from_time ,sp.schedule_to_time as to_time, " +
                "  line.name as name , us.user_name as uname, " +
                "  sp.update_date as updata_date,bu.business_name as business_name  " +
                "  from bsth_c_s_sp sp " +
                "  LEFT JOIN bsth_c_line  line on sp.xl = line.line_code   " +
                "  left join bsth_c_sys_user us  on sp.update_by = us.id " +
                "  LEFT JOIN bsth_c_business bu on line.branche_company = bu.business_code " +
                "  where   sp.id in (select max(id) from bsth_c_s_sp spt  where plan_result ='ok' GROUP BY spt.xl)" +
                "  and line.name not like '%测试线路%' and sfyy = '1' " +
                "  and line.destroy = '0'  " ;
        if(!fgs.equals(" ") && !fgs.equals("")){
            sql +=" and line.branche_company = '"+fgs+"'";
        }
        if(!line.equals(" ") && !line.equals("")){
            sql += "and sp.xl="+line;
        }

        sql += " ORDER BY sp.schedule_from_time desc,sp.tt_info_names ;";
        List<Map> list = null;
        try {
              list = jdbcTemplate.query(sql, new RowMapper<Map>() {
                @Override
                public Map mapRow(ResultSet rs, int rowNum) throws SQLException {
                    Map map = new HashMap();
                    map.put("xl", rs.getString("xl"));
                    map.put("ttInfoName", rs.getString("tt_info_name"));
                    map.put("fromTime",rs.getDate("from_time"));
                    map.put("toTime", rs.getDate("to_time"));
                    map.put("name", rs.getString("name"));
                    map.put("uName", rs.getString("uname"));
                    map.put("updataDate", rs.getString("updata_date"));
                    map.put("businessName", rs.getString("business_name"));
                    return map;
                }

            });

            for (Map m : list) {
                m.put("updataDate", sfd.format(sfd.parse(m.get("updataDate").toString())));
            }
        }catch (Exception e){
            e.printStackTrace();
        }


        //分页
        if(page.length() != 0 ){
            int currPage = Integer.valueOf(page);
            modelMap.put("totalPage", list.size()%10>0?(list.size()/10 + 1):list.size()/10);
//			modelMap.put("dataList", resList.subList(currPage*10,((currPage+1)*10)>=resList.size()?resList.size():(currPage+1)*10));
            modelMap.put("list", list);
        } else {
            modelMap.put("dataList", list);
        }


        return modelMap;
    }
}