001: /*
002: * @(#)ColumnMap.java 1.2 04/12/06
003: *
004: * Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package org.pnuts.jdbc;
010:
011: import java.sql.*;
012: import java.util.*;
013: import pnuts.lang.Property;
014: import pnuts.lang.Indexed;
015:
016: /*
017: * A poor man's O/R mapper
018: */
019: public class ColumnMap extends AbstractMap implements Indexed {
020:
021: protected ResultSet rs;
022: private String[] columnNames;
023: private HashSet columnNameSet;
024: private boolean clobToStringConversion = true;
025: private boolean updated;
026:
027: protected ColumnMap() {
028: }
029:
030: public ColumnMap(ResultSet rs) throws SQLException {
031: this .rs = rs;
032: initialize(rs.getMetaData());
033: }
034:
035: void initialize(ResultSetMetaData meta) throws SQLException {
036: int columnCount = meta.getColumnCount();
037: columnNameSet = new HashSet();
038: columnNames = new String[columnCount];
039: for (int i = 0; i < columnCount; i++) {
040: String name = meta.getColumnName(i + 1);
041: name = name.toLowerCase();
042: columnNames[i] = name;
043: columnNameSet.add(name);
044: }
045: }
046:
047: public void setClobToStringConvertion(boolean flag) {
048: this .clobToStringConversion = flag;
049: }
050:
051: public boolean getClobToStringConvertion() {
052: return this .clobToStringConversion;
053: }
054:
055: public boolean next() throws SQLException {
056: if (updated) {
057: rs.updateRow();
058: updated = false;
059: }
060: return rs.next();
061: }
062:
063: public void set(int idx, Object value) {
064: try {
065: rs.updateObject(idx + 1, value);
066: } catch (SQLException e) {
067: handleSQLException(e);
068: }
069: updated = true;
070: }
071:
072: public Object get(int idx) {
073: try {
074: return unwrap(rs.getObject(idx + 1));
075: } catch (SQLException e) {
076: handleSQLException(e);
077: return null;
078: }
079: }
080:
081: public int size() {
082: return columnNames.length;
083: }
084:
085: public boolean isEmpty() {
086: return size() == 0;
087: }
088:
089: public boolean containsKey(Object key) {
090: return columnNameSet.contains(key);
091: }
092:
093: public boolean containsValue(Object value) {
094: return false;
095: }
096:
097: public Object get(Object key) {
098: try {
099: return unwrap(rs.getObject(((String) key).toLowerCase()));
100: } catch (SQLException e) {
101: handleSQLException(e);
102: return null;
103: }
104: }
105:
106: public Object put(Object key, Object value) {
107: try {
108: rs.updateObject(((String) key).toLowerCase(), value);
109: } catch (SQLException e) {
110: handleSQLException(e);
111: }
112: updated = true;
113: return null;
114: }
115:
116: public Object remove(Object key) {
117: throw new UnsupportedOperationException();
118: }
119:
120: public void putAll(Map t) {
121: throw new UnsupportedOperationException();
122: }
123:
124: public void clear() {
125: throw new UnsupportedOperationException();
126: }
127:
128: public Set keySet() {
129: return columnNameSet;
130: }
131:
132: public Collection values() {
133: throw new UnsupportedOperationException();
134: }
135:
136: public Set entrySet() {
137: return new EntrySet();
138: }
139:
140: protected void handleSQLException(SQLException e) {
141: throw new RuntimeException(String.valueOf(e));
142: }
143:
144: private Object unwrap(Object x) throws SQLException {
145: if (clobToStringConversion) {
146: if (x instanceof Clob) {
147: Clob clob = (Clob) x;
148: long len = clob.length();
149: if (len < 0 || len > Integer.MAX_VALUE) {
150: throw new RuntimeException(
151: "Can't convert to String");
152: }
153: if (len == 0) {
154: return "";
155: } else {
156: return clob.getSubString(1L, (int) len);
157: }
158: }
159: }
160: return x;
161: }
162:
163: private class EntryIterator implements Iterator {
164: int pos = 0;
165:
166: public boolean hasNext() {
167: return columnNames.length > pos;
168: }
169:
170: public Object next() {
171: final int p = pos;
172: pos++;
173: return new Map.Entry() {
174: public Object getKey() {
175: return columnNames[p];
176: }
177:
178: public Object getValue() {
179: try {
180: return unwrap(rs.getObject(p + 1));
181: } catch (SQLException e) {
182: handleSQLException(e);
183: return null;
184: }
185: }
186:
187: public Object setValue(Object value) {
188: try {
189: rs.updateObject(p + 1, value);
190: updated = true;
191: return null;
192: } catch (SQLException e) {
193: handleSQLException(e);
194: return null;
195: }
196: }
197:
198: public String toString() {
199: return getKey() + "=" + getValue();
200: }
201: };
202: }
203:
204: public void remove() {
205: throw new UnsupportedOperationException();
206: }
207: }
208:
209: private class EntrySet extends AbstractSet {
210: public Iterator iterator() {
211: return new EntryIterator();
212: }
213:
214: public boolean contains(Object o) {
215: if (!(o instanceof Map.Entry)) {
216: return false;
217: }
218: Map.Entry e = (Map.Entry) o;
219: for (Iterator it = iterator(); it.hasNext();) {
220: if (it.next().equals(e)) {
221: return true;
222: }
223: }
224: return false;
225: }
226:
227: public boolean remove(Object o) {
228: throw new UnsupportedOperationException();
229: }
230:
231: public int size() {
232: return columnNames.length;
233: }
234:
235: public void clear() {
236: throw new UnsupportedOperationException();
237: }
238: }
239: }
|