/*
* Copyright (C) 2010---2014 星星(wuweixing)<349446658@qq.com>
*
* This file is part of Wabacus
*
* Wabacus is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.wabacus.system.dataset.update.precondition;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.wabacus.config.Config;
import com.wabacus.config.ConfigLoadManager;
import com.wabacus.config.component.application.report.ReportBean;
import com.wabacus.config.database.type.AbsDatabaseType;
import com.wabacus.exception.WabacusConfigLoadingException;
import com.wabacus.exception.WabacusRuntimeException;
import com.wabacus.system.ReportRequest;
import com.wabacus.system.assistant.WabacusAssistant;
import com.wabacus.system.component.application.report.configbean.editablereport.EditableReportParamBean;
import com.wabacus.system.intercept.IInterceptor;
import com.wabacus.util.Tools;
public class DefaultConcreteExpressionBean extends AbsConcreteExpressionBean
{
private static Log log=LogFactory.getLog(DefaultConcreteExpressionBean.class);
protected String type;
private String param1;
private List<EditableReportParamBean> lstParamsBean1;
private String param2;
private List<EditableReportParamBean> lstParamsBean2;//如果第二个参数是SQL语句种情况,这里存放获取数据的SQL语句所用到的动态参数列表
private Class param1Class;
private Class param2Class;
private AbsCompareDataType datatypeObj;
public boolean isTrue(ReportRequest rrequest,Map<String,String> mRowData,Map<String,String> mParamValues)
{
Object realParam1Value=null;
if(param1Class!=null)
{
realParam1Value=getRealParamValueByClass(rrequest,mRowData,mParamValues,this.param1Class);
}else
{
realParam1Value=getRealParamValue(rrequest,mRowData,mParamValues,param1,lstParamsBean1);
}
Object realParam2Value=null;
if(param2Class!=null)
{//如果第二个参数是从自定义JAVA类中获取
realParam2Value=getRealParamValueByClass(rrequest,mRowData,mParamValues,this.param2Class);
}else
{
realParam2Value=getRealParamValue(rrequest,mRowData,mParamValues,param2,lstParamsBean2);
}
log.debug("compare value1:"+realParam1Value+";value2:"+realParam2Value);
if(type.equals("eq"))
{
return datatypeObj.isEquals(realParam1Value,realParam2Value);
}else if(type.equals("neq"))
{
return !datatypeObj.isEquals(realParam1Value,realParam2Value);
}else if(type.equals("gt"))
{
return datatypeObj.isGreaterThan(realParam1Value,realParam2Value);
}else if(type.equals("lt"))
{
return !datatypeObj.isEquals(realParam1Value,realParam2Value)&&!datatypeObj.isGreaterThan(realParam1Value,realParam2Value);
}else if(type.equals("gte"))
{
return datatypeObj.isGreaterThan(realParam1Value,realParam2Value)||datatypeObj.isEquals(realParam1Value,realParam2Value);
}else
{
return !datatypeObj.isGreaterThan(realParam1Value,realParam2Value);
}
}
private Object getRealParamValueByClass(ReportRequest rrequest,Map<String,String> mRowData,Map<String,String> mParamValues,Class c)
{
try
{
Method m=c.getDeclaredMethod("getValue",new Class[] { ReportRequest.class, ReportBean.class, Map.class, Map.class });
return m.invoke(c.newInstance(),new Object[] { rrequest, getReportBean(), mRowData, mParamValues });
}catch(Exception e)
{
throw new WabacusRuntimeException("加载报表"+getReportBean().getPath()+"的precondition的条件值失败,无法调用自定义JAVA类:"+c.getName()
+"的方法getValue(ReportRequet,ReportBean,Map,Map)获取数据",e);
}
}
private Object getRealParamValue(ReportRequest rrequest,Map<String,String> mRowData,Map<String,String> mParamValues,String param,
List<EditableReportParamBean> lstParamBeans)
{
if(param==null||param.trim().equals("")) return param;
Object paramValue;
if(WabacusAssistant.getInstance().isGetRequestContextValue(param))
{//从url/request/rrequest/session中取数据
paramValue=WabacusAssistant.getInstance().getRequestContextValue(rrequest,param);
}else if(Tools.isDefineKey("@",param))
{
if(mRowData==null) return null;
param=Tools.getRealKeyByDefine("@",param);
paramValue=mRowData.get(param);
}else if(Tools.isDefineKey("#",param))
{
if(mParamValues==null) return null;
paramValue=mParamValues.get(Tools.getRealKeyByDefine("#",param));
}else if(Tools.isDefineKey("sql",param))
{
String sql=Tools.getRealKeyByDefine("sql",param);
sql=getStatementExecuteSql(rrequest,mRowData,mParamValues,sql,lstParamBeans);
paramValue=getDataFromDB(rrequest,mRowData,mParamValues,lstParamBeans,sql);
}else
{//常量
paramValue=param;
}
return paramValue;
}
private Object getDataFromDB(ReportRequest rrequest,Map<String,String> mRowData,Map<String,String> mParamValues,
List<EditableReportParamBean> lstParamBeans,String sql)
{
Connection conn=rrequest.getConnection(this.datasource);
Statement stmt=null;
ResultSet rs=null;
try
{
IInterceptor interceptorObj=this.getReportBean().getInterceptor();
if(interceptorObj!=null)
{
Object objTmp=interceptorObj.beforeLoadData(rrequest,this.getReportBean(),this,sql);
if(objTmp==null) return null;
if(!(objTmp instanceof String))
{
throw new WabacusRuntimeException("加载报表"+getReportBean().getPath()+"的precondition的条件值失败,此时的拦截器前置动作只能返回SQL语句");
}
sql=(String)objTmp;
}
if(Tools.isEmpty(sql)) return null;
if(Config.show_sql) log.info("Execute sql:"+sql);
stmt=conn.createStatement();
rs=stmt.executeQuery(sql);
if(!rs.next()) return null;
return this.datatypeObj.getDataFromResultSet(rs);
}catch(SQLException e)
{
throw new WabacusRuntimeException("执行报表"+getReportBean().getPath()+"的SQL语句:"+sql+"失败",e);
}finally
{
try
{
rs.close();
}catch(SQLException e)
{
e.printStackTrace();
}
WabacusAssistant.getInstance().release(null,stmt);
}
}
private String getStatementExecuteSql(ReportRequest rrequest,Map<String,String> mRowData,Map<String,String> mParamValues,String sql,
List<EditableReportParamBean> lstParamBeans)
{
ReportBean rbean=this.getReportBean();
if(lstParamBeans!=null&&lstParamBeans.size()>0)
{
String paramValueTmp;
AbsDatabaseType dbtype=rrequest.getDbType(this.datasource);
for(EditableReportParamBean paramBean:lstParamBeans)
{
paramValueTmp=paramBean.getRuntimeParamValue(rrequest,rbean,mRowData,mParamValues,this.datasource,ownerEditbean.isAutoReportdata());
paramValueTmp=dbtype.getStatementValue(paramBean.getDataTypeObj(),paramValueTmp);
if(paramValueTmp==null) paramValueTmp="null";
sql=Tools.replaceAll(sql,paramBean.getPlaceholder(),paramValueTmp);
}
}
return sql;
}
public void parseParams()
{
super.parseParams();
if(lstParams==null||lstParams.size()<3)
{
throw new WabacusConfigLoadingException("解析报表"+getReportBean().getPath()+"配置的precondition中表达式失败,采用内置的比较条件时,必须指定比较参数和被比较参数");
}
this.type=lstParams.get(0).toLowerCase().trim();
lstParamsBean1=new ArrayList<EditableReportParamBean>();
this.param1=parseCompareParams(lstParams.get(1),lstParamsBean1);
this.param1Class=getParamClass(this.param1);
lstParamsBean2=new ArrayList<EditableReportParamBean>();
this.param2=parseCompareParams(lstParams.get(2),lstParamsBean2);
this.param2Class=getParamClass(this.param2);
String datatype=lstParams.size()>3?lstParams.get(3):null;//比较的数据类型
if(datatype!=null) datatype=datatype.toLowerCase().trim();
if("int".equalsIgnoreCase(datatype))
{
this.datatypeObj=new IntDataType();
}else if("long".equalsIgnoreCase(datatype))
{
this.datatypeObj=new LongDataType();
}else if("float".equalsIgnoreCase(datatype))
{
this.datatypeObj=new FloatDataType();
}else if("double".equalsIgnoreCase(datatype))
{
this.datatypeObj=new DoubleDataType();
}else if("boolean".equalsIgnoreCase(datatype))
{
this.datatypeObj=new BooleanDataType();
}else if("object".equalsIgnoreCase(datatype))
{
this.datatypeObj=new ObjectDataType();
}else
{
this.datatypeObj=new StringDataType();
}
}
private String parseCompareParams(String param,List<EditableReportParamBean> lstSqlParams)
{
if(param==null||param.trim().equals("")) return param;
if(Tools.isDefineKey("sql",param.trim()))
{
param=Tools.getRealKeyByDefine("sql",param);
param=this.ownerEditbean.parseStandardEditSql(param,lstSqlParams,reportTypeKey,false,false);
param="sql{"+param+"}";
}else if(Tools.isDefineKey("url",param.trim()))
{
getReportBean().addParamNameFromURL(Tools.getRealKeyByDefine("url",param));
}else if(param.trim().startsWith("'")&¶m.trim().endsWith("'")&¶m.trim().length()>=2)
{
param=param.trim().substring(1,param.trim().length()-1);
}else if(param.trim().toLowerCase().equals("null"))
{//配置的为null(不是'null')
param=null;
}
return param;
}
private Class getParamClass(String param)
{
if(!Tools.isDefineKey("class",param)) return null;
param=Tools.getRealKeyByDefine("class",param);
return ConfigLoadManager.currentDynClassLoader.loadClassByCurrentLoader(param);
}
// correctParamnameOfCol(this.lstParamsBean2);
private abstract class AbsCompareDataType
{
public abstract Object getDataFromResultSet(ResultSet rs) throws SQLException;
public boolean isEquals(Object paramObj1,Object paramObj2)
{
if(paramObj1==null||paramObj1.toString().equals("")||paramObj2==null||paramObj2.toString().equals(""))
{
return isEqualsBetweenEmptyParams(paramObj1,paramObj2);
}else
{
return isEqualsBetweenNonEmptyParams(paramObj1,paramObj2);
}
}
protected boolean isEqualsBetweenEmptyParams(Object paramObj1,Object paramObj2)
{
if(paramObj1==null&¶mObj2==null) return true;
if(paramObj1==null&¶mObj2!=null||paramObj1!=null&¶mObj2==null)
{
return false;
}
if(paramObj1.toString().equals("")&¶mObj2.toString().equals("")) return true;
return false;
}
protected boolean isEqualsBetweenNonEmptyParams(Object paramObj1,Object paramObj2)
{
try
{
return getRealTypeValue(paramObj1)==getRealTypeValue(paramObj2);
}catch(Exception e)
{
return false;
}
}
public boolean isGreaterThan(Object paramObj1,Object paramObj2)
{
if(paramObj1==null||paramObj2==null||paramObj1.toString().trim().equals("")||paramObj2.toString().trim().equals(""))
{
return isGreaterThanBetweenEmptyParams(paramObj1,paramObj2);
}
return isGreaterThanBetweenNonEmptyParams(paramObj1,paramObj2);
}
protected boolean isGreaterThanBetweenEmptyParams(Object paramObj1,Object paramObj2)
{
if(paramObj1==null&¶mObj2==null) return false;
if(paramObj1==null&¶mObj2!=null) return false;
if(paramObj1!=null&¶mObj2==null) return true;
if(paramObj1.toString().trim().equals("")) return false;
return true;//paramObj1不为空而paramObj2为空字符串
}
protected abstract boolean isGreaterThanBetweenNonEmptyParams(Object paramObj1,Object paramObj2);
protected abstract Object getRealTypeValue(Object paramObj);
}
private class BooleanDataType extends AbsCompareDataType
{
public Object getDataFromResultSet(ResultSet rs) throws SQLException
{
return rs.getBoolean(1);
}
protected Object getRealTypeValue(Object paramObj)
{
boolean resultValue;
if(paramObj instanceof Boolean)
{
resultValue=(Boolean)paramObj;
}else
{
resultValue=paramObj.toString().trim().toLowerCase().equals("true");
}
return resultValue;
}
protected boolean isGreaterThanBetweenNonEmptyParams(Object paramObj1,Object paramObj2)
{
return false;
}
}
private class DoubleDataType extends AbsCompareDataType
{
public Object getDataFromResultSet(ResultSet rs) throws SQLException
{
return rs.getDouble(1);
}
protected boolean isGreaterThanBetweenNonEmptyParams(Object paramObj1,Object paramObj2)
{
try
{
double d1=(Double)getRealTypeValue(paramObj1);
double d2=(Double)getRealTypeValue(paramObj2);
return d1>d2;
}catch(Exception e)
{
return false;
}
}
protected Object getRealTypeValue(Object paramObj)
{
double resultValue;
if(paramObj instanceof Double)
{
resultValue=(Double)paramObj;
}else
{
resultValue=Double.parseDouble(String.valueOf(paramObj));
}
return resultValue;
}
}
private class FloatDataType extends AbsCompareDataType
{
public Object getDataFromResultSet(ResultSet rs) throws SQLException
{
return rs.getFloat(1);
}
protected boolean isGreaterThanBetweenNonEmptyParams(Object paramObj1,Object paramObj2)
{
try
{
float d1=(Float)getRealTypeValue(paramObj1);
float d2=(Float)getRealTypeValue(paramObj2);
return d1>d2;
}catch(Exception e)
{
return false;
}
}
protected Object getRealTypeValue(Object paramObj)
{
float resultValue;
if(paramObj instanceof Float)
{
resultValue=(Float)paramObj;
}else
{
resultValue=Float.parseFloat(String.valueOf(paramObj));
}
return resultValue;
}
}
private class IntDataType extends AbsCompareDataType
{
public Object getDataFromResultSet(ResultSet rs) throws SQLException
{
return rs.getInt(1);
}
protected boolean isGreaterThanBetweenNonEmptyParams(Object paramObj1,Object paramObj2)
{
try
{
int d1=(Integer)getRealTypeValue(paramObj1);
int d2=(Integer)getRealTypeValue(paramObj2);
return d1>d2;
}catch(Exception e)
{
return false;
}
}
protected Object getRealTypeValue(Object paramObj)
{
int resultValue;
if(paramObj instanceof Integer)
{
resultValue=(Integer)paramObj;
}else
{
resultValue=Integer.parseInt(String.valueOf(paramObj));
}
return resultValue;
}
}
private class LongDataType extends AbsCompareDataType
{
public Object getDataFromResultSet(ResultSet rs) throws SQLException
{
return rs.getLong(1);
}
protected boolean isGreaterThanBetweenNonEmptyParams(Object paramObj1,Object paramObj2)
{
try
{
long d1=(Long)getRealTypeValue(paramObj1);
long d2=(Long)getRealTypeValue(paramObj2);
return d1>d2;
}catch(Exception e)
{
return false;//如果有一个不是合法的数字,则说明不相等
}
}
protected Object getRealTypeValue(Object paramObj)
{
long resultValue;
if(paramObj instanceof Long)
{
resultValue=(Long)paramObj;
}else
{
resultValue=Long.parseLong(String.valueOf(paramObj));
}
return resultValue;
}
}
private class ObjectDataType extends AbsCompareDataType
{
public Object getDataFromResultSet(ResultSet rs) throws SQLException
{
return rs.getObject(1);
}
protected Object getRealTypeValue(Object paramObj)
{
return paramObj;
}
protected boolean isEqualsBetweenNonEmptyParams(Object paramObj1,Object paramObj2)
{
return paramObj1.equals(paramObj2);
}
protected boolean isGreaterThanBetweenNonEmptyParams(Object paramObj1,Object paramObj2)
{
if(!(paramObj1 instanceof Comparable)||!(paramObj2 instanceof Comparable)) return false;
return ((Comparable)paramObj1).compareTo(paramObj2)>0;
}
}
private class StringDataType extends AbsCompareDataType
{
public Object getDataFromResultSet(ResultSet rs) throws SQLException
{
return rs.getString(1);
}
protected Object getRealTypeValue(Object paramObj)
{
return paramObj.toString();
}
protected boolean isEqualsBetweenNonEmptyParams(Object paramObj1,Object paramObj2)
{
return paramObj1.equals(paramObj2);
}
protected boolean isGreaterThanBetweenNonEmptyParams(Object paramObj1,Object paramObj2)
{
return paramObj1.toString().compareTo(paramObj2.toString())>0;
}
}
}