package com.wb.common;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 数据库数据字典。
 */
public class Dictionary {
	/** 字典数据缓存。 */
	public static ConcurrentHashMap<String, ConcurrentHashMap<String, com.wb.tool.DictRecord>> buffer;

	/**
	 * 在指定表名的字典信息中查找指定字段名称的字典定义记录。
	 * @param tableNames 表名列表。
	 * @param fieldName 字段名称。
	 * @return 字典定义记录。
	 */
	public static com.wb.tool.DictRecord find(String[] tableNames, String fieldName) {
		com.wb.tool.DictRecord dictRecord;
		ConcurrentHashMap<String, com.wb.tool.DictRecord> fieldMap;
		String upperFieldName = fieldName.toUpperCase();
		for (String tableName : tableNames) {
			fieldMap = buffer.get(tableName.toUpperCase());
			if (fieldMap != null) {
				dictRecord = fieldMap.get(upperFieldName);
				if (dictRecord != null) {
					if (dictRecord.linkTo == null)
						return dictRecord;
					else {
						String tableField[] = com.wb.util.StringUtil.split(dictRecord.linkTo.toUpperCase(), '.');
						fieldMap = buffer.get(tableField[0]);
						if (fieldMap == null)
							return null;
						else
							return fieldMap.get(tableField[1]);
					}
				}
			}
		}
		return null;
	}

	/**
	 * 获取指定表名的字典信息中所有配置有键值关系的字段组成的Map。如果未找到键值关系返回空的Map。
	 * @param tableNames 表名列表。
	 * @return 键值关系Map。
	 */
	public static HashMap<String, String> getKeyFields(String[] tableNames) {
		HashMap<String, String> keyMap = new HashMap<String, String>();
		com.wb.tool.DictRecord dictRecord;
		ConcurrentHashMap<String, com.wb.tool.DictRecord> fieldMap;

		for (String tableName : tableNames) {
			fieldMap = buffer.get(tableName.toUpperCase());
			if (fieldMap != null) {
				Set<Entry<String, com.wb.tool.DictRecord>> es = fieldMap.entrySet();
				for (Entry<String, com.wb.tool.DictRecord> e : es) {
					dictRecord = e.getValue();
					if (dictRecord.keyName != null)
						keyMap.put(e.getKey(), dictRecord.keyName);
				}
			}
		}
		return keyMap;
	}

	/**
	 * 获得结果集当前记录的字典定义对象。
	 * @param rs 结果集。
	 * @return 字典记录定义对象。
	 * @throws Exception 读取过程发生异常。
	 */
	public static com.wb.tool.DictRecord getDictRecord(ResultSet rs) throws Exception {
		com.wb.tool.DictRecord dictRecord = new com.wb.tool.DictRecord();
		dictRecord.linkTo = com.wb.util.StringUtil.force(rs.getString("LINK_TO"));
		dictRecord.listable = !"0".equals(rs.getString("LISTABLE"));
		dictRecord.editable = !"0".equals(rs.getString("EDITABLE"));
		dictRecord.dispText = com.wb.util.StringUtil.force(rs.getString("DISP_TEXT"));
		dictRecord.dispWidth = rs.getInt("DISP_WIDTH");
		if (rs.wasNull())
			dictRecord.dispWidth = -1;
		dictRecord.dispFormat = com.wb.util.StringUtil.force(rs.getString("DISP_FORMAT"));
		dictRecord.autoWrap = "1".equals(rs.getString("AUTO_WRAP"));
		dictRecord.allowBlank = com.wb.util.StringUtil.getBoolA(rs.getString("ALLOW_BLANK"));
		dictRecord.readOnly = com.wb.util.StringUtil.getBoolA(rs.getString("READ_ONLY"));
		dictRecord.keyName = com.wb.util.StringUtil.force(rs.getString("KEY_NAME"));
		dictRecord.fieldSize = rs.getInt("FIELD_SIZE");
		if (rs.wasNull())
			dictRecord.fieldSize = -1;
		dictRecord.decimalPrecision = rs.getInt("DECIMAL_PRECISION");
		if (rs.wasNull())
			dictRecord.decimalPrecision = -1;
		dictRecord.validator = com.wb.util.StringUtil.force(rs.getString("VALIDATOR"));
		dictRecord.renderer = com.wb.util.StringUtil.force(rs.getString("RENDERER"));
		return dictRecord;
	}

	/**
	 * 加载和初始化。
	 */
	public static synchronized void load() {
		try {
			buffer = new ConcurrentHashMap<String, ConcurrentHashMap<String, com.wb.tool.DictRecord>>();
			Connection conn = null;
			Statement st = null;
			ResultSet rs = null;
			String tableName = null, preTableName = null;
			ConcurrentHashMap<String, com.wb.tool.DictRecord> map = new ConcurrentHashMap<String, com.wb.tool.DictRecord>();
			try {
				conn = com.wb.util.DbUtil.getConnection();
				st = conn.createStatement();
				rs = st.executeQuery("select * from WB_DICT order by TABLE_NAME");
				while (rs.next()) {
					tableName = rs.getString("TABLE_NAME").toUpperCase();
					if (preTableName != null && !preTableName.equals(tableName)) {
						buffer.put(preTableName, map);
						map = new ConcurrentHashMap<String, com.wb.tool.DictRecord>();
					}
					map.put(rs.getString("FIELD_NAME").toUpperCase(), getDictRecord(rs));
					preTableName = tableName;
				}
				if (preTableName != null)
					buffer.put(preTableName, map);
			} finally {
				com.wb.util.DbUtil.close(rs);
				com.wb.util.DbUtil.close(st);
				com.wb.util.DbUtil.close(conn);
			}
		} catch (Throwable e) {
			throw new RuntimeException(e);
		}
	}
}