package nc.bs.smart.data;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import com.ufida.dataset.IContext;
import com.ufida.dataset.db.DbType;
import com.ufida.iufo.pub.tools.AppDebug;
import com.ufida.zior.exception.MessageException;
import com.ufida.zior.perfwatch.PerfWatch;

import nc.bs.bi.smart.ConfigDBTool;
import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.framework.common.NCLocator;
import nc.bs.framework.common.RuntimeEnv;
import nc.bs.iufo.dao.SQLExec;
import nc.bs.logging.Logger;
import nc.itf.ls.ILightScheduler;
import nc.itf.smart.ISmartService;
import nc.jdbc.framework.JdbcSession;
import nc.jdbc.framework.PersistenceManager;
import nc.jdbc.framework.SQLParameter;
import nc.jdbc.framework.exception.DbException;
import nc.jdbc.framework.processor.ColumnListProcessor;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.jdbc.framework.processor.ResultSetProcessor;
import nc.jdbc.framework.util.DBConsts;
import nc.md.MDBaseQueryFacade;
import nc.md.model.IBean;
import nc.md.model.ITable;
import nc.md.model.MetaDataException;
import nc.mddb.MDDBBaseQueryFacade;
import nc.pub.bi.clusterscheduler.SchedulerUtilities;
import nc.pub.bi.meta.IMeta;
import nc.pub.iufo.cache.CacheManager;
import nc.pub.smart.cache.GlobalConfig;
import nc.pub.smart.cache.GlobalConfigCache;
import nc.pub.smart.cache.SmartConfigCache;
import nc.pub.smart.cache.SmartDefCache;
import nc.pub.smart.cache.SmartModelCache;
import nc.pub.smart.context.SmartContext;
import nc.pub.smart.data.DataSet;
import nc.pub.smart.data.DataSetRequest;
import nc.pub.smart.data.DbTable;
import nc.pub.smart.data.DbTableType;
import nc.pub.smart.data.SmartModelData;
import nc.pub.smart.data.dialect.IDataBaseDialect;
import nc.pub.smart.exception.SmartException;
import nc.pub.smart.metadata.DataTypeConstant;
import nc.pub.smart.metadata.Field;
import nc.pub.smart.metadata.MetaData;
import nc.pub.smart.model.DefaultExecStrategy;
import nc.pub.smart.model.MaterExecStrategy;
import nc.pub.smart.model.SmartModel;
import nc.pub.smart.model.descriptor.ConfigDescriptor;
import nc.pub.smart.model.descriptor.Descriptor;
import nc.pub.smart.provider.impl.procedure.ProcedureRequest;
import nc.pub.smart.provider.impl.procedure.ProcedureResult;
import nc.pub.smart.script.engine.MetaLinkFinder;
import nc.pub.smart.script.engine.ScriptEngine;
import nc.pub.smart.script.engine.event.ProcessOrderByEvent;
import nc.pub.smart.script.expression.LongValue;
import nc.pub.smart.script.expression.operators.relational.EqualsTo;
import nc.pub.smart.script.statement.select.AllColumns;
import nc.pub.smart.script.statement.select.Limit;
import nc.pub.smart.script.statement.select.PlainSelect;
import nc.pub.smart.script.statement.select.Select;
import nc.pub.smart.script.statement.select.SelectBody;
import nc.pub.smart.script.statement.select.SelectItem;
import nc.pub.smart.script.statement.select.SubSelect;
import nc.pub.smart.script.statement.select.Union;
import nc.pub.smart.script.util.deparser.ExpressionDeParser;
import nc.pub.smart.script.util.deparser.StatementDeParser;
import nc.pub.smart.util.DescriptorUtil;
import nc.pub.smart.util.SmartUtilities;
import nc.pub.smart.util.SqlUtil;
import nc.pubitf.para.SysInitQuery;
import nc.vo.bi.clusterscheduler.TempTableVO;
import nc.vo.bi.clusterscheduler.TimeSettingVO;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.ls.TaskResult;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.pub.BusinessRuntimeException;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.smart.config.SmartDataSource;
import nccloud.commons.lang.StringUtils;
import oracle.jdbc.OracleTypes;
import uap.bs.ae.datasource.DataSourceManager;
import uap.pub.ae.datasource.DataSourceCache;
import uap.pub.ae.datasource.temptable.TempTableManager;
import uap.vo.ae.procedure.ParameterType;
import uap.vo.ae.procedure.ProcedureParameter;

/**
 * 语义模型服务
 *
 * @author liuyy
 *
 */
public class SmartService implements ISmartService {

	/**
	 * NC元数据主实体标记
	 */
	private static final String DB_MAINENTITY_TAG = "DBMainEntity";

	/**
	 * 将数据集快照为数据库一张临时表 一般写入内存数据库
	 *
	 * @param dataset
	 *            状态为open;
	 * @param table
	 *            元数据以及表类型（table）不能为空；
	 * @return
	 */
	public DbTable storeDataSet(DataSet dataset, DbTable table)
			throws Exception {
		if (dataset.getMetaData() == null && table.getDsName() == null)
			throw new IllegalArgumentException(
					"MetaData or datasource name  is Null");

		table.setMetaData(dataset.getMetaData());

		if (table.getTablename() == null) {
			table.setTablename(DbTable.genTempName());
		}

		// 保证已有表不被覆盖
		if (SmartUtilities.getDDCService().isTableExisted(table)) {
			table.setTablename(DbTable.genTempName());
		}

		PerfWatch pw = new PerfWatch("SmartService.storeDataSet(): "
				+ table.getTablename());
		try {
			pw.appendMessage(table);
			pw.appendMessage(" rowCount:" + dataset.getCount());
			
			//wby 20220722 读写分离，创建临时表指定写库数据源
			String adgDsName = table.getDsName();
			if(adgDsName.toUpperCase().contains("ADG")) {
				String wDsName = "NCCDATA";
				try {
					wDsName = SysInitQuery.getParaString("GLOBLE00000000000000", "ADGParam01");
					if(StringUtils.isEmpty(wDsName)) {
						wDsName = adgDsName;
					}
					
				} catch (Exception e) {
					ExceptionUtils.wrappException(e);
				}
				table.setDsName(wDsName);//临时指定写库创建临时表
			}
			
			SmartUtilities.getDDCService().createTable(table);
			
			//wby 20220722 报表数据源为ADG 则创建临时表到写库后等待同步到ADG数据库
			if(adgDsName.toUpperCase().contains("ADG")) {
				Integer second = SysInitQuery.getParaInt("GLOBLE00000000000000", "ADGWaitTim");
				if (second != null && second > 0) {
					Thread.sleep(second * 1000);
				} else {
					Thread.sleep(1000);
				}
				
				//wby 20220726 创建完临时表需要指定回读库 读库支持DDL操作（增，删，改）
				table.setDsName(adgDsName);
			}
			
//			SQLExec.execBatch(
//					table.getDsName(),
//					SqlUtil.getInsertSQLWithParam(dataset.getMetaData(),
//							table.getTablename(),
//							SmartUtilities.getDbType(table.getDsName())),
//					SqlUtil.getSQLParam(dataset));
			execBatch(table.getDsName(), SqlUtil.getInsertSQLWithParam(dataset.getMetaData(),table.getTablename(),SmartUtilities.getDbType(table.getDsName())),SqlUtil.getSQLParam(dataset));
			
		} catch (Exception e) {
			pw.appendMessage(e);
			throw e;
		} finally {
			pw.stop();
		}
		return table;
	}
	
