001 package biz.hammurapi.sql; 002 003 import java.io.Serializable; 004 import java.lang.reflect.Method; 005 import java.sql.PreparedStatement; 006 import java.sql.SQLException; 007 008 import biz.hammurapi.sql.columns.ObjectColumn; 009 010 /** 011 * Wrapper for different types. 012 * @author Pavel 013 */ 014 public class Variant implements Parameterizer, Serializable { 015 016 private static final int TYPE_BOOLEAN = 0; 017 private static final int TYPE_BYTE = 1; 018 private static final int TYPE_CHAR = 2; 019 private static final int TYPE_DOUBLE = 3; 020 private static final int TYPE_FLOAT = 4; 021 private static final int TYPE_INT = 5; 022 private static final int TYPE_LONG = 6; 023 private static final int TYPE_STRING = 7; 024 private static final int TYPE_OBJECT = 8; 025 private static final int TYPE_TYPED_OBJECT = 9; 026 private static final int TYPE_SHORT = 10; 027 028 private int type; 029 030 private boolean booleanValue; 031 private byte byteValue; 032 private char charValue; 033 private double doubleValue; 034 private float floatValue; 035 private int intValue; 036 private long longValue; 037 private String stringValue; 038 private Object objectValue; 039 private int sqlType; 040 private short shortValue; 041 042 public Variant(boolean value) { 043 type = TYPE_BOOLEAN; 044 this.booleanValue = value; 045 } 046 047 public Variant(byte value) { 048 type = TYPE_BYTE; 049 this.byteValue = value; 050 } 051 052 public Variant(char value) { 053 type = TYPE_CHAR; 054 this.charValue = value; 055 } 056 057 public Variant(double value) { 058 type = TYPE_DOUBLE; 059 this.doubleValue = value; 060 } 061 062 public Variant(float value) { 063 type = TYPE_FLOAT; 064 this.floatValue = value; 065 } 066 067 public Variant(int value) { 068 type = TYPE_INT; 069 this.intValue = value; 070 } 071 072 public Variant(long value) { 073 type = TYPE_LONG; 074 this.longValue = value; 075 } 076 077 public Variant(String value) { 078 type = TYPE_STRING; 079 this.stringValue = value; 080 } 081 082 public Variant(Object value) { 083 type = TYPE_OBJECT; 084 this.objectValue = value; 085 } 086 087 public Variant(Object value, int sqlType) { 088 type = TYPE_TYPED_OBJECT; 089 this.objectValue = value; 090 this.sqlType = sqlType; 091 } 092 093 public Variant(short value) { 094 type = TYPE_SHORT; 095 this.shortValue = value; 096 } 097 098 public int parameterize(PreparedStatement ps, int idx) throws SQLException { 099 switch (type) { 100 case TYPE_BOOLEAN: 101 ps.setBoolean(idx++, booleanValue); 102 break; 103 case TYPE_BYTE: 104 ps.setByte(idx++, byteValue); 105 break; 106 case TYPE_CHAR: 107 ps.setString(idx++, ""+charValue); 108 break; 109 case TYPE_DOUBLE: 110 ps.setDouble(idx++, doubleValue); 111 break; 112 case TYPE_FLOAT: 113 ps.setFloat(idx++, floatValue); 114 break; 115 case TYPE_INT: 116 ps.setInt(idx++, intValue); 117 break; 118 case TYPE_LONG: 119 ps.setLong(idx++, longValue); 120 break; 121 case TYPE_STRING: 122 ps.setString(idx++, stringValue); 123 break; 124 case TYPE_OBJECT: 125 Method setter = ObjectColumn.findSetter(objectValue.getClass()); 126 if ("setObject".equals(setter.getName())) { 127 ps.setObject(idx++, objectValue); 128 } else { 129 try { 130 setter.invoke(ps, new Object[] {new Integer(idx++), objectValue}); 131 } catch (Exception e) { 132 Throwable cause = e; 133 while (cause.getCause()!=null && cause.getCause()!=cause) { 134 cause = cause.getCause(); 135 } 136 if (cause instanceof SQLException) { 137 throw (SQLException) cause; 138 } else { 139 throw new SQLRuntimeException(e); 140 } 141 } 142 } 143 break; 144 case TYPE_TYPED_OBJECT: 145 ps.setObject(idx++, objectValue, sqlType); 146 break; 147 case TYPE_SHORT: 148 ps.setShort(idx++, shortValue); 149 break; 150 default: 151 throw new SQLException("Unrecognized value type: "+type); 152 } 153 return idx; 154 } 155 156 public int hashCode() { 157 final int prime = 31; 158 int result = 1; 159 result = prime * result + (booleanValue ? 1231 : 1237); 160 result = prime * result + charValue; 161 long temp; 162 temp = Double.doubleToLongBits(doubleValue); 163 result = prime * result + (int) (temp ^ (temp >>> 32)); 164 result = prime * result + Float.floatToIntBits(floatValue); 165 result = prime * result + intValue; 166 result = prime * result + (int) (longValue ^ (longValue >>> 32)); 167 result = prime * result 168 + ((objectValue == null) ? 0 : objectValue.hashCode()); 169 result = prime * result + shortValue; 170 result = prime * result + sqlType; 171 result = prime * result 172 + ((stringValue == null) ? 0 : stringValue.hashCode()); 173 result = prime * result + type; 174 return result; 175 } 176 177 public boolean equals(Object obj) { 178 if (this == obj) 179 return true; 180 if (obj == null) 181 return false; 182 if (getClass() != obj.getClass()) 183 return false; 184 final Variant other = (Variant) obj; 185 if (booleanValue != other.booleanValue) 186 return false; 187 if (byteValue != other.byteValue) 188 return false; 189 if (charValue != other.charValue) 190 return false; 191 if (Double.doubleToLongBits(doubleValue) != Double 192 .doubleToLongBits(other.doubleValue)) 193 return false; 194 if (Float.floatToIntBits(floatValue) != Float 195 .floatToIntBits(other.floatValue)) 196 return false; 197 if (intValue != other.intValue) 198 return false; 199 if (longValue != other.longValue) 200 return false; 201 if (objectValue == null) { 202 if (other.objectValue != null) 203 return false; 204 } else if (!objectValue.equals(other.objectValue)) 205 return false; 206 if (shortValue != other.shortValue) 207 return false; 208 if (sqlType != other.sqlType) 209 return false; 210 if (stringValue == null) { 211 if (other.stringValue != null) 212 return false; 213 } else if (!stringValue.equals(other.stringValue)) 214 return false; 215 if (type != other.type) 216 return false; 217 return true; 218 } 219 220 }