package cn.org.rapid_framework.generator.ext.tableconfig.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import cn.org.rapid_framework.generator.GeneratorProperties;
import cn.org.rapid_framework.generator.ext.tableconfig.IbatisSqlMapConfigParser;
import cn.org.rapid_framework.generator.provider.db.sql.SqlFactory;
import cn.org.rapid_framework.generator.provider.db.sql.model.Sql;
import cn.org.rapid_framework.generator.provider.db.sql.model.SqlParameter;
import cn.org.rapid_framework.generator.provider.db.sql.model.SqlSegment;
import cn.org.rapid_framework.generator.provider.db.table.TableFactory;
import cn.org.rapid_framework.generator.provider.db.table.model.Column;
import cn.org.rapid_framework.generator.provider.db.table.model.ColumnSet;
import cn.org.rapid_framework.generator.provider.db.table.model.Table;
import cn.org.rapid_framework.generator.util.BeanHelper;
import cn.org.rapid_framework.generator.util.StringHelper;
import cn.org.rapid_framework.generator.util.sqlparse.SqlParseHelper;
import cn.org.rapid_framework.generator.util.typemapping.JavaPrimitiveTypeMapping;
import cn.org.rapid_framework.generator.util.typemapping.JdbcType;
public class TableConfig {
public String sqlName;
public String sequence;
public String dummyPk;
public String remarks;
public String subPackage;
public String _package;
public boolean autoSwitchDataSrc;
public String className;
public List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
public List<OperationConfig> operations = new ArrayList<OperationConfig>();
public List<ResultMapConfig> resultMaps = new ArrayList<ResultMapConfig>();
//for support
//<sql id="columns"><![CDATA[ ]]></sql id="columns">
//<include refid="columns"/>
private List<SqlConfig> includeSqls = new ArrayList<SqlConfig>();
public List<ResultMapConfig> getResultMaps() {
return resultMaps;
}
public void setResultMaps(List<ResultMapConfig> resultMaps) {
this.resultMaps = resultMaps;
}
public String getClassName() {
if(StringHelper.isNotBlank(className)) return className;
if(StringHelper.isBlank(sqlName)) return null;
return StringHelper.toJavaClassName(sqlName);
}
public void setClassName(String className) {
this.className = className;
}
public Column getPkColumn() throws Exception {
if(StringHelper.isBlank(dummyPk)) {
return getTable().getPkColumn();
}else {
return getTable().getColumnByName(dummyPk);
}
}
public String getPackage() {
if(StringHelper.isBlank(subPackage)) {
return _package;
}else {
return _package+"."+subPackage;
}
}
public void setPackage(String pkg) {
this._package = pkg;
}
private Table table = null;
public Table getTable() throws Exception {
if(table != null) return table;
table = TableFactory.getInstance().getTable(getSqlName());
return customTable(table);
}
public Table customTable(Table table) {
if(!table.getSqlName().equalsIgnoreCase(getSqlName())) {
throw new RuntimeException("cannot custom table properties,sqlName not equals. tableConfig.sqlName:"+getSqlName()+" table.sqlName:"+table.getSqlName());
}
if(columns != null) {
for(ColumnConfig c : columns) {
Column tableColumn = table.getColumnByName(c.getName());
if(tableColumn != null) {
tableColumn.setJavaType(c.getJavatype()); //FIXME 只能自定义javaType
}
}
}
if(StringHelper.isNotBlank(getDummyPk())) {
Column c = table.getColumnBySqlName(getDummyPk());
if(c != null) {
c.setPk(true);
}
}
table.setClassName(getClassName());
if(StringHelper.isNotBlank(remarks)) {
table.setTableAlias(remarks);
}
return table;
}
public String getSqlName() {
return sqlName;
}
public void setSqlName(String sqlname) {
this.sqlName = sqlname;
}
public String getSequence() {
return sequence;
}
public void setSequence(String sequence) {
this.sequence = sequence;
}
public List<ColumnConfig> getColumns() {
if(columns == null) {
columns = new ArrayList();
}
return columns;
}
public void setColumns(List<ColumnConfig> column) {
this.columns = column;
}
public List<SqlConfig> getIncludeSqls() {
return includeSqls;
}
public void setIncludeSqls(List<SqlConfig> includeSqls) {
this.includeSqls = includeSqls;
}
public void addSqlConfig(SqlConfig c) {
this.includeSqls.add(c);
c.setTableConfig(this);
}
public List<OperationConfig> getOperations() {
return operations;
}
public void setOperations(List<OperationConfig> operations) {
this.operations = operations;
}
public OperationConfig findOperation(String operationName) {
OperationConfig operation = null;
for(OperationConfig item : getOperations()){
if(item.getName().equals(operationName)) {
return item;
}
}
return null;
}
public String getDummyPk() {
return dummyPk;
}
public void setDummyPk(String dummypk) {
this.dummyPk = dummypk;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public String getSubPackage() {
return subPackage;
}
public void setSubPackage(String subpackage) {
this.subPackage = subpackage;
}
public boolean isAutoSwitchDataSrc() {
return autoSwitchDataSrc;
}
public void setAutoSwitchDataSrc(boolean autoswitchdatasrc) {
this.autoSwitchDataSrc = autoswitchdatasrc;
}
public void setDoName(String doname) {
this.className = doname;
}
public String getBasepackage() {
return getPackage();
}
public String toString() {
return "sqlname:"+sqlName;
}
private List<Sql> sqls;
public List<Sql> getSqls() {
if(sqls == null) {
sqls = toSqls(this);
}
return sqls;
}
public static List<Sql> toSqls(TableConfig table) {
return new Convert2SqlsProecssor().toSqls(table);
}
public OperationConfig getOperation(String name) {
for(OperationConfig op : operations) {
if(op.getName().equals(name)) {
return op;
}
}
return null;
}
/**
* 用于将 OperationConfig.class 解析转换成 Sql.class对象
**/
static class Convert2SqlsProecssor {
public List<Sql> toSqls(TableConfig table) {
List<Sql> sqls = new ArrayList<Sql>();
for(OperationConfig op :table.getOperations()) {
sqls.add(processOperation(op,table));
}
return sqls;
}
public Sql toSql(TableConfig table,String operationName) {
OperationConfig operation = table.findOperation(operationName);
if(operation == null) throw new IllegalArgumentException("not found operation with name:"+operationName);
return processOperation(operation, table);
}
private Sql processOperation(OperationConfig op,TableConfig table) {
try {
IbatisSqlMapConfigParser ibatisSqlMapConfigParser = new IbatisSqlMapConfigParser();
String sqlString = ibatisSqlMapConfigParser.parse(op.getSql(),toMap(table.includeSqls));
String namedSql = SqlParseHelper.convert2NamedParametersSql(sqlString,":",""); // TODO 确认要删除本行?,因为与SqlFactory里面的代码重复
Sql sql = new SqlFactory().parseSql(namedSql);
sql.setSqlSegments(ibatisSqlMapConfigParser.getSqlSegments());
LinkedHashSet<SqlParameter> finalParameters = addExtraParams2SqlParams(op.getExtraparams(), sql);
sql.setParams(finalParameters);
sql.setColumns(processWithCustomColumns(getCustomColumns(table),sql.getColumns()));
String ibatisSql = getIbatisSql(op, sql);
sql.setIbatisSql(ibatisSql);
sql.setMybatisSql(sql.replaceWildcardWithColumnsSqlName(SqlParseHelper.convert2NamedParametersSql(op.getSql(),"#{","}")) + " "+op.getAppend()); // FIXME 修正ibatis3的问题
sql.setOperation(op.getName());
sql.setParameterClass(op.getParameterClass());
sql.setResultClass(op.getResultClass());
sql.setRemarks(op.getRemarks());
sql.setPaging(op.isPaging());
sql.setSqlmap(op.getSqlmap());
sql.setResultMap(op.getResultMap());
//FIXME 增加insert append="nowait"至 CDATA ]]>结尾的前面
if(StringHelper.isNotBlank(op.getMultiplicity())) {
sql.setMultiplicity(op.getMultiplicity());
}
//FIXME 与dalgen的规则是否一致
if(StringHelper.isNotBlank(op.getParamtype())) {
sql.setParamType(op.getParamtype());
}else if(StringHelper.isBlank(op.getParamtype()) && (sql.isSelectSql() || sql.isDeleteSql())) {
sql.setParamType(Sql.PARAMTYPE_PRIMITIVE);
}
sql.afterPropertiesSet();
return afterProcessed(sql,op,table);
}catch(Exception e) {
throw new RuntimeException("parse sql error on table:"+table.getSqlName()+" operation:"+op.getName()+"() sql:"+op.getSql(),e);
}
}
protected Sql afterProcessed(Sql sql,OperationConfig op,TableConfig table) {
return sql;
}
private static String getIbatisSql(OperationConfig op, Sql sql) {
String ibatisNamedSql = sql.replaceWildcardWithColumnsSqlName(SqlParseHelper.convert2NamedParametersSql(op.getSql(),"#","#")) + " "+ StringHelper.defaultString(op.getAppend());
String ibatisSql = processSqlForMoneyParam(ibatisNamedSql,sql.getParams());
return ibatisSql;
}
private static LinkedHashSet<Column> processWithCustomColumns(List<Column> customColumns,LinkedHashSet<Column> columns) {
ColumnSet columnSet = new ColumnSet(customColumns);
for(Column c : columns) {
Column custom = columnSet.getBySqlName(c.getSqlName());
if(custom != null) {
c.setJavaType(custom.getJavaType());
}
}
return columns;
}
private static LinkedHashSet<SqlParameter> addExtraParams2SqlParams(List<ParamConfig> extraParams, Sql sql) {
LinkedHashSet<SqlParameter> filterdExtraParameters = new LinkedHashSet<SqlParameter>();
for(ParamConfig extraParam : extraParams) {
SqlParameter param = sql.getParam(extraParam.getName());
if(param == null) {
SqlParameter extraparam = new SqlParameter();
extraparam.setParameterClass(extraParam.getJavatype());
if(StringHelper.isNotBlank(extraParam.getColumnAlias())) {
extraparam.setColumnAlias(extraParam.getColumnAlias()); // FIXME extraparam alias 现在的处理方式不好,应该不使用StringHelper.isNotBlank()判断
}
extraparam.setParamName(extraParam.getName());
filterdExtraParameters.add(extraparam);
}else {
param.setParameterClass(extraParam.getJavatype());
if(StringHelper.isNotBlank(extraParam.getColumnAlias())) {
param.setColumnAlias(extraParam.getColumnAlias()); // FIXME extraparam alias 现在的处理方式不好,应该不使用StringHelper.isNotBlank()判断
}
}
}
if(GeneratorProperties.getBoolean("generator.extraParams.append", true)) {
LinkedHashSet result = new LinkedHashSet(sql.getParams());
result.addAll(filterdExtraParameters);
return result;
}else {
filterdExtraParameters.addAll(sql.getParams());
return filterdExtraParameters;
}
}
/**
* Money类的特殊转换,only for alipay
**/
private static String processSqlForMoneyParam(String ibatisSql,LinkedHashSet<SqlParameter> params) {
for(SqlParameter p : params) {
if(p.getParameterClass().endsWith("Money")) {
ibatisSql = StringHelper.replace(ibatisSql, "#"+p.getParamName()+"#", "#"+p.getParamName()+".cent"+"#");
ibatisSql = StringHelper.replace(ibatisSql, "#{"+p.getParamName()+"}", "#{"+p.getParamName()+".cent"+"}");
}
}
return ibatisSql;
}
private static Map<String, String> toMap(List<SqlConfig> sql) {
Map map = new HashMap();
for(SqlConfig s : sql) {
map.put(s.id, s.sql);
}
return map;
}
private static List<Column> getCustomColumns(TableConfig table) throws Exception {
List<Column> result = new ArrayList<Column>();
Table t = table.getTable();
for(ColumnConfig mc : table.getColumns()) {
Column c = t.getColumnByName(mc.getName());
if(c == null) {
c = new Column(null, JdbcType.UNDEFINED.TYPE_CODE, "UNDEFINED",
mc.getName(), -1, -1, false,false,false,false,
"",mc.getColumnAlias());
}
c.setJavaType(mc.getJavatype());
if(StringHelper.isNotBlank(mc.getColumnAlias())) {
c.setColumnAlias(mc.getColumnAlias()); // FIXME custom column的 alias 现在的处理方式不好,应该不使用StringHelper.isNotBlank()判断
}
result.add(c);
}
return result;
}
}
/** 代表被 include的一段sql */
public static class SqlConfig {
String id;
String sql;
private TableConfig tableConfig;
public String toString() {
return String.format("<sql id='%s'>%s</sql>",id,sql);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
public TableConfig getTableConfig() {
return tableConfig;
}
public void setTableConfig(TableConfig tableConfig) {
this.tableConfig = tableConfig;
}
public SqlSegment getSqlSegment() {
if(tableConfig == null) throw new IllegalArgumentException("tableConfig must be not null");
for(Sql sql : tableConfig.getSqls()) {
if(sql.getSqlSegment(id) != null) {
return sql.getSqlSegment(id);
}
}
return null;
}
}
public static class ColumnConfig {
private String name;
private String javatype;
private String columnAlias;
private String nullValue;
public String getName() {
return name;
}
public void setName(String sqlname) {
this.name = sqlname;
}
public String getJavatype() {
return javatype;
}
public void setJavatype(String javatype) {
this.javatype = javatype;
}
public String getColumnAlias() {
return columnAlias;
}
public void setColumnAlias(String columnAlias) {
this.columnAlias = columnAlias;
}
public void setNullValue(String nullValue) {
this.nullValue = nullValue;
}
public String getNullValue() {
if(StringHelper.isBlank(nullValue)) {
return JavaPrimitiveTypeMapping.getDefaultValue(javatype);
}else {
return nullValue;
}
}
public boolean isHasNullValue() {
return JavaPrimitiveTypeMapping.getWrapperTypeOrNull(javatype) != null;
}
public String toString() {
return BeanHelper.describe(this).toString();
}
}
public static class ParamConfig extends ColumnConfig {
}
public static class ResultMapConfig {
private String name;
private List<ColumnConfig> columns = new ArrayList();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ColumnConfig> getColumns() {
return columns;
}
public void setColumns(List<ColumnConfig> columns) {
this.columns = columns;
}
}
public static class OperationConfig {
public List<ParamConfig> extraparams = new ArrayList<ParamConfig>();
public String name;
public String resultClass;
public String resultMap;
public String parameterClass;
public String remarks;
public String multiplicity;
public String paramtype;
public String sql;
public String sqlmap;
public Sql parsedSql;
public boolean paging = false;
public String append = ""; // append为无用配置,only for alipay的兼容性
public String appendXmlAttributes = ""; //TODO 还没有实现
public List<ParamConfig> getExtraparams() {
return extraparams;
}
public void setExtraparams(List<ParamConfig> extraparams) {
this.extraparams = extraparams;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getResultClass() {
return resultClass;
}
public void setResultClass(String resultClass) {
this.resultClass = resultClass;
}
public String getParameterClass() {
return parameterClass;
}
public void setParameterClass(String parameterClass) {
this.parameterClass = parameterClass;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
public String getMultiplicity() {
return multiplicity;
}
public void setMultiplicity(String multiplicity) {
this.multiplicity = multiplicity;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
public String getSqlmap() {
return sqlmap;
}
public void setSqlmap(String sqlmap) {
this.sqlmap = sqlmap;
}
public String getParamtype() {
return paramtype;
}
public void setParamtype(String paramtype) {
this.paramtype = paramtype;
}
public boolean isPaging() {
return paging;
}
public void setPaging(boolean paging) {
this.paging = paging;
}
public String getResultMap() {
return resultMap;
}
public void setResultMap(String resultMap) {
this.resultMap = resultMap;
}
public String getAppend() {
return append;
}
public void setAppend(String append) {
this.append = append;
}
public String toString() {
return BeanHelper.describe(this).toString();
}
}
}