	/*
	 * wby 20220728 读写分离改造 需要先提交事务，再等待同步到数据
	 */
	private int execBatch(String dsName, String sql, SQLParameter[] params) {
		 if (dsName == null) {
			 throw new IllegalArgumentException("SQLExec: dsName is null.");
		 }
		 
		 dsName = getPhysicalDS(dsName);
		 
		 if (sql == null || sql.length() < 1) {
			 return 0;
		 }
		 
		 PersistenceManager persist = null;
		 JdbcSession jdbc = null;
		 
		 try {
			 persist = DataSourceManager.getInstance().getPersistenceManager(dsName);
			 persist.setAddTimeStamp(false);
			 jdbc = persist.getJdbcSession();
			 jdbc.setSQLTranslator(false);
			 jdbc.addBatch(sql, params);
			 
			 if(dsName.toUpperCase().contains("ADG")) {
				 jdbc.addBatch("commit");
			 }
			 return jdbc.executeBatch();
		 } catch (Exception e) {
			 AppDebug.error(e);
			 throw new RuntimeException(NCLangRes4VoTransl.getNCLangRes().getStrByID("1413002_0", "01413002-0964") + e.getMessage(), e);
		 } finally {
			 if (jdbc != null) {
				 jdbc.closeAll(); 
			 }
			 if (persist != null) {
				 persist.release();
			 }
		 }
	}
	
	/*
	 * wby 20220728 读写分离改造
	 */
	private static String getPhysicalDS(String dsName) { return DataSourceCache.getPhysicalDSName(dsName); }
	
	public DbTable storeDataSet_RequiresNew(DataSet dataset, DbTable table)
			throws Exception {
		return storeDataSet(dataset,table);
	}

	// /**
	// * 抽取数据 liuyy.
	// *
	// * @param metaData
	// * @param sql
	// * @param dsName
	// * @return
	// */
	// public Object[][] fetchData(final MetaData metaData, String sql,
	// String dsName) {
	// if (metaData == null || sql == null || dsName == null) {
	// throw new IllegalArgumentException();
	// }
	// Object obj = new Object[0][];
	// final PerfWatch pw = new PerfWatch("SmartService.fetchData()");
	// pw.appendMessage("dsName: " + dsName).appendMessage("sql: " + sql);
	// try {
	// obj = SQLExec.execQuery(dsName, sql, new ResultSetProcessor() {
	// private static final long serialVersionUID = 1L;
	//
	// public Object handleResultSet(ResultSet rs) throws SQLException {
	// // 根据查询结果过滤字段，因为有限制列的描述器存在，不是所有元数据中的字段都会查询出来。liuyy
	// // 2009-08-14
	// Field[] columns = getColumnNamesByResultSet(rs);
	//
	// List<Field> listFlds = new ArrayList<Field>();
	// // 要读取列在元数据中的位置
	// final Map<String, Integer> hashIndex = new HashMap<String, Integer>();
	// for (Field col : columns) {
	// Field f = metaData.getField(col.getFldname());
	// if (f != null) {
	// listFlds.add(f);
	// hashIndex.put(f.getFldname(), metaData.getIndex(f));
	// }
	// }
	// List<Object[]> rowList = new ArrayList<Object[]>();
	// int metaDataFieldNum = metaData.getFieldNum();
	//
	// while (rs.next()) {
	// Object[] data = new Object[metaDataFieldNum];
	// for (Field field : listFlds) {
	// Object value = null;
	// try {
	// value = rs.getObject(field.getFldname());
	// value = SmartUtilities.convert2TargetType(
	// field.getDataType(), value);
	// int index = hashIndex.get(field.getFldname());
	// data[index] = value;
	// } catch (Exception e) {
	// AppDebug.debug(e);
	// }
	// }
	// rowList.add(data);
	// }
	// Object[][] datas = rowList.toArray(new Object[0][]);
	// pw.appendMessage("FetchData Count: " + datas.length);
	// return datas;
	//
	// }
	// });
	// } catch (Exception e) {
	// pw.appendMessage(e);
	// throw new RuntimeException(e.getMessage(), e);
	// } finally {
	// pw.stop();
	// }
	//
	// return (Object[][]) obj;
	//
	// }

