/*
* 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.action.rationaldb;
import java.util.ArrayList;
import java.util.List;
import com.wabacus.config.Config;
import com.wabacus.config.component.application.report.ColBean;
import com.wabacus.config.component.application.report.ReportBean;
import com.wabacus.config.database.type.AbsDatabaseType;
import com.wabacus.exception.WabacusConfigLoadingException;
import com.wabacus.system.buttons.EditableReportSQLButtonDataBean;
import com.wabacus.system.component.application.report.configbean.editablereport.AbsEditableReportEditDataBean;
import com.wabacus.system.component.application.report.configbean.editablereport.EditableReportParamBean;
import com.wabacus.system.dataset.update.action.AbsUpdateAction;
import com.wabacus.util.Tools;
public class SQLUpdateAction extends AbsRationalDBUpdateAction implements Cloneable
{
public SQLUpdateAction(AbsEditableReportEditDataBean ownerUpdateBean)
{
super(ownerUpdateBean);
}
public void parseActionScript(String sql,List<AbsUpdateAction> lstUpdateActions,String reportTypeKey)
{
if(this.isStandardUpdateSql(sql))
{
List<EditableReportParamBean> lstDynParamsTmp=new ArrayList<EditableReportParamBean>();
sql=this.ownerUpdateBean.parseStandardEditSql(sql,lstDynParamsTmp,reportTypeKey,this.isPreparedStatement,this.isOriginalParams);
this.sqlsp=sql;
this.isStandardSql=true;
this.lstParamBeans=lstDynParamsTmp;
lstUpdateActions.add(this);
}else
{
int idxwhere=sql.toLowerCase().indexOf(" where ");
String whereclause=null;
List<EditableReportParamBean> lstParamsBeanInWhereClause=null;
if(idxwhere>0)
{
lstParamsBeanInWhereClause=new ArrayList<EditableReportParamBean>();
whereclause=sql.substring(idxwhere).trim();
sql=sql.substring(0,idxwhere).trim();
}
AbsDatabaseType dbtype=Config.getInstance().getDataSource(this.datasource).getDbType();
if(dbtype==null)
{
throw new WabacusConfigLoadingException("没有实现数据源"+this.datasource+"对应数据库类型的相应实现类");
}
List<SQLUpdateAction> lstRealUpdateSqls=dbtype.constructUpdateSql(sql.trim(),this.ownerUpdateBean.getOwner().getReportBean(),
reportTypeKey,this);
if(!Tools.isEmpty(whereclause))
{
whereclause=this.ownerUpdateBean.parseStandardEditSql(whereclause,lstParamsBeanInWhereClause,reportTypeKey,this.isPreparedStatement,this.isOriginalParams);
}
List<EditableReportParamBean> lstParamsBean;
String updatesql;
for(SQLUpdateAction updateSqlBeanTmp:lstRealUpdateSqls)
{
updatesql=updateSqlBeanTmp.getSqlsp();
lstParamsBean=updateSqlBeanTmp.getLstParamBeans();
if(whereclause!=null&&!whereclause.trim().equals(""))
{
if(updatesql.indexOf("%where%")>0)
{
updatesql=Tools.replaceAll(updatesql,"%where%",whereclause);
}else
{
updatesql=updatesql+" "+whereclause;
}
lstParamsBean.addAll(lstParamsBeanInWhereClause);
}
updateSqlBeanTmp.setSqlsp(updatesql);
updateSqlBeanTmp.setLstParamBeans(lstParamsBean);
lstUpdateActions.add(updateSqlBeanTmp);
}
}
}
public List<SQLUpdateAction> constructUpdateSql(String configUpdateSql,ReportBean rbean,String reportTypeKey)
{
StringBuilder sqlBuffer=new StringBuilder();
List<EditableReportParamBean> lstParamsBean=new ArrayList<EditableReportParamBean>();
int idxleft=configUpdateSql.indexOf("(");
int placeholderIdxTmp=0;
EditableReportParamBean paramBean;
if(idxleft<0||configUpdateSql.endsWith("()"))
{//没有指定要更新的字段,则将所有从数据库取数据的<col/>(不包括hidden="1"和="2"的<col/>)全部更新到表中
if(!this.ownerUpdateBean.isAutoReportdata())
{
throw new WabacusConfigLoadingException("加载报表"+rbean.getPath()+"失败,在autoreportdata属性为false的<button/>中,不能配置update table这种不带参数的SQL语句");
}
if(configUpdateSql.endsWith("()")) configUpdateSql=configUpdateSql.substring(0,configUpdateSql.length()-2);
sqlBuffer.append(configUpdateSql).append(" set ");
for(ColBean cbean:rbean.getDbean().getLstCols())
{
paramBean=createParamBeanByColbean(cbean.getProperty(),reportTypeKey,false,false);
if(paramBean!=null)
{
sqlBuffer.append(cbean.getColumn()+"="+getDynParamStringInSql(paramBean,placeholderIdxTmp++)+",");
lstParamsBean.add(paramBean);
}
}
}else
{
sqlBuffer.append(configUpdateSql.substring(0,idxleft)).append(" set ");
int idxright=configUpdateSql.lastIndexOf(")");
if(idxright!=configUpdateSql.length()-1)
{
throw new WabacusConfigLoadingException("加载报表"+rbean.getPath()+"失败,配置的修改数据SQL语句"+configUpdateSql+"不合法");
}
String cols=configUpdateSql.substring(idxleft+1,idxright);
List<String> lstUpdateCols=Tools.parseStringToList(cols,",",new String[]{"'","'"},false);
String columnname=null;
String columnvalue=null;
ColBean cb;
for(String updatecol:lstUpdateCols)
{
if(updatecol==null||updatecol.trim().equals("")) continue;
int idxequals=updatecol.indexOf("=");
if(idxequals>0)
{//配置为“字段名=值”格式
columnname=updatecol.substring(0,idxequals).trim();
columnvalue=updatecol.substring(idxequals+1).trim();
Object paramObjTmp=this.createEditParams(columnvalue,reportTypeKey);
if(paramObjTmp==null) continue;
sqlBuffer.append(columnname+"=");
if(paramObjTmp instanceof EditableReportParamBean)
{
sqlBuffer.append(getDynParamStringInSql((EditableReportParamBean)paramObjTmp,placeholderIdxTmp++));
lstParamsBean.add((EditableReportParamBean)paramObjTmp);
}else
{
sqlBuffer.append(paramObjTmp);
}
sqlBuffer.append(",");
}else
{
if(!Tools.isDefineKey("@",updatecol))
{
throw new WabacusConfigLoadingException("加载报表"+rbean.getPath()+"失败,配置的修改数据SQL语句"+configUpdateSql+"不合法,更新的字段值必须采用@{}括住");
}
if(this.ownerUpdateBean.isAutoReportdata())
{
updatecol=Tools.getRealKeyByDefine("@",updatecol);
String realColProperty=updatecol.trim();
if(realColProperty.endsWith("__old")) realColProperty=realColProperty.substring(0,realColProperty.length()-"__old".length());
cb=rbean.getDbean().getColBeanByColProperty(realColProperty);
if(cb==null)
{
throw new WabacusConfigLoadingException("加载报表"+rbean.getPath()+"失败,配置的要更新字段"+updatecol+"不合法,没有取到其值对应的<col/>");
}
paramBean=createParamBeanByColbean(updatecol,reportTypeKey,true,true);
lstParamsBean.add(paramBean);
sqlBuffer.append(cb.getColumn()+"="+getDynParamStringInSql(paramBean,placeholderIdxTmp++)+",");
}else
{
((EditableReportSQLButtonDataBean)this.ownerUpdateBean).setHasReportDataParams(true);
paramBean=new EditableReportParamBean();
paramBean.setParamname(updatecol);
lstParamsBean.add(paramBean);
sqlBuffer.append(Tools.getRealKeyByDefine("@",updatecol)+"="+getDynParamStringInSql(paramBean,placeholderIdxTmp++)+",");
}
}
}
}
if(sqlBuffer.charAt(sqlBuffer.length()-1)==',') sqlBuffer.deleteCharAt(sqlBuffer.length()-1);
List<SQLUpdateAction> lstUpdateSqlActions=new ArrayList<SQLUpdateAction>();
this.sqlsp=sqlBuffer.toString();
this.lstParamBeans=lstParamsBean;
lstUpdateSqlActions.add(this);
return lstUpdateSqlActions;
}
private String getDynParamStringInSql(EditableReportParamBean paramBean,int placeholderIdx)
{
if(this.isPreparedStatement) return "?";
paramBean.setPlaceholder("[PLACE_HOLDER_"+placeholderIdx+"]");
return paramBean.getPlaceholder();
}
private boolean isStandardUpdateSql(String updatesql)
{
updatesql=updatesql==null?"":updatesql.toLowerCase().trim();
if(!updatesql.startsWith("update ")) return true;
updatesql=updatesql.substring("update ".length()).trim();
if(updatesql.equals("")) return true;
updatesql=Tools.replaceCharacterInQuote(updatesql,'(',"$_LEFTBRACKET_$",true);
updatesql=Tools.replaceCharacterInQuote(updatesql,')',"$_RIGHTBRACKET_$",true);
int idxBracket1=updatesql.indexOf("(");
if(idxBracket1==0) return true;
if(idxBracket1<0)
{
if(updatesql.indexOf(" ")<0&&updatesql.indexOf(",")<0&&updatesql.indexOf("=")<0) return false;//update tablename格式
}else
{
String tablename=updatesql.substring(0,idxBracket1).trim();
if(tablename.indexOf(" ")>=0||tablename.indexOf(",")>=0||tablename.indexOf("=")>=0) return true;
updatesql=updatesql.substring(idxBracket1+1);
int idxleft=1;
int idxRightBacket=-1;
for(int i=0;i<updatesql.length();i++)
{
if(updatesql.charAt(i)=='(')
{
idxleft++;
}else if(updatesql.charAt(i)==')')
{
if(idxleft==1)
{//此右括号与第一个左括号匹配
idxRightBacket=i;
break;
}else if(idxleft<=0)
{
return true;
}else
{
idxleft--;
}
}
}
if(idxRightBacket==-1) return true;
if(idxRightBacket==0&&(updatesql.equals(")")||updatesql.substring(1).trim().startsWith("where "))) return false;
updatesql=updatesql.substring(idxRightBacket+1).trim();
if(updatesql.equals("")||updatesql.startsWith("where ")) return false;
}
return true;
}
public SQLUpdateAction cloneWithAllDefaultValues()
{
try
{
return (SQLUpdateAction)super.clone();
}catch(CloneNotSupportedException e)
{
throw new WabacusConfigLoadingException("clone对象失败",e);
}
}
}