package to.etc.webapp.qsql;

import java.math.*;
import java.sql.*;
import java.util.*;

import to.etc.util.*;

/**
 * EXPERIMENTAL A record read from the database. Stores all (usable) attributes as a map of values.
 *
 * @author <a href="mailto:jal@etc.to">Frits Jalvingh</a>
 * Created on Apr 26, 2010
 */
public class JdbcAnyRecord {
	private Map<String, Object> m_valueMap = new HashMap<String, Object>();

	private String m_tableName;

	public void initFromRS(String tablename, ResultSetMetaData rsm, ResultSet rs) throws SQLException {
		m_valueMap.clear();
		m_tableName = tablename;
		for(int i = 1, len = rsm.getColumnCount(); i <= len; i++) {
			int type = rsm.getColumnType(i);
			String name = rsm.getColumnName(i);
			switch(type){
				default:
					throw new IllegalStateException("Cannot handle SQLType=" + type + " for column " + tablename + "." + name);
				case Types.NUMERIC:
				case Types.DECIMAL:
				case Types.FLOAT:
				case Types.DOUBLE:
					BigDecimal bd = rs.getBigDecimal(i);
					set(name, bd);
					break;
				case Types.VARCHAR:
				case Types.CHAR:
					set(name, rs.getString(i));
					break;
			}
		}
	}

	public void set(String name, Object bd) {
		if(bd == null)
			m_valueMap.remove(name);
		else
			m_valueMap.put(name.toLowerCase(), bd);
	}

	public Object get(String name) {
		return m_valueMap.get(name.toLowerCase());
	}

	public <T> T getValue(Class<T> type, String name) {
		Object v = get(name);
		if(v == null)
			return null;
		return (T) RuntimeConversions.convertTo(v, type);
	}


}

@@ -82,16 +82,44 @@
 til.*;%0A%0A
+import javax.annotation.*;%0A%0A
 import t
@@ -358,16 +358,71 @@
 ecord %7B%0A
+%09static private final Object NULL_VAL = new Object();%0A%0A
 %09private
@@ -581,16 +581,25 @@
 ata rsm,
+ @Nonnull
  ResultS
@@ -627,16 +627,92 @@
 ption %7B%0A
+%09%09if(rs == null)%0A%09%09%09throw new IllegalStateException(%22Null rs not allowed%22);%0A
 %09%09m_valu
@@ -1289,16 +1289,223 @@
 %09break;%0A
+%09%09%09%09case Types.DATE:%0A%09%09%09%09case Types.TIMESTAMP:%0A%09%09%09%09%09Timestamp ts = rs.getTimestamp(i);%0A%09%09%09%09%09if(ts == null)%0A%09%09%09%09%09%09set(name, NULL_VAL);%0A%09%09%09%09%09else%0A%09%09%09%09%09%09set(name, new java.util.Date(ts.getTime()));%0A%09%09%09%09%09break;%0A
 %09%09%09%7D%0A%09%09%7D
@@ -1587,19 +1587,26 @@
 Map.
-remove(name
+put(name, NULL_VAL
 );%0A%09
@@ -1832,29 +1832,115 @@
  == 
-null)%0A%09%09%09return null;
+NULL_VAL)%0A%09%09%09return null;%0A%09%09if(v == null)%0A%09%09%09return null; // FIXME Should throw column not found exception.
 %0A%09%09r

Add AnyRecord support for TIMESTAMP and DATE