	/**
	 * 抽取元数据信息 liuyy.
	 *
	 * @param sql
	 * @param dsName
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("deprecation")
	public MetaData fetchMetaData(String sql, String dsName) throws Exception {

		if (sql == null || sql.trim().length() == 0) {
			throw new IllegalArgumentException("sql is null.");
		}

		DbType dbType = SmartUtilities.getDbType(dsName);
		// 尝试走脚本模型解析
		Select select = null;
		try {
			select = (Select) ScriptEngine.parse(sql);
		} catch (Exception e) {
			select = null;
		}
		if (select != null) {
			SelectBody sb = select.getSelectBody();
			PlainSelect ps = null;
			if (sb instanceof PlainSelect) {
				ps = (PlainSelect) sb;
			} else if (sb instanceof Union) {
				Union union = (Union) sb;
				ps = new PlainSelect();
				// ----select字段--------
				List<SelectItem> selectItemList = new Vector<SelectItem>();
				selectItemList.add(new AllColumns());
				ps.setSelectItems(selectItemList);

				// --------from 表名----------
				SubSelect subSelect = new SubSelect();
				subSelect.setSelectBody(union);
				subSelect.setAlias("nestQuery");
				ps.setFromItem(subSelect);

				select.setSelectBody(ps);
			}else{
				ps = new PlainSelect();
			}

			// where中增加1=0
			if(dbType == DbType.GBASE){
				Limit limit = new Limit();
				limit.setRowCount(1);
				ps.setLimit(limit);
			}else{
				EqualsTo equal = new EqualsTo();
				equal.setLeftExpression(new LongValue(1));
				equal.setRightExpression(new LongValue(0));
				ps.addWhereExpression(equal);
			}

			// 反解析
			StringBuffer sbf = new StringBuffer();
			StatementDeParser dp = new StatementDeParser(sbf);
			dp.visit(select, new ExpressionDeParser());
			sql = sbf.toString();
		} else {
			// 字符串处理：做嵌套 select * from (原始sql) temp where 1=0
			if(dbType == DbType.GBASE){
				sql = "select * from (" + sql + ") temp limit 1";
			}else{
				sql = "select * from (" + sql + ") temp where 1=0";
			}

		}

		Object obj = new Object[0];

		try {
			/* 临时表取数逻辑 */
			if (StringUtils.indexOf(sql, DbTable.PREX_TEMP_TABLE) > 0) {
				obj = TempTableManager.getTempTableManager().execQuery(dsName, sql, new ResultSetProcessor() {
					private static final long serialVersionUID = -4156999551501797136L;

					public Object handleResultSet(ResultSet rs) throws SQLException {
						return SmartResultSetProcessor.getColumnNamesByResultSet(rs);
					}
				}, true);
			} else {
				obj = SQLExec.execQuery(dsName, sql, new ResultSetProcessor() {
					private static final long serialVersionUID = 3660339080876010242L;

					public Object handleResultSet(ResultSet rs) throws SQLException {
						return SmartResultSetProcessor.getColumnNamesByResultSet(rs);
					}
				}, true);
			}
		} catch (DbException dbe) {
			AppDebug.error("Error sql: " + sql);
			AppDebug.error(dbe);

			// 对于数据库异常，后台记录日志，直接封装message，抛弃原始异常
			throw new SmartException("DataBase access error:"
					+ dbe.getMessage());
		} catch (Exception e) {
			AppDebug.error("Error sql: " + sql);
			throw new SmartException(e.getMessage(), e);
		} 
		
		MetaData md = new MetaData();
		md.addField((Field[]) obj);
		return md;

	}

	/**
	 * 读取数据
	 *
	 * @throws SmartException
	 */
	public DataSet fetchDataSet(String sql, String dsName)
			throws SmartException {
		DataSetRequest request = new DataSetRequest(sql, dsName);
		return fetchDataSet(request);
	}

	/**
	 * 读取数据
	 *
	 * 依据metadata来构建结果数据集，涉及 字段顺序、数据类型 等。metadata 可为空 遵循原则：
	 * --字段顺序：metadata中有，sql中没有的 去掉； metadata中没有，sql中有的 附加在最后面；
	 * --类型转换：依据metadata中数据类型做类型转换
	 *
	 * @throws Exception
	 */
	public DataSet fetchDataSet(DataSetRequest request) throws SmartException {

		final PerfWatch pw = new PerfWatch(
				"SmartService.fetchDataSet(DataSetRequest)");
		pw.appendMessage("maxRows: " + request.getMaxRows());

		String dsName = request.getDsName();
		String sql = request.getSql();
		if (dsName == null || dsName.trim().length() < 1) {
			dsName = SmartUtilities.getCurrentDsName();
		}

		if (sql == null || dsName == null) {
			throw new IllegalArgumentException();
		}
		Object obj = new Object[0][];
		pw.appendMessage("dsName: " + dsName).appendMessage("sql: " + sql);

		// 处理脚本规则
		if (request.isEnableScriptRule()) {
			try {
				Select select = (Select) ScriptEngine.parse(sql);

				SmartContext context = new SmartContext();
				context.setDsName4Exec(dsName);
				ProcessOrderByEvent evt = new ProcessOrderByEvent(select,
						context);

				select = ScriptEngine.handleEvent(evt);

				// 生成sql
				sql = ScriptEngine.select2Sql(select);
			} catch (Throwable e) {
				String message = "SmartService.fetchDataSet():catch exception when process sql with scriptRule:"
						+ e.getMessage();
				Logger.error(message);
				pw.appendMessage(message);
			}
		}

		SmartResultSetProcessor rsProcessor = null;
		
		//如果有扩展结果集，使用扩展结果集
		String clzName = request.getRsProcessorClzName();
		if(clzName != null){
			try {
				Class<?> cls = Class.forName(clzName);
				Constructor<?> cons = cls.getConstructor(DataSetRequest.class);
				Object extProcessor = cons.newInstance(request);
				if(extProcessor != null && extProcessor instanceof SmartResultSetProcessor){
					rsProcessor = (SmartResultSetProcessor)extProcessor;
				}
			} catch (ClassNotFoundException e) {
				AppDebug.error(e.getMessage());
			} catch (NoSuchMethodException e) {
				AppDebug.error(e.getMessage());
			} catch (Exception e) {
				AppDebug.error(e.getMessage());
			}finally{
				if(rsProcessor == null){
					rsProcessor = new SmartResultSetProcessor(request);
				}
			}
		}else{
			rsProcessor = new SmartResultSetProcessor(request);
		}
		
		try {
			/*临时表取数逻辑*/
			if (StringUtils.indexOf(sql, DbTable.PREX_TEMP_TABLE) > 0) {
				obj = TempTableManager.getTempTableManager().execQuery(dsName, sql,
						rsProcessor, request.isEnableSQLTranslator());
			} else {
				obj = SQLExec.execQuery(dsName, sql, rsProcessor,
						request.isEnableSQLTranslator());
			}
		} catch (DbException dbe) {
			pw.appendMessage("Error sql: " + sql);
			pw.appendMessage(dbe);
			AppDebug.error("Error sql: " + sql);
			AppDebug.error(dbe);

			// 对于数据库异常，后台记录日志，直接封装message，抛弃原始异常
			throw new SmartException("DataBase access error:"
					+ dbe.getMessage());
		} catch (Exception e) {
			pw.appendMessage("Error sql: " + sql);
			pw.appendMessage(e);
			AppDebug.error("Error sql: " + sql);
			throw new SmartException(e.getMessage(), e);
		} finally {
			pw.stop();
		}

		return (DataSet) obj;

	}

	/**
	 * 提取数据表内容
	 *
	 * @param table
	 * @return
	 * @throws Exception
	 */
	public DataSet fetchDataSet(DbTable table) throws SmartException {
		if (table == null || table.getMetaData() == null) {
			throw new IllegalArgumentException();
		}

		DataSetRequest request = new DataSetRequest(table.getMetaData(),
				table.toSelectSQL(), table.getDsName(), 0, true, false);
		DataSet dataset = fetchDataSet(request);

		return dataset;

	}

	

	

	/**
	 * 读取数据行数
	 *
	 * @param sql
	 *            原始select sql
	 * @param dsName
	 *            数据源
	 * @return
	 * @throws Exception
	 */
	public int fetchRecordCount(String sql, String dsName) throws Exception {
		// SQL Server 子查询中不允许有order by ---biancm 20090828
		DbType dbType = SmartUtilities.getDbType(dsName);
		if (dbType == DbType.SQLSERVER) {
			sql = SqlUtil.removeOrderBy(sql);
		}

		String countSql = "select count(1) num from (" + sql + ") temp_Count"; // 对sql进行count封装
		// try {
		return SQLExec.getRecordCount(dsName, countSql);
		// } catch (Exception e) {
		// throw new RuntimeException(e.getMessage(), e);
		// }

	}

	@Override
	public Integer[] provideCount(SmartModelData[] models)
			throws SmartException {
	  Logger.error("SmartService is in : [" + RuntimeEnv.getInstance().getNCHome() + "]");
		if (models == null)
			return new Integer[0];

		int size = models.length;
		Integer[] rslt = new Integer[size];
		PerfWatch pw = new PerfWatch("SmartService.provideCount()");
		try {
			for (int i = 0; i < size; i++) {
				SmartModelData data = models[i];
				SmartModel model = data.getModel();
				if (model == null) {
					continue;
				}
				rslt[i] = model.provideCount(data.getContext(),
						data.getDescriptors());
			}
		} catch (BusinessRuntimeException e) {
			pw.appendMessage(e);
			throw e;
		} catch (SmartException e) {
			pw.appendMessage(e);
			throw e;
		} catch (Exception e) {
			pw.appendMessage(e);
			throw new SmartException(e.getMessage(), e);
		} finally {
			pw.stop();
		}
		return rslt;
	}

	@Override
	public String[] provideSQL(SmartModelData[] models) throws SmartException {
		if (models == null)
			throw new IllegalArgumentException();
		int size = models.length;
		String[] rslt = new String[size];

		PerfWatch pw = new PerfWatch("SmartService.provideSQL()");
		try {
			for (int i = 0; i < size; i++) {
				SmartModelData data = models[i];
				SmartModel model = data.getModel();
				if (model == null) {
					continue;
				}
				rslt[i] = model.provideSQL(data.getContext(),
						data.getDescriptors());
			}
		} catch (BusinessRuntimeException e) {
			pw.appendMessage(e);
			throw e;
		} catch (SmartException e) {
			pw.appendMessage(e);
			throw e;
		} catch (Exception e) {
			pw.appendMessage(e);
			throw new SmartException(e.getMessage(), e);
		} finally {
			pw.stop();
		}
		return rslt;
	}

	@Override
	public DataSet[] provideData(SmartModelData[] models) throws SmartException {
		if (models == null)
			return new DataSet[0];

		PerfWatch pw = new PerfWatch("SmartService.provideData()");

		int size = models.length;
		DataSet[] rslt = new DataSet[size];
		pw.appendMessage("SmartModelData[]: " + size);
		try {
			for (int i = 0; i < size; i++) {
				SmartModelData data = models[i];
				SmartModel model = data.getModel();
				if (model == null) {
					continue;
				}
				rslt[i] = model.provideData(data.getContext(),
						data.getDescriptors());
			}
		} catch (BusinessRuntimeException e) {
			pw.appendMessage(e);
			throw e;
		} catch (SmartException e) {
			pw.appendMessage(e);
			throw e;
		} catch (Exception e) {
			pw.appendMessage(e);
			throw new SmartException(e.getMessage(), e);
		} finally {
			pw.stop();
		}
		return rslt;
	}

	@Override
	public DbTable[] provideView(SmartModelData[] models) throws SmartException {
		if (models == null)
			return new DbTable[0];

		PerfWatch pw = new PerfWatch("SmartService.provideView()");

		int size = models.length;
		DbTable[] rslt = new DbTable[size];
		try {
			for (int i = 0; i < size; i++) {
				SmartModelData data = models[i];
				SmartModel model = data.getModel();
				if (model == null) {
					continue;
				}
				rslt[i] = model.provideView(data.getContext(),
						data.getDescriptors());
			}
		} catch (BusinessRuntimeException e) {
			pw.appendMessage(e);
			throw e;
		} catch (SmartException e) {
			pw.appendMessage(e);
			throw e;
		} catch (Exception e) {
			pw.appendMessage(e);
			throw new SmartException(e.getMessage(), e);
		} finally {
			pw.stop();
		}

		return rslt;
	}

	/**
	 * 提供元数据MetaData 注意：根据语义模型生成的sql语句来加载。不是直接取模型的元数据 内部使用。外部不推荐使用
	 *
	 * @param models
	 * @return
	 * @throws SmartException
	 */
	public MetaData[] provideMetaData(SmartModelData[] models)
			throws SmartException {
		if (models == null)
			throw new IllegalArgumentException();
		int size = models.length;
		MetaData[] rslt = new MetaData[size];

		PerfWatch pw = new PerfWatch("SmartService.provideMetaData()");
		try {
			for (int i = 0; i < size; i++) {
				SmartModelData data = models[i];
				SmartModel model = data.getModel();
				if (model == null) {
					continue;
				}

				DefaultExecStrategy execStrategy = new DefaultExecStrategy(
						model);
				String sql = execStrategy.provideSQL(data.getContext(),
						data.getDescriptors());
				String dsName = execStrategy.provideDsName4Exec(null);
				MetaData md = fetchMetaData(sql, dsName);
				rslt[i] = md;
			}
		} catch (BusinessRuntimeException e) {
			pw.appendMessage(e);
			throw e;
		} catch (SmartException e) {
			pw.appendMessage(e);
			throw e;
		} catch (Exception e) {
			pw.appendMessage(e);
			throw new SmartException(e.getMessage(), e);
		} finally {
			pw.stop();
		}
		return rslt;
	}

	@Override
	public DataSet execScript(String script, String dsName, IContext context)
			throws SmartException {
		SmartContext smartContext = new SmartContext(context);
		//设置下执行数据源
		try {
			if(smartContext.getDsName4Exec() == null){
				smartContext.setDsName4Exec(dsName);
			}
		} catch (Exception e) {
			AppDebug.error(e);
		}
		
		String sql = ScriptEngine.buildSQL(script, smartContext);
		return fetchDataSet(sql, dsName);
	}

	// /**
	// * 物化语义模型
	// *
	// * @param pk
	// * @param table 如果为空，则使用语义模型物化定义
	// */
	// public void storeSmartModel(String pk, DbTable table){
	// SmartModel model = SmartModelCache.getInstance().getModel(pk);
	// if(model == null){
	// return ;
	// }
	//
	// String tableName =
	// model.getPreferences().getConfigItem().getMaterTableName();
	// String dsName = model.getDsName();
	// DbTable dt = new DbTable(dsName, tableName, DbTable.TYPE_TABLE);
	//
	// SmartUtilities.getSmartService().dropTable(dt);
	//
	// DbTable view = model.provideView(null, null);
	// dt.setMetaData(view.getMetaData());
	//
	// }
	//

	/**
	 * 根据关联表达式获取目标字段
	 *
	 * @param model
	 *            语义模型
	 * @param smartscripts
	 *            关联表达式
	 * @return 找不到字段，返回null
	 */
	@Override
	public Field[] fetchField(SmartModel model, String... smartScripts) {
		if (smartScripts == null || smartScripts.length < 1) {
			return null;
		}

		Field[] fields = new Field[smartScripts.length];
		for (int i = 0; i < smartScripts.length; i++) {
			String script = smartScripts[i];
			Field f = MetaLinkFinder.findField(model, script);
			fields[i] = f;
		}
		return fields;
	}

	/**
	 * 客户端获取全局配置缓存内容
	 */
	public GlobalConfig getGlobalConfig() {
		return GlobalConfigCache.getGlobalConfig();
	}

	/**
	 * 保存语义模型数据源配置
	 *
	 * @param dataSource
	 * @throws Exception
	 */
	public void saveSmartDataSource(SmartDataSource dataSource)
			throws Exception {
		//added by biancm 20130529 如果定义数据源发生更改，清空所有缓存
		try {
			String originalDesignDS = SmartUtilities.getDefDsName();
			String currentDesignDS = dataSource.getDesignDsName();
			if (originalDesignDS != null && currentDesignDS != null
					&& !originalDesignDS.equalsIgnoreCase(currentDesignDS)) {
				CacheManager.refresh();
			}
		} catch (Exception e) {

		}


		// 更新缓存GlobalConfigCache
		GlobalConfigCache.getSmartConfig().setDataSource(dataSource);

		// 保存到文件
//		IBaseSPService service = NCLocator.getInstance().lookup(
//				IBaseSPService.class);
//		service.saveSmartDataSource(dataSource);
		(new ConfigDBTool()).saveSmartDataSource(dataSource);
	}

	/**
	 * 手动启动异步执行物化
	 *
	 * @param smartId
	 */
	public void asyncExecMater(String smartId) {
		SmartMaterialTask.asyncExecMater(smartId);
	}

	/**
	 * 执行语义模型物化
	 *
	 * @param smartId
	 *            语义模型id
	 * @throws Exception
	 */
	public DbTable execMater(String smartId) throws Exception {
		String code = SmartDefCache.getInstance().getNameWithCode(smartId);
		PerfWatch pw = new PerfWatch("MaterExecStrategy.execMater: " + code);
		SmartModel model = SmartModelCache.getInstance().getModel(smartId);
		if (model == null) {
			pw.appendMessage(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
					.getStrByID("8001002_0", "08001002-0148", null,
							new String[] { smartId })/*
													 * @res "语义模型(" + smartId
													 * +")为空！"
													 */);
		}
		String tableName = null;
		MaterExecStrategy exeStr = new MaterExecStrategy(model);
		if (!exeStr.haveMaterDef()) {
			pw.appendMessage(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
					.getStrByID("1413002_0", "01413002-1023")/* @res "物化定义为空" */);
			tableName = DbTable.genTempName();
		} else {
			tableName = model.getPreferences().getConfigItem().getMaterConfig()
					.getTableName();

		}

		try {
			// 构建context
			// 加入宏变量
			SmartContext context = model.getInitialContext();

			// added by zhangyth 2012-12-10
			// 执行物化前，如果参数值为空，则将参数移除。
			String[] names = context.getAttributeNames();
			for (String name : names) {
				if (name.startsWith("parameter_")) {
					Object value = context.getAttribute(name);
					if ("".equals(value)) {
						context.removeAttribute(name);
					}
				}
			}
			// end

			// 物化数据源
			String dsName = exeStr.provideDsName4Exec(null);

			String sql = new DefaultExecStrategy(model).provideSQL(context,
					null);
			// 模型执行数据源
			String current_exeDsName = new DefaultExecStrategy(model)
					.provideDsName4Exec(null);

			DbTable srcTable = DbTable.generateTempSql(model.getMetaData(),
					sql, current_exeDsName);

			DbTable dt = new DbTable(dsName, tableName, DbTableType.TABLE);
			SmartUtilities.getDDCService().copyTable(srcTable, dt);
			//add by luaidi 记录任务最后执行时间 并更新bi_schd_timer
			String scheduleid = (String)model.getExtProp("scheduleid");
			List<TaskResult>  taskResults = null;
			UFDateTime lasttime = null;
			ILightScheduler schedule =  NCLocator.getInstance().lookup(ILightScheduler.class);
			//如果有scheduleid代表走得是轻量级调度 
			if(scheduleid != null && !StringUtils.isEmpty(scheduleid)) {
				taskResults = schedule.getResults(scheduleid);
				if(taskResults != null && taskResults.size()>0) {
					//取最新时间
					lasttime =  taskResults.get(taskResults.size()-1).getEndTime();
				}
				
				//获取TimeSettingVO 并更新
				TimeSettingVO  timesetvo = new TimeSettingVO();
				String dydsName = SmartConfigCache.getDsName4Design();
				timesetvo = SchedulerUtilities.loadTimeSetting(smartId, dydsName);
				timesetvo.setLastTime(String.valueOf(lasttime));
				SchedulerUtilities.addTimeSetting(timesetvo,dydsName);
			}
			return dt;
		} catch (Exception e) {
			pw.appendMessage(e);
			throw new MessageException(nc.vo.ml.NCLangRes4VoTransl
					.getNCLangRes().getStrByID("1413002_0", "01413002-1024")/*
																			 * @res
																			 * "执行物化错误："
																			 */
					+ e.getMessage(), e);
		} finally {
			pw.stop();

		}
	}

	@Override
	public DataSet fetchAdhocDataSet(IContext context, IMeta meta,
			String linkModuleId, Descriptor[] des) throws SmartException {

		// 将IMeta转成SmartModel
		SmartModel model = SmartUtilities.meta2Model(meta);

		// 设置SmartContext
		SmartContext smartContext = new SmartContext(context);
		smartContext.setDsName4Exec(meta.getDsName());
		smartContext.setAttribute(SmartContext.KEY_CURR_LINK_MODULE_ID,
				linkModuleId);
		smartContext.setAttribute(SmartContext.KEY_CURR_META, meta);

		// 不能直接调用语义模型的provideData（元数据顺序问题）
		// return model.provideData(smartContext, des);

		String sql = model.provideSQL(smartContext, des);

		// 取AdhocDataSet
		// 最大行
		int maxRows = 0;
		ConfigDescriptor config = DescriptorUtil.getDescriptorByType(
				ConfigDescriptor.class, des);
		if (config != null) {
			maxRows = config.getMaxRows();
			maxRows = maxRows > 0 ? maxRows : model.getPreferences().getConfigItem().getMaxRows();
		}

		DataSetRequest request = new DataSetRequest(sql, meta.getDsName());
		request.setMetadata(meta.getMetaData());
		request.setMaxRows(maxRows);
		DataSet dataSet = fetchDataSet(request);
		return dataSet;
	}

	@Override
	public IBean getEntityByTableID(String tableID) throws SmartException {
		IBean bean;
		try {
			ITable table = null;
			table = MDDBBaseQueryFacade.getInstance().getTableByID(tableID);

			String pkColumnID = table.getPrimaryKey().getPKColumn().getID();
			bean = getEntityByPKColumnID(pkColumnID, tableID);// 该table对应的实体
		} catch (Exception e) {
			throw new SmartException("load entity by table error:"
					+ e.getMessage(), e);
		}
		return bean;
	}

	/**
	 * 根据表pk查找NC元数据实体
	 *
	 * @param pkColumnID
	 * @param tableID
	 * @return
	 */
	private IBean getEntityByPKColumnID(String pkColumnID, String tableID) {
		// 这里如果该表对应多个实体的话，取第一个
		String sql = "select distinct classid from md_ormap where columnid = '"
				+ pkColumnID + "'";
		String beanID = null;
		try {
			List<String> idList = (List<String>) (new BaseDAO().executeQuery(
					sql, new ColumnListProcessor()));
			if (idList != null && idList.size() > 0) {
				if (idList.size() > 1) {
					beanID = getMainEntityFromTable(idList);
				} else {
					beanID = idList.get(0);
				}
			} else {
				String sqlTable = "select distinct classid from md_ormap where tableid = '"
						+ tableID + "'";
				List<String> idListForTable = (List<String>) (new BaseDAO()
						.executeQuery(sqlTable, new ColumnListProcessor()));
				if (idListForTable != null && idListForTable.size() > 0) {
					if (idListForTable.size() > 1) {
						beanID = getMainEntityFromTable(idListForTable);
					} else {
						beanID = idListForTable.get(0);
					}
				}
			}
		} catch (DAOException e1) {
			Logger.error("根据列查询实体，查询失败！列id：" + pkColumnID + " ###@@# " + e1);
		}
		if (StringUtil.isEmptyWithTrim(beanID)) {
			return null;
		}
		IBean bean = null;
		try {
			bean = MDBaseQueryFacade.getInstance().getBeanByID(beanID);
		} catch (MetaDataException e) {
			Logger.error("查询元数据失败！元数据实体id：" + beanID + e);
			return null;
		}
		return bean;
	}

	/**
	 * 查找主实体
	 *
	 * @param beanIDlist
	 * @return
	 * @throws DAOException
	 */
	private String getMainEntityFromTable(List<String> beanIDlist)
			throws DAOException {

		StringBuffer inSql = new StringBuffer("'" + beanIDlist.get(0) + "'");
		for (int i = 1; i < beanIDlist.size(); i++) {
			inSql.append(", '" + beanIDlist.get(i) + "'");
		}
		String sql = "select id,help from md_class where id in (" + inSql + ")";
		List<Map<String, String>> result = (List<Map<String, String>>) new BaseDAO()
				.executeQuery(sql, new MapListProcessor());
		for (Map<String, String> value : result) {
			if (value != null && !StringUtil.isEmptyWithTrim(value.get("help"))
					&& value.get("help").contains(DB_MAINENTITY_TAG)) {
				return value.get("id");
			}
		}
		return beanIDlist.get(0);
	}

	/**
	 * 2013-11-29 添加，删除临时表
	 * @see TempTableSchdTask的dropTempTables1和totalMin方法
	 * @param dsName 数据源名称，为空抛出SmartException，当前数据源需要在外部处理
	 * @throws SmartException
	 */
	public void dropTempTable(String dsName) throws SmartException{
		if(StringUtils.isEmpty(dsName)){
			throw new SmartException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("0301002_0","00301002-0002")/*@res "删除临时表异常：数据源为空"*/);
		}

		//读取数据源dsName上的临时表，1000这个参数没用
		TempTableVO[] vos = SmartUtilities.getDDCService()
				.getTempTableNames(dsName, 1000);
		if (vos == null || vos.length < 1) {
			return;
		}

		//构造PerfWatch
		PerfWatch pw = new PerfWatch("SmartService.dropTempTable():" + dsName);
		pw.setModule("SmartService");

		//构造删除语句
		List<String> sqls = new ArrayList<String>();

		final long timeouts = 10;//删除创建时间到现在间隔超过10分钟的临时表

		for (TempTableVO vo : vos) {
			try {
				String tableName = vo.getTablename();
				String[] arr =  tableName.split("_");
				if(arr == null || arr.length < 3){
					continue;
				}
				try {
					String createTime = arr[arr.length - 1];
					Calendar calendar = Calendar.getInstance();
					SimpleDateFormat fmt = (SimpleDateFormat) new SimpleDateFormat(
							"HHmm");
					String time = fmt.format(calendar.getTime());

					int old = totalMin(createTime);
					int curr = totalMin(time);
					int diff = curr - old;
					if(diff < 0){
						diff += 24 * 60;
					}

					if (diff < timeouts) {
						continue;
					}

				} catch (Exception e) {
					continue;
				}

				String sql = "drop " + vo.getTableType() + " "
						+ vo.getTablename();
				sqls.add(sql);

			} catch (Exception e) {
				pw.appendMessage(e);
			}
		}

		//执行删除语句
		try {
			//JdbcSession中的批量执行已经自动实现了分页批量提交的功能
			SQLExec.execBatch(dsName, sqls.toArray(new String[sqls.size()]));
		} catch (Exception e) {
			pw.appendMessage(sqls);
			throw new SmartException(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("0301002_0","00301002-0003")/*@res "删除临时表异常："*/+ (StringUtils.isEmpty(e.getMessage()) ? e : e.getMessage()));
		}
	}

	/**
	 * 将HHmm格式的时间，转化为以分为单位的时间
	 * @see this.dropTempTable()
	 * @param flag
	 * @return HH x 60 + mm
	 */
	private int totalMin(String flag){//HHmm
		int hour0 = new Integer(flag.substring(0, 2));
		int min0  = new Integer(flag.substring(2, 4));
		int total = hour0 * 60 + min0;

		return total;
	}

	@Override
	public ProcedureResult callProcedure(ProcedureRequest procedureRequest) throws SmartException {
		
		ProcedureResult procedureResult = new ProcedureResult();
		
		String dsName = procedureRequest.getProcedure().getDsName();
		ProcedureParameter[] parameters = procedureRequest.getProcedure().getParameters();

		PersistenceManager persist = null;
		CallableStatement stmt = null;
		try {
			dsName = DataSourceCache.getPhysicalDSName(dsName);
			persist = DataSourceManager.getInstance().getPersistenceManager(dsName);
			//获取数据库类型
			DbType dbType = getDbType(persist);
			//如果运行时数据库类型与Procedure中数据库类型不匹配，更新Procedure中数据库类型
			if(dbType != procedureRequest.getProcedure().getDbType() && dbType != DbType.UNKNOWN) {
				procedureRequest.getProcedure().setDbType(dbType);
			}
			String script = procedureRequest.getProcedure().getScript();
			stmt = persist.getJdbcSession().getConnection().prepareCall(script);
			
			// 设置参数,排除RETURN参数
			if(parameters != null) {
				int i = 0;
				for(ProcedureParameter parameter: parameters) {
					ParameterType type = parameter.getType();
 					if(type == ParameterType.IN || type == ParameterType.INOUT) {
						Object value = procedureRequest.getParameterValue(parameter.getName());
						setInParamValue(parameter, i+1, value, stmt);
					}
					if(type == ParameterType.OUT || type == ParameterType.INOUT) {
						registOutParam(parameter, i+1, stmt, dbType);
					}
					if(type != ParameterType.RETURN) {
						i++;
					}
				}
			}
			
			// 执行存储过程
			stmt.execute();
			// 设置返回值
			ResultSet resultSet = stmt.getResultSet();
			if(resultSet != null) {
				procedureResult.setResultDataSet(
						(DataSet) new SmartResultSetProcessor(new DataSetRequest(null, null)).handleResultSet(resultSet)
					);
			}
			
			// 获取输出参数值
			if(parameters != null) {
				int i = 0;
				for(ProcedureParameter parameter: parameters) {
					ParameterType type = parameter.getType();
					if(type == ParameterType.OUT || type == ParameterType.INOUT){
						Object result = getOutParamValue(parameter, i+1, stmt, dbType);
						//设置Out参数值
						procedureResult.getOutParamValueMap().put(parameter.getName(), result);
					}
					if(type != ParameterType.RETURN) {
						i++;
					}
				}
			}
		} catch (DbException e) {
			throw new SmartException(e.getMessage());
		} catch (SQLException e) {
			throw new SmartException(e.getMessage());
		} catch (Exception e) {
			throw new SmartException(e.getMessage());
		} finally {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					//do nothing
				}
			}
			if (persist != null) {
				persist.release();
			}
		}
		
		return procedureResult;
	}
	
	private DbType getDbType(PersistenceManager persist) {
		DbType type;
		int iDBType = persist.getDBType();
		switch (iDBType) {
			case DBConsts.DB2:
				type = DbType.DB2;
				break;
			case DBConsts.ORACLE:
				type = DbType.ORACLE;
				break;
			case DBConsts.SQLSERVER:
				type = DbType.SQLSERVER;
				break;
			case DBConsts.HSQL:
				type = DbType.HSQLDB;
				break;
			case DBConsts.POSTGRESQL:
				type = DbType.POSTGRESQL;
				break;
			case DBConsts.SYBASE:
				type = DbType.SYBASE;
				break;
			case DBConsts.GBASE:
				type = DbType.GBASE;
				break;
			case DBConsts.ALCEDO:
				type = DbType.ALCEDO;
				break;
			default:
				type = DbType.UNKNOWN;
		}
		return type;
	}
	
	private Object getOutParamValue(ProcedureParameter parameter, int index, CallableStatement stmt, DbType dbType) throws SmartException {
		
		Object result = null;
		try{
			Method method;
			if(dbType == DbType.ORACLE && parameter.getSqlType() == OracleTypes.CURSOR) {
				method = stmt.getClass().getMethod("getCursor", int.class);
			}else {
				method = CallableStatement.class.getMethod(parameter.genGetter(), int.class);
			}
			result = method.invoke(stmt, index);
		} catch (IllegalAccessException e) {
			throw new SmartException(e.getMessage(), e);
		} catch (IllegalArgumentException e) {
			throw new SmartException(e.getMessage(), e);
		} catch (InvocationTargetException e) {
			throw new SmartException(e.getMessage(), e);
		} catch (NoSuchMethodException e) {
			throw new SmartException(e.getMessage(), e);
		} catch (SecurityException e) {
			throw new SmartException(e.getMessage(), e);
		}
		
		//处理结果集情况
		if(result instanceof ResultSet) {
			DataSet dataSet;
			try {
				dataSet = (DataSet) new SmartResultSetProcessor(new DataSetRequest(null, null)).handleResultSet((ResultSet) result);
				result = dataSet;
			} catch (SQLException e) {
				throw new SmartException(e.getMessage());
			}
		}
		
		return result;
	}
	
	private void registOutParam(ProcedureParameter parameter, int index, CallableStatement stmt, DbType dbType) throws SmartException {
		int sqlType = parameter.getSqlType();
		if(sqlType == Types.OTHER && parameter.getTypeName().equals("REF CURSOR") && dbType == DbType.ORACLE) {
			sqlType = OracleTypes.CURSOR;
		}
		
		try {
			Method method;
			method = CallableStatement.class.getMethod("registerOutParameter", int.class, int.class);
			method.invoke(stmt, index, sqlType);
		} catch (NoSuchMethodException e) {
			throw new SmartException(e.getMessage(), e);
		} catch (SecurityException e) {
			throw new SmartException(e.getMessage(), e);
		} catch (IllegalAccessException e) {
			throw new SmartException(e.getMessage(), e);
		} catch (IllegalArgumentException e) {
			throw new SmartException(e.getMessage(), e);
		} catch (InvocationTargetException e) {
			throw new SmartException(e.getMessage(), e);
		}
		
	}
	
	private void setInParamValue(ProcedureParameter parameter, int index, Object value, CallableStatement stmt) throws SmartException {
		
		Method method;
		if(value == null || value.equals("")) {
			//参数值为空的情况
			try {
				stmt.setNull(index, parameter.getSqlType());
			} catch (SQLFeatureNotSupportedException e) {
				// 不支持调用setNull的类型
				throw new SmartException(e.getMessage());
			} catch (SQLException e) {
				throw new SmartException(e.getMessage());
			}
		}else {
			try {
				method = PreparedStatement.class.getMethod(parameter.genSetter(), int.class, parameter.getJavaType());
				method.invoke(stmt, index, value);
			} catch (NoSuchMethodException e) {
				throw new SmartException(e.getMessage(), e);
			} catch (SecurityException e) {
				throw new SmartException(e.getMessage(), e);
			} catch (IllegalAccessException e) {
				throw new SmartException(e.getMessage(), e);
			} catch (IllegalArgumentException e) {
				throw new SmartException(e.getMessage(), e);
			} catch (InvocationTargetException e) {
				throw new SmartException(e.getMessage(), e);
			}
		}
		
	}
	@SuppressWarnings("serial")
	private static class DataSetResultSetProcessor implements ResultSetProcessor {
		
		@Override
		public Object handleResultSet(ResultSet resultSet) throws SQLException {
			return resultSet2DataSet(resultSet);
		}
		
		private DataSet resultSet2DataSet(ResultSet rs) throws SQLException {
			Field[] new_fields = getColumnNamesByResultSet(rs);

			MetaData meta = new MetaData(new_fields);

			DataSet dataset = fetchDatas(rs, meta);

			return dataset;
		}

		private DataSet fetchDatas(ResultSet rs, MetaData meta) throws SQLException {
			List<Object[]> rowList = new ArrayList<Object[]>();

			Field[] fields = meta.getFields();

			int metaDataFieldNum = fields.length;

			while (rs.next()) {
				Object[] data = new Object[metaDataFieldNum];
				for (int i = 0; i < metaDataFieldNum; i++) {
					Field field = fields[i];
					Object value = null;

					if (field.getDataType() == DataTypeConstant.OBJECT) {
						value = getBlobValue(rs, field.getFldname());
					} else {
						value = rs.getObject(i + 1);
					}

					value = SmartUtilities.convert2TargetType(field.getDataType(), value);

					// added by zhangyth 处理精度，以语义模型向导中的精度为准，四舍五入。
					if (DataTypeConstant.isNumberType(field.getDataType()) && field.getScale() > 0) {
						try {
							value = processScale(value, field.getScale());
						} catch (Exception e) {
							AppDebug.error(e.getMessage());
						}
					}

					data[i] = value;
				}
				rowList.add(data);
			}

			Object[][] datas = rowList.toArray(new Object[0][]);
			DataSet ds = new DataSet(meta, datas);

			return ds;
		}

		private Object processScale(Object value, int scale) {

			if (value == null) {
				return null;
			}

			if (value instanceof BigDecimal) {
				return ((BigDecimal) value).setScale(scale, BigDecimal.ROUND_HALF_UP);
			} else {
				if (value instanceof Double) {
					value = BigDecimal.valueOf((Double) value);
					value = ((BigDecimal) value).setScale(scale, BigDecimal.ROUND_HALF_UP);
					return Double.valueOf(value.toString());
				} else if (value instanceof Float) {
					value = BigDecimal.valueOf((Float) value);
					value = ((BigDecimal) value).setScale(scale, BigDecimal.ROUND_HALF_UP);
					return Float.valueOf(value.toString());
				}
			}

			return value;
		}

		/**
		 * 加载blob值
		 * 
		 * @param rs
		 * @param fieldName
		 * @return 可序列化对象
		 */
		private Serializable getBlobValue(ResultSet rs, String fieldName) {
			return null;
		}

		private static Field[] getColumnNamesByResultSet(ResultSet rs) throws SQLException {
			ResultSetMetaData rsmd = rs.getMetaData();
			int iColCount = rsmd.getColumnCount();
			List<Field> fieldList = new ArrayList<Field>();
			for (int i = 0; i < iColCount; i++) {
				int sqlType = rsmd.getColumnType(i + 1);
				String typeName = rsmd.getColumnTypeName(i + 1);

				// DB2容错，数据类型DECFLOAT
				if (sqlType == Types.OTHER && typeName.equalsIgnoreCase("decfloat")) {
					sqlType = Types.DECIMAL;
				}

				// 去掉分页sql中的行号列
				if (rsmd.getColumnName(i + 1).equalsIgnoreCase(IDataBaseDialect.ROW_NUMBER)) {
					continue;
				}

				Field fld = new Field();
				fieldList.add(fld);
				fld.setDataType(DataTypeConstant.translateType(sqlType));
				fld.setDbColumnType(sqlType);

				//字段名
				String fldName = rsmd.getColumnName(i + 1);
				String label = rsmd.getColumnLabel(i + 1);
				if (label != null && label.trim().length() > 0 && !label.equalsIgnoreCase(fldName)) {
					fldName = label;// 有些驱动实现中label与name不一致。做下容错
				}
				fld.setFldname(fldName);

				int precision = rsmd.getPrecision(i + 1);
				fld.setPrecision(precision);

				int scale = rsmd.getScale(i + 1);
				fld.setScale(scale);
			}
			return fieldList.toArray(new Field[fieldList.size()]);
		}

	}
	@Override
	public uap.vo.ae.procedure.ProcedureResult callProcedure1(
			uap.vo.ae.procedure.ProcedureRequest procedureRequest)
			throws SmartException {
		uap.vo.ae.procedure.ProcedureResult procedureResult = new uap.vo.ae.procedure.ProcedureResult();
		
		String dsName = procedureRequest.getProcedure().getDsName();
		ProcedureParameter[] parameters = procedureRequest.getProcedure().getParameters();

		PersistenceManager persist = null;
		CallableStatement stmt = null;
		try {
			dsName = DataSourceCache.getPhysicalDSName(dsName);
			persist = DataSourceManager.getInstance().getPersistenceManager(dsName);
			//获取数据库类型
//			DbType dbType = getDbType(persist);
			DbType dbType = SmartUtilities.getDbType(dsName);
			//如果运行时数据库类型与Procedure中数据库类型不匹配，更新Procedure中数据库类型
			if(dbType != procedureRequest.getProcedure().getDbType() && dbType != DbType.UNKNOWN) {
				procedureRequest.getProcedure().setDbType(dbType);
			}
			String script = procedureRequest.getProcedure().getScript();
			stmt = persist.getJdbcSession().getConnection().prepareCall(script);
			
			// 设置参数,排除RETURN参数
			if(parameters != null) {
				int i = 0;
				for(ProcedureParameter parameter: parameters) {
					ParameterType type = parameter.getType();
 					if(type == ParameterType.IN || type == ParameterType.INOUT) {
						Object value = procedureRequest.getParameterValue(parameter.getName());
						setInParamValue(parameter, i+1, value, stmt);
						i++;
					}
					if(type == ParameterType.OUT || type == ParameterType.INOUT) {
						registOutParam(parameter, i+1, stmt, dbType);
						i++;
					}
				}
			}
			
			// 执行存储过程
			stmt.execute();
			// 设置返回值
			ResultSet resultSet = stmt.getResultSet();
			if(resultSet != null) {
				procedureResult.setResultDataSet(
						(DataSet) new DataSetResultSetProcessor().handleResultSet(resultSet)
					);
			}
			
			// 获取输出参数值
			if(parameters != null) {
				for(int i=0;i<parameters.length;i++){
					ProcedureParameter parameter = parameters[i];
					ParameterType type = parameter.getType();
					if(type == ParameterType.OUT || type == ParameterType.INOUT){
						Object result = getOutParamValue(parameter, i+1, stmt, dbType);
						//设置Out参数值
						procedureResult.getOutParamValueMap().put(parameter.getName(), result);
					}
				}
			}
		} catch (DbException e) {
			throw new SmartException(e.getMessage());
		} catch (SQLException e) {
			throw new SmartException(e.getMessage());
		} catch (Exception e) {
			throw new SmartException(e.getMessage());
		} finally {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					//do nothing
				}
			}
			if (persist != null) {
				persist.release();
			}
		}
		
		return procedureResult;
	}
}
