/** * */ package com.ycsoft.business.component.config; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.springframework.beans.factory.BeanFactory; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.stereotype.Component; import com.ycsoft.beans.config.TAddress; import com.ycsoft.beans.config.TPublicAcctitem; import com.ycsoft.beans.config.TRuleDefine; import com.ycsoft.beans.core.acct.CAcctBank; import com.ycsoft.beans.core.cust.CCust; import com.ycsoft.beans.core.fee.CFee; import com.ycsoft.beans.core.fee.CFeeDevice; import com.ycsoft.beans.core.prod.CProd; import com.ycsoft.beans.core.user.CUser; import com.ycsoft.beans.core.user.CUserAtv; import com.ycsoft.beans.core.user.CUserBroadband; import com.ycsoft.beans.core.user.CUserDtv; import com.ycsoft.beans.core.user.CUserStb; import com.ycsoft.beans.system.SOptr; import com.ycsoft.business.commons.pojo.BusiParameter; import com.ycsoft.business.dao.config.TAddressDao; import com.ycsoft.business.dao.config.TRuleDefineDao; import com.ycsoft.business.dao.config.TRuleEditDao; import com.ycsoft.business.dao.core.acct.CAcctBankDao; import com.ycsoft.business.dao.core.cust.CCustDao; import com.ycsoft.business.dao.core.fee.CFeeDao; import com.ycsoft.business.dao.core.fee.CFeeDeviceDao; import com.ycsoft.business.dao.core.prod.CProdDao; import com.ycsoft.business.dao.core.user.CUserAtvDao; import com.ycsoft.business.dao.core.user.CUserDao; import com.ycsoft.business.dao.core.user.CUserDtvDao; import com.ycsoft.business.dao.prod.PPromotionDao; import com.ycsoft.business.dto.core.acct.AcctitemDto; import com.ycsoft.business.dto.core.prod.CProdDto; import com.ycsoft.commons.constants.StatusConstants; import com.ycsoft.commons.constants.SystemConstants; import com.ycsoft.commons.exception.ComponentException; import com.ycsoft.commons.helper.BeanHelper; import com.ycsoft.commons.helper.DateHelper; import com.ycsoft.commons.helper.LoggerHelper; import com.ycsoft.commons.helper.StringHelper; import com.ycsoft.daos.core.JDBCException; /** * @author liujiaqi * */ //@Component public class ExpressionUtil { private static final String [] replaceParmer={"ACCTITEM","times","BALANCE"}; private static String[] datefunname= {"TODAY","THISYEAR","THISMONTH"}; //不再使用 //public ExpressionUtil(){} public ExpressionUtil(BeanFactory beanFactory) { tAddressDao=beanFactory.getBean(TAddressDao.class); //private CCustDao cCustDao; cCustDao=beanFactory.getBean(CCustDao.class); //private CFeeDeviceDao cFeeDeviceDao; cFeeDeviceDao=beanFactory.getBean(CFeeDeviceDao.class); //private CUserDao cUserDao; cUserDao=beanFactory.getBean(CUserDao.class); // private CUserDtvDao cUserDtvDao; cUserDtvDao=beanFactory.getBean(CUserDtvDao.class); // private CUserAtvDao cUserAtvDao; cUserAtvDao=beanFactory.getBean(CUserAtvDao.class); // private TRuleEditDao tRuleEditDao; tRuleEditDao=beanFactory.getBean(TRuleEditDao.class); // private TRuleDefineDao tRuleDefineDao; tRuleDefineDao=beanFactory.getBean(TRuleDefineDao.class); // @SuppressWarnings("unused") // private PPromotionDao pPromotionDao; pPromotionDao=beanFactory.getBean(PPromotionDao.class); // private CFeeDao cFeeDao; cFeeDao=beanFactory.getBean(CFeeDao.class); // private CProdDao cProdDao; cProdDao=beanFactory.getBean(CProdDao.class); // private CAcctBankDao cAcctBankDao; cAcctBankDao=beanFactory.getBean(CAcctBankDao.class); } private TAddressDao tAddressDao; private CCustDao cCustDao; private CFeeDeviceDao cFeeDeviceDao; private CUserDao cUserDao; private CUserDtvDao cUserDtvDao; private CUserAtvDao cUserAtvDao; private TRuleEditDao tRuleEditDao; private TRuleDefineDao tRuleDefineDao; @SuppressWarnings("unused") private PPromotionDao pPromotionDao; private CFeeDao cFeeDao; private CProdDao cProdDao; private CAcctBankDao cAcctBankDao; List<TPublicAcctitem> allAcctitem = null; private CCust ccust; private CUser cuser; private CUserDtv cuserdtv; private CUserAtv cuseratv; private CUserBroadband cuserBroadband; private CUserStb cuserStb; private CFeeDevice stb; private List<CFee> payacctitem;//当日支付的费用 private List<AcctitemDto> balanceacctitem;//账户余额 private List<CProdDto> orderprods; private Map<String,Integer> acctitemSumMap; private Date TODAY = DateHelper.today(); private SOptr optr ; public void setAllValue(CCust cust, CUser user, CUserDtv userdtv, CUserAtv useratv, CUserBroadband userBroadband, List<CFee> feeList,List<AcctitemDto> balanceList,List<CProdDto> prodList) { ccust = cust; setCuser(user); cuserdtv = userdtv; cuseratv = useratv; cuserBroadband = userBroadband; payacctitem = feeList; balanceacctitem = balanceList; orderprods = prodList; converNull(); } public void setAllValue(BusiParameter busiParam, List<CFee> feeList, List<AcctitemDto> balanceList,List<CProdDto> prodList) { ccust = busiParam.getCust(); cuser = busiParam.getSelectedUsers().size() > 0 ? busiParam .getSelectedUsers().get(0) : null; // cuserdtv = busiParam.getSelectedDtvs().size() > 0 ? busiParam // .getSelectedDtvs().get(0) : null; // cuseratv = busiParam.getSelectedAtvs().size() > 0 ? busiParam // .getSelectedAtvs().get(0) : null; // cuserBroadband = busiParam.getSelectedBands().size() > 0 ? busiParam // .getSelectedBands().get(0) : null; payacctitem = feeList; balanceacctitem = balanceList; orderprods = prodList; optr = busiParam.getOptr(); converNull(); } private void converNull(){ BeanHelper.setNullPropertyEmptyString(ccust); BeanHelper.setNullPropertyEmptyString(cuser); BeanHelper.setNullPropertyEmptyString(cuserdtv); BeanHelper.setNullPropertyEmptyString(cuseratv); BeanHelper.setNullPropertyEmptyString(cuserBroadband); BeanHelper.setNullPropertyEmptyString(optr); } public String afterDate(int day){ return DateHelper.format(DateHelper.addDate(new Date(),day)); } public String dateToString(Date d){ return DateHelper.format(d); } public boolean parseBoolean(String ruleStr,String... params) { if (StringHelper.isEmpty(ruleStr)) return true; try { context.setRootObject(this); for (int i = 0; i < params.length; i++) { getVariable("#param" + i + "=" + params[i]); } ruleStr = ruleParamerReplace(ruleStr); setupPayacctitem(); setupBalanceacctitem(); loadData(ruleStr); return getVariable(ruleStr, Boolean.class); } catch (Exception e) { LoggerHelper.error(getClass(), "表达式解析错误:"+ruleStr+e.getMessage()); return false; } } //装填缴费数据 private void setupPayacctitem() throws JDBCException { if (payacctitem != null){ for (CFee f : payacctitem) { getVariable("#ACCTITEM_" + f.getAcctitem_id() + "=" + f.getReal_pay()); } } } //装填账户余额数据 private void setupBalanceacctitem() throws JDBCException { if (balanceacctitem != null){ for (AcctitemDto f : balanceacctitem) { getVariable("#BALANCE_" + f.getAcctitem_id() + "=" + (f.getActive_balance()-f.getReal_fee())); } } } public CProdDto prods(String prodid) throws JDBCException { if (orderprods != null){ for (CProdDto f : orderprods) { if(f.getProd_id().equals(prodid)) return f; } } return new CProdDto(); } /** * ruleStr 有包含条件变量 times,计算满足times的最大正整数值,最大值不超过repetitionTimes * @param ruleStr 表达式 * @param repetitionTimes 最大值 * @return 满足的最大正整数 * @throws Exception */ public Integer parsePromotion(String ruleStr, Integer repetitionTimes) throws Exception { if (StringHelper.isEmpty(ruleStr)) return 0; context.setRootObject(this); ruleStr = ruleParamerReplace(ruleStr); setupPayacctitem(); setupBalanceacctitem(); loadData(ruleStr); acctitemSumMap = new HashMap<String ,Integer>(); double times=repetitionTimes; while (times > 0) { getVariable("#times=" + times); try { if (getVariable(ruleStr, Boolean.class)) { break; } } catch (Exception e) { LoggerHelper.error(getClass(), "表达式解析错误:" + ruleStr + e.getMessage()); return 0; } times -= 1; } // if (times < repetitionTimes){ // for (int i=1;i<10;i++){ // times=times+0.1; // getVariable("#times=" + times); // try { // if (!getVariable(ruleStr, Boolean.class)) { // break; // } // } catch (Exception e) { // } // } // times = times -0.1; // } return (int)(times*10); } private void loadData(String ruleStr) throws Exception { if (cuser != null && StringHelper.isNotEmpty(cuser.getStb_id())&&ruleStr.indexOf("stb.")>=0) stb = cFeeDeviceDao.queryByStbId(cuser.getStb_id()); if (cuser != null &&ruleStr.indexOf(".unit_id")>=0){ List<CCust> units = cCustDao.queryUnitByResident(ccust.getCust_id(),ccust.getCounty_id()); if (units!=null && units.size()>0) ccust.setUnit_id(units.get(0).getCust_id()); } if (ccust != null && ruleStr.indexOf(".user_count") >= 0) { ccust.setUser_count(cUserDao.queryUserCount(ccust.getCust_id())); } if (ccust != null && ruleStr.indexOf(".user_count_dtv") >= 0) { //ccust.setUser_count_dtv(cUserDao.queryUserByCustId(ccust.getCust_id(),SystemConstants.USER_TYPE_DTV).size()); } if (ccust != null && ruleStr.indexOf(".is_bank") >= 0) { CAcctBank acctBank = cAcctBankDao.findByCustId(ccust.getCust_id()); if (acctBank != null && acctBank.getStatus().equals(StatusConstants.ACTIVE)) ccust.setIs_bank("T"); } if(cuser != null && ruleStr.indexOf(".seq")>=0){ cuser.setSeq(cUserDao.queryUserSequence(cuser.getCust_id(),cuser.getUser_id())); } // System.out.println(ruleStr); } public boolean parseBoolean(String ruleId, Map<String, Object> params) { if (StringHelper.isEmpty(ruleId)) return true; try { List<String> modelNames = tRuleEditDao.queryModelByRule(ruleId); TRuleDefine rule = tRuleDefineDao.findByKey(ruleId); String names = ""; for (String n : modelNames) names += n + ","; setupDateByModelNames(params, names); if (params.get("prod_id")!=null) getVariable("#prod_id='" + params.get("prod_id")+"'"); return parseBoolean(rule.getRule_str()); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 加载数据 * * @param data * @param modelName */ private void setupDateByModelNames(Map<String, Object> params, String modelName) throws JDBCException, ComponentException { if (modelName.indexOf("CUSERDTV,") > -1 ) { String userId = (String) params.get("userId"); if (StringHelper.isEmpty(userId)) { throw new ComponentException("表达式缺少必要的参数"); } CUserDtv user = cUserDtvDao.queryDtvById(userId); if (user != null){ params.put("custId", user.getCust_id()); setCuserdtv(user); } } if (modelName.indexOf("CUSERATV,") > -1) { String userId = (String) params.get("userId"); if (StringHelper.isEmpty(userId)) { throw new ComponentException("表达式缺少必要的参数"); } CUserAtv user = cUserAtvDao.queryAtvById(userId); if (user != null){ params.put("custId", user.getCust_id()); setCuseratv(user); } } if (modelName.indexOf("CUSER,") > -1) { String userId = (String) params.get("userId"); if (StringHelper.isEmpty(userId)) { throw new ComponentException("表达式缺少必要的参数"); } CUser user = cUserDao.findByKey(userId); if (user != null){ params.put("custId", user.getCust_id()); setCuser(user); } } if (modelName.indexOf("CCUST,") > -1) { String custId = (String) params.get("custId"); if (StringHelper.isEmpty(custId)) { throw new ComponentException("表达式缺少必要的参数"); } CCust cust = cCustDao.findByKey(custId); setCcust(cust); } } /** * 一.将replaceParmer 定义参数开头的参数,如果参数为空,设置为0 * 原因:SPEL对于空的参数进行逻辑操作时返回结果都是为ture的 * 如:表达式为ACCTITEM_100000>1000,当ACCTITEM_100000为空时,表达式返回的是true,应该返回为false * * 二.将表达式中,以replaceParmer 定义参数开头的参数,都加前缀 # * 原因:SPEL动态定义的变量都需要在参数前加上 #号 * @param ruleStr * @return */ private String ruleParamerReplace(String ruleStr) { String comStr = ""; for (String p:replaceParmer){ comStr += p + "_[0-9]+|"; ruleStr = ruleStr.replace(p, "#"+p); } comStr = comStr.substring(0, comStr.length() - 1); Pattern pattern = Pattern.compile(comStr); Matcher matcher = pattern.matcher(ruleStr); while (matcher.find()) { getVariable("#" + matcher.group() + "=0"); } ruleStr = converDateFunction(ruleStr); return ruleStr; } private static String converDateFunction(String ruleStr) { ruleStr = " " +ruleStr+" "; for (String s : datefunname) { int end = ruleStr.indexOf("=="+s) ; while (end > -1) { String tt = ruleStr.substring(ruleStr.substring(0, end).lastIndexOf(" ")+1,end+s.length()+2); ruleStr = ruleStr.replace(tt, s+"("+tt.replaceAll("=="+s, ")")); end = ruleStr.indexOf("=="+s) ; } } return ruleStr; } public boolean inAddr(String... addrid) throws JDBCException { if (ccust == null) return false; if (ccust.getAddr_id().equals(addrid)) return true; List<TAddress> addrs = tAddressDao.queryAddrByPid(ccust.getAddr_id(),addrid); return addrs.size() == 0 ? false : true; } public boolean prodTariff(String prodId,String tariffId){ for(CProd prod : orderprods){ if(prod.getProd_id().equals(prodId) && prod.getTariff_id().equals(tariffId)){ return true; } } return false; } /** * * 统计指定时间段,指定账目的有效缴费金额(分) * @param acctItemId * @param bDate * @param eDate * @return * @throws JDBCException */ public Integer sumPayFee(String acctItemId,String bDate,String eDate) throws JDBCException{ if (cuser != null && StringHelper.isNotEmpty(cuser.getUser_id())) return cFeeDao.queryFeeByDate(cuser.getUser_id(),acctItemId,bDate,eDate); return 0; } public int acctitem(String acctItemId, Integer days) throws JDBCException { if (cuser != null && StringHelper.isNotEmpty(cuser.getUser_id())) { Integer sum = acctitemSumMap.get(acctItemId + days); if (sum == null) { sum = cFeeDao.queryBeforeAllFees(cuser.getCust_id(),cuser.getUser_id(), acctItemId, days); acctitemSumMap.put(acctItemId + days, sum); } return sum; } return 0; } /** * 查找用户下的订购的指定产品 * @param acctItemId * @return * @throws JDBCException */ public CProd orderPord(String acctItemId) throws JDBCException{ if (cuser != null ){ return cProdDao.queryProdsByUserProd(cuser.getUser_id(),acctItemId); } return null; } /** * 查找客户户下的订购的指定产品 * @param acctItemId * @return * @throws JDBCException */ public List<CProd> orderPordByCust(String prodId) throws JDBCException{ if (ccust != null ){ return cProdDao.queryProdsByCustProd(ccust.getCust_id(),prodId); } return null; } /** * 通过规则Id查询 * @param ruleId * @return * @throws JDBCException */ public TRuleDefine queryByRuleId(String ruleId) throws JDBCException{ return tRuleDefineDao.findByKey(ruleId); } /** * 查找用户下的订购的指定产品类型的最晚日期 * @param prodType * @return * @throws JDBCException */ public Date laterOrderByType(String prodType) throws JDBCException { if (cuser != null) { CProd cprod = cProdDao.queryLaterOrderDateByProdType(cuser .getUser_id(), prodType); if (cprod != null) return cprod.getOrder_date(); } return null; } /** * 统计指定产品缴费月份数,当天 * @return * @throws Exception */ public int payMonthsOfToday(String acctitemId) throws Exception { int months = 0; if (cuser != null) { months = cProdDao.payMonthsOfToday(cuser.getUser_id(), acctitemId); } return months; } public Boolean TODAY(Date d){ return DateHelper.isToday(d); } public Boolean THISMONTH(Date d){ return DateHelper.dateToStr(d).substring(0, 7).equals(DateHelper.formatNow().substring(0, 7)); } public Boolean THISYEAR(Date d){ return DateHelper.dateToStr(d).substring(0, 4).equals(DateHelper.formatNow().substring(0, 4)); } /** * @return the ccust */ public CCust getCcust() { return ccust; } /** * @param ccust * the ccust to set */ public void setCcust(CCust ccust) { this.ccust = ccust; } /** * @return the cuser */ public CUser getCuser() { return cuser; } /** * @param cuser * the cuser to set */ public void setCuser(CUser cuser) { if (cuser instanceof CUserAtv) { setCuseratv((CUserAtv) cuser); setCuserdtv(null); setCuserBroadband(null); } else if (cuser instanceof CUserDtv) { setCuserdtv((CUserDtv) cuser); setCuserBroadband(null); setCuseratv(null); } else if (cuser instanceof CUserBroadband) { setCuserBroadband((CUserBroadband) cuser); setCuserdtv(null); setCuseratv(null); } this.cuser = cuser; } /** * @return the cuserdtv */ public CUserDtv getCuserdtv() { return cuserdtv; } /** * @param cuserdtv * the cuserdtv to set */ public void setCuserdtv(CUserDtv cuserdtv) { this.cuserdtv = cuserdtv; } /** * @return the cuseratv */ public CUserAtv getCuseratv() { return cuseratv; } /** * @param cuseratv * the cuseratv to set */ public void setCuseratv(CUserAtv cuseratv) { this.cuseratv = cuseratv; } /** * @return the tODAY */ public Date getTODAY() { return TODAY; } /** * @param today the tODAY to set */ public void setTODAY(Date today) { TODAY = today; } private StandardEvaluationContext context = new StandardEvaluationContext(); private ExpressionParser parser = new SpelExpressionParser(); public ExpressionParser getParser() { return parser; } /** * 返回指定类型的表达式结果 * * @param <T> * 返回类型 * @param exp * 表达式 * @param resultType * @return */ public <T> T getVariable(String exp, Class<T> resultType) { return parser.parseExpression(exp).getValue(context, resultType); } public String getVariable(String exp) { return getVariable(exp, String.class); } /** * 将变量加入表达式容器 以#varname的方式调用 * * @param varname * @param value */ public void setVariable(String varname, Object value) { context.setVariable(varname, value); } /** * @return the cuserBroadband */ public CUserBroadband getCuserBroadband() { return cuserBroadband; } /** * @param cuserBroadband the cuserBroadband to set */ public void setCuserBroadband(CUserBroadband cuserBroadband) { this.cuserBroadband = cuserBroadband; } /** * @param addressDao the tAddressDao to set */ public void setTAddressDao(TAddressDao addressDao) { tAddressDao = addressDao; } /** * @param custDao the cCustDao to set */ public void setCCustDao(CCustDao custDao) { cCustDao = custDao; } public CAcctBankDao getCAcctBankDao() { return cAcctBankDao; } public void setCAcctBankDao(CAcctBankDao cAcctBankDao) { this.cAcctBankDao = cAcctBankDao; } /** * @param userDao the cUserDao to set */ public void setCUserDao(CUserDao userDao) { cUserDao = userDao; } /** * @param userDtvDao the cUserDtvDao to set */ public void setCUserDtvDao(CUserDtvDao userDtvDao) { cUserDtvDao = userDtvDao; } /** * @param userAtvDao the cUserAtvDao to set */ public void setCUserAtvDao(CUserAtvDao userAtvDao) { cUserAtvDao = userAtvDao; } /** * @param ruleEditDao the tRuleEditDao to set */ public void setTRuleEditDao(TRuleEditDao ruleEditDao) { tRuleEditDao = ruleEditDao; } /** * @param ruleDefineDao the tRuleDefineDao to set */ public void setTRuleDefineDao(TRuleDefineDao ruleDefineDao) { tRuleDefineDao = ruleDefineDao; } /** * @param promotionDao the pPromotionDao to set */ public void setPPromotionDao(PPromotionDao promotionDao) { pPromotionDao = promotionDao; } /** * @param feeDao the cFeeDao to set */ public void setCFeeDao(CFeeDao feeDao) { cFeeDao = feeDao; } /** * @return the stb */ public CFeeDevice getStb() { return stb; } /** * @param stb the stb to set */ public void setStb(CFeeDevice stb) { this.stb = stb; } /** * @param feeDeviceDao the cFeeDeviceDao to set */ public void setCFeeDeviceDao(CFeeDeviceDao feeDeviceDao) { cFeeDeviceDao = feeDeviceDao; } /** * @return the orderprods */ public List<CProdDto> getOrderprods() { return orderprods; } /** * @param orderprods the orderprods to set */ public void setOrderprods(List<CProdDto> orderprods) { this.orderprods = orderprods; } /** * @param prodDao the cProdDao to set */ public void setCProdDao(CProdDao prodDao) { cProdDao = prodDao; } public SOptr getOptr() { return optr; } public void setOptr(SOptr optr) { this.optr = optr; } public ExpressionUtil(TAddressDao tAddressDao) { this.tAddressDao = tAddressDao; } /** * @return the cuserStb */ public CUserStb getCuserStb() { return cuserStb; } /** * @param cuserStb the cuserStb to set */ public void setCuserStb(CUserStb cuserStb) { this.cuserStb = cuserStb; } }