public class CapacityGrapCache extends ReloadableSpringBean {
private static final Logger logger = LoggerFactory.getLogger(CapacityGrapCache.class);
//中转流量流向基本数据
@StoreFillin(name = StoreNameConstants.STORE_TRANS_BATCH_CONVEYANCE_FLOW, type = StoreFillin.StoreType.EXTERNAL_QUERY_STORE)
private IExternalDataQueryStore transBatchConveyanceStore;
//运力缺口配置基本信息cache
private CvyBreachCfgCache breachCfgCache;
//运力缺口满载信息cache
private BreachFillCapacityCache breachFillCapacityCache;
//部门缓存
private DepartmentCache departmentCache;
//满载标准
private final double FULLCONVERY=0.8;
//存放快件路由信息集合
private Map>> expressBreachFilterMap = new ConcurrentHashMap>>();
//存放运力满载的集合
private List fullBreachList=new ArrayList();
private boolean isFirst=true;
@Override
public void reload(){
if(isFirst){
isFirst=false;
return;
}
//清空满载数据
fullBreachList.clear();
//用于快件路由的Map
Map> expressBreachCfgMap=new HashMap>();
//根据基础信息计算满载信息
this.calcBreachMap(expressBreachCfgMap);
//用于快件路由的Map
this.convertExpress(expressBreachCfgMap);
//判断是否满载
this.checkConveryFull(expressBreachCfgMap);
//清除快件路由Map缓存
this.clearExpressMap();
}
/**
* 根据基础信息计算满载信息
* Feb 26, 2015
* @param cvyBreachCfgMap
* @param expressBreachCfgMap
*/
private void calcBreachMap(Map> expressBreachCfgMap){
List cvyBreachCfgCfgList=breachCfgCache.getCvyBreachCfgCfgList();
Date curDate=new Date();
Map planBillWeightMap=new HashMap();
for(CvyBreachCfg breachBean:cvyBreachCfgCfgList){
StringBuilder builder=new StringBuilder();
builder.append(DateTimeFormatUtils.formatYyyyMmDd(curDate)).append("-");
builder.append(breachBean.getTransferBatchCode()).append("-");
builder.append(breachBean.getCargoCityCode()).append("-");
builder.append(breachBean.getTakegoodsZoneCode());
String planWeightKey=builder.toString();
//计算模糊应发重量
this.calcPlanDepartWeight(planBillWeightMap, breachBean, planWeightKey);
//设置模糊应发重量
breachBean.setBillWeight(planBillWeightMap.get(planWeightKey));
//设置快件路由需要的Map
this.setExpressMap(expressBreachCfgMap,breachBean);
}
}
/**
* 计算模糊应发重量
* Feb 28, 2015
* @param planBillWeightMap
* @param breachBean
* @param planWeightKey
* @return
*/
private Map calcPlanDepartWeight(Map planBillWeightMap,CvyBreachCfg breachBean,String planWeightKey){
Double actualPlanDepartBillWeightQty=0d;
if(!planBillWeightMap.containsKey(planWeightKey)){
QueryCapaCityConditon condition=findQueryCondition(breachBean);
StoreCriteria criteria = getStoreCriteria(condition);
try{
Collection keys=transBatchConveyanceStore.searchKeys(criteria);
if(!BlankUtil.isBlank(keys)){
Collection entities = transBatchConveyanceStore.get(keys);
for(TransBatchConveyanceFlowEntity transBatchConveyance:entities){
//产品类型
String productType=transBatchConveyance.getProductType();
if(productType.contains(breachBean.getProductType())){
actualPlanDepartBillWeightQty+=transBatchConveyance.getFuzzyPlanDepartBillWeightQty();
}
}
planBillWeightMap.put(planWeightKey, actualPlanDepartBillWeightQty);
}
}catch(Exception ce){
logger.warn("transBatchConveyanceStore search error!");
}
}
return planBillWeightMap;
}
/**
* 设置快件路由Map
* Feb 28, 2015
* @param expressBreachCfgMap
* @param breachKey
* @param breachBean
*/
private void setExpressMap(Map> expressBreachCfgMap,CvyBreachCfg breachBean){
List deptCodeList=null;
//判断区部代码是否为空
if(null!=breachBean.getSrcAreaCode()){
deptCodeList=departmentCache.getDeptListByArea(breachBean.getSrcAreaCode(),null);
}else if(null!=breachBean.getSrcCityCode()){
deptCodeList=departmentCache.getDeptListByCity(breachBean.getSrcCityCode(), null);
}else if(null!=breachBean.getSrcZoneCode()){
deptCodeList=new ArrayList();
deptCodeList.add(breachBean.getSrcZoneCode());
}
this.setCommonMap(breachBean, deptCodeList,expressBreachCfgMap);
}
/**
* 设置Map值
* Mar 19, 2015
* @param breachCfg
* @param deptCodeList
* @param expressBreachCfgMap
*/
private void setCommonMap(CvyBreachCfg breachCfg,List deptCodeList,Map> expressBreachCfgMap){
for(String deptCode:deptCodeList){
CvyBreachCfg cvyBreachCfg=null;
try{
cvyBreachCfg = (CvyBreachCfg)BeanUtilsBean.getInstance().cloneBean(breachCfg);
}catch(Exception ce){
logger.warn("clone CvyBreachCfg bean faild!",ce);
}
cvyBreachCfg.setSrcZoneCode(deptCode);
cvyBreachCfg.setTransferDate(DateTimeFormatUtils.parseYyyyMmDdSplit(this.getCurdateStr()));
StringBuilder builder=new StringBuilder();
builder.append(deptCode).append("-");
builder.append(breachCfg.getCargoCityCode()).append("-");
builder.append(breachCfg.getProductType()).append("-");
builder.append(deptCode+breachCfg.getPickupBatch());
String breachKey=builder.toString();
List breachList=null;
if((breachList=expressBreachCfgMap.get(breachKey))==null){
breachList=new ArrayList();
expressBreachCfgMap.put(breachKey, breachList);
}
breachList.add(cvyBreachCfg);
}
}
/**
* 设置查询条件
* Feb 10, 2015
* @param breachBean
* @return
*/
private QueryCapaCityConditon findQueryCondition(CvyBreachCfg breachBean){
QueryCapaCityConditon condition=new QueryCapaCityConditon();
Date curDate=new Date();
String versionDate="";
//跨越天数
if(!BlankUtil.isBlank(breachBean.getAcrossDay())){
if(breachBean.getAcrossDay()==0){
versionDate=DateTimeFormatUtils.formatYyyyMmDd(curDate);
}else{
versionDate=findAcorssDate(curDate,breachBean.getAcrossDay());
}
}else{
versionDate=DateTimeFormatUtils.formatYyyyMmDd(curDate);
}
condition.setDate(versionDate);
condition.setBatchCode(breachBean.getTransferBatchCode());
condition.setDestCity(breachBean.getCargoCityCode());
condition.setNextNodeCode(breachBean.getTakegoodsZoneCode());
return condition;
}
/**
* 获取Store查询对象
* Feb 10, 2015
* @param condition
* @return
*/
private StoreCriteria getStoreCriteria(QueryCapaCityConditon condition) {
StoreCriteria criteria = new StoreCriteria();
//日期
criteria.equal("date", condition.getDate());
//班次编码
criteria.equal("batchCode", condition.getBatchCode());
//配置代码
criteria.like("configCode", condition.getDestCity());
//下一环节网点
criteria.like("nextNodeCode", condition.getNextNodeCode());
//有效数据
criteria.equal("deleteFlag", 0);
return criteria;
}
/**
* 判断运力满载(应发重量/审核载量(百分比)大于80%(含)以上,则为运力满载。)
* Feb 26, 2015
* @param breachBean
*/
private void checkConveryFull(Map> expressBreachCfgMap){
Set breachSets=expressBreachCfgMap.keySet();
for(String breachKey:breachSets){
List breachList=expressBreachCfgMap.get(breachKey);
for(CvyBreachCfg breachBean:breachList){
if(!BlankUtil.isBlank(breachBean.getBillWeight())){
//模糊应发重量
Double shouldWeight=breachBean.getBillWeight();
//审核载量
Double checkLoad=breachBean.getCheckLoadCapacity();
double ratio=shouldWeight/checkLoad;
//满载
if(ratio>=FULLCONVERY){
fullBreachList.add(breachBean);
}
}
}
}
}
/**
* 设置快件路由需要的信息
* Feb 26, 2015
* @param expressBreachCfgMap
*/
private void convertExpress(Map> expressBreachCfgMap){
Set breachSets=expressBreachCfgMap.keySet();
for(String breachKey:breachSets){
List breachList=expressBreachCfgMap.get(breachKey);
Map> transferZoneMap=new HashMap>();
for(CvyBreachCfg breachCfg:breachList){
//流向
String takegoodsZoneCode=breachCfg.getTakegoodsZoneCode();
//机场
String transferZoneCode=breachCfg.getTransferZoneCode();
//流向-机场作为key
String transferZoneKey=takegoodsZoneCode+"-"+transferZoneCode;
List transferZoneList=null;
if((transferZoneList=transferZoneMap.get(transferZoneKey))==null){
transferZoneList=new ArrayList();
transferZoneMap.put(transferZoneKey, transferZoneList);
}
transferZoneList.add(breachCfg);
}
this.filterExpressMap(transferZoneMap,breachKey);
}
}
/**
* 根据原始Map,封装需要返回的Map
* 1、流向相同,机场相同,按班次升序排列,返回最早的班次(第一个)。
* 2、流向相同,机场不相同,返回多条。
* Feb 13, 2015
* @return
*/
private void filterExpressMap(Map> transferZoneMap,String breachKey){
Set transferZoneSet=transferZoneMap.keySet();
List breachCfgList=new ArrayList();
for(String transerZone:transferZoneSet){
CvyBreachCfg breachCfg=null;
List transerZoneList=transferZoneMap.get(transerZone);
if(transerZoneList.size()>1){
breachCfg=this.getFirsttransBatch(transerZoneList);
}else{
breachCfg=transerZoneList.get(0);
}
breachCfgList.add(breachCfg);
}
Long zeroDateTime=this.convertCureDateExpressMap(0);
if(!expressBreachFilterMap.containsKey(zeroDateTime)){
expressBreachFilterMap.put(zeroDateTime,new HashMap>());
}
expressBreachFilterMap.get(zeroDateTime).put(breachKey, breachCfgList);
}
/**
* 获取班次最早的一条数据
* Feb 13, 2015
* @param transerZoneList
* @return
*/
private CvyBreachCfg getFirsttransBatch(List transerZoneList){
List batchCodeList=new ArrayList();
Map transferBatchMap=new HashMap();
for(CvyBreachCfg breachCfg:transerZoneList){
//中转班次编码
String transferBatchCode=breachCfg.getTransferBatchCode();
batchCodeList.add(transferBatchCode);
transferBatchMap.put(transferBatchCode, breachCfg);
}
this.sortTransferBatchCode(batchCodeList);
String firstBatchCode=batchCodeList.get(0);
return transferBatchMap.get(firstBatchCode);
}
/**
* 班次编码排序
* Feb 13, 2015
* @param batchCodeList
*/
private void sortTransferBatchCode(List batchCodeList){
Comparator com = new Comparator() {
public int compare(String batchCode1, String batchCode2){
return batchCode1.compareTo(batchCode2);
}
};
Collections.sort(batchCodeList, com);
}
/**
* 获取当前日期
* Feb 9, 2015
* @return
*/
private String getCurdateStr(){
String month="";
String date="";
Calendar cal=Calendar.getInstance();
int y=cal.get(Calendar.YEAR);
int m=cal.get(Calendar.MONTH)+1;
int d=cal.get(Calendar.DATE);
if(m<10){
month="0"+m;
}else{
month=m+"";
}
if(d<10){
date="0"+d;
}else{
date=d+"";
}
String curDateStr=y+"-"+month+"-"+date;
return curDateStr;
}
/**
* 提供给快件路由调用
* Mar 6, 2015
* @param srcZoneCode
* @param cargoCityCode
* @param produceType
* @param pickupBatch
* @return
*/
public List findFullConveryInfo(String srcZoneCode,String cargoCityCode,String produceType,String pickupBatch){
StringBuilder builder=new StringBuilder();
builder.append(srcZoneCode).append("-");
builder.append(cargoCityCode).append("-");
builder.append(produceType).append("-");
builder.append(pickupBatch);
String mapKey=builder.toString();
List list = null;
for(Map> breachMap:expressBreachFilterMap.values()){
if (breachMap.containsKey(mapKey)) {
list = breachMap.get(mapKey);
break;
}
}
return list;
}
/**
* 如果不是当前日期,就从满载缓存获取数据提供给快件路由
* Mar 13, 2015
* @param srcZoneCode
* @param cargoCityCode
* @param produceType
* @param pickupBatch
* @return
*/
public List findCapacityFullInfo(String srcZoneCode,String cargoCityCode,String produceType,String pickupBatch,Date versionDate){
StringBuilder builder=new StringBuilder();
builder.append(srcZoneCode).append("-");
builder.append(cargoCityCode).append("-");
builder.append(produceType).append("-");
builder.append(pickupBatch);
String mapKey=builder.toString();
Map>> capacityFillMap=breachFillCapacityCache.getCapacityFillMap();
List list = null;
if(!BlankUtil.isBlank(capacityFillMap)){
Long versionDateTime=breachFillCapacityCache.getZeroTime(versionDate);
Map> breachMap=capacityFillMap.get(versionDateTime);
if(!BlankUtil.isBlank(breachMap)){
logger.info("find expressVersionDate mapKey:"+mapKey);
if (breachMap.containsKey(mapKey)) {
list = breachMap.get(mapKey);
logger.info("find expressVersionDate mapKey List size:"+list.size());
}
}
}
return list;
}
/**
* 获取凌晨时间点
* Mar 12, 2015
*/
private Long convertCureDateExpressMap(int addDays){
Date curDate=new Date();
Date keyTime=DateTimeUtils.addTimes(curDate,addDays,DateTimeUtils.TIME_TYPE_DATE);
String zeroDateStr = DateTimeFormatUtils.formatYyyyMmDdSplit(keyTime);
Date zeroDate = DateTimeFormatUtils.parseYyyyMmDdSplit(zeroDateStr);
long zeroDateTime = zeroDate.getTime();
return zeroDateTime;
}
/**
* 清除1天以前的快件路由缓存
* Mar 12, 2015
*/
private void clearExpressMap(){
//获取1天以前的数据
Long beforeTwozeroDateTime=this.convertCureDateExpressMap(-1);
Set dateSets=expressBreachFilterMap.keySet();
for(Long zeroTime :dateSets){
if(zeroTime<=beforeTwozeroDateTime){
expressBreachFilterMap.remove(zeroTime);
}
}
}
/**
* 获取跨越天数后的日期
* Mar 16, 2015
* @param curDate
* @param acrossDay
* @return
*/
@SuppressWarnings("unchecked")
private String findAcorssDate(Date curDate,Integer acrossDay){
Calendar calendar = new GregorianCalendar();
calendar.setTime(curDate);
calendar.add(calendar.DATE,acrossDay);//把日期往后增加acrossDay天
curDate=calendar.getTime();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String dateString = formatter.format(curDate);
String versionDate=dateString.replace("-", "");
return versionDate;
}
public void setTransBatchConveyanceStore(
IExternalDataQueryStore transBatchConveyanceStore) {
this.transBatchConveyanceStore = transBatchConveyanceStore;
}
public CvyBreachCfgCache getBreachCfgCache() {
return breachCfgCache;
}
public void setBreachCfgCache(CvyBreachCfgCache breachCfgCache) {
this.breachCfgCache = breachCfgCache;
}
public List getFullBreachList() {
return fullBreachList;
}
public void setFullBreachList(List fullBreachList) {
this.fullBreachList = fullBreachList;
}
public BreachFillCapacityCache getBreachFillCapacityCache() {
return breachFillCapacityCache;
}
public void setBreachFillCapacityCache(
BreachFillCapacityCache breachFillCapacityCache) {
this.breachFillCapacityCache = breachFillCapacityCache;
}
public DepartmentCache getDepartmentCache() {
return departmentCache;
}
public void setDepartmentCache(DepartmentCache departmentCache) {
this.departmentCache = departmentCache;
}