001/* 002 * www.openamf.org 003 * 004 * Distributable under LGPL license. 005 * See terms of license at gnu.org. 006 */ 007 008package flex.messaging.io; 009 010import java.io.IOException; 011import java.lang.reflect.InvocationTargetException; 012import java.lang.reflect.Method; 013import java.sql.ResultSet; 014import java.sql.ResultSetMetaData; 015import java.sql.SQLException; 016import java.util.ArrayList; 017import java.util.HashMap; 018import java.util.Iterator; 019import java.util.List; 020import java.util.Map; 021 022import org.granite.logging.Logger; 023import org.granite.util.Introspector; 024import org.granite.util.PropertyDescriptor; 025 026 027/** 028 * @author Jason Calabrese <jasonc@missionvi.com> 029 * @version $Revision: 1.29 $, $Date: 2006/03/25 22:17:44 $ 030 */ 031public class ASRecordSet extends ASObject { 032 033 private static final long serialVersionUID = 1L; 034 035 private static final Logger log = Logger.getLogger(ASRecordSet.class); 036 037 public static final String SERVICE_NAME = "OpenAMFPageableRecordSet"; 038 039 private static final String SI = "serverInfo"; 040 private static final String SI_ID = "id"; 041 private static final String SI_TOTAL_COUNT = "totalCount"; 042 private static final String SI_INITIAL_DATA = "initialData"; 043 //private static final String SI_ROWS = "rows"; 044 private static final String SI_CURSOR = "cursor"; 045 private static final String SI_SERVICE_NAME = "serviceName"; 046 private static final String SI_COLUMN_NAMES = "columnNames"; 047 private static final String SI_VERSION = "version"; 048 049 private static int count = 0; 050 051 private Map<String, Object> serverInfo; 052 private List<List<Object>> rows; 053 private int initialRowCount; 054 055 public ASRecordSet() { 056 super("RecordSet"); 057 serverInfo = new HashMap<String, Object>(); 058 put(SI, serverInfo); 059 060 synchronized (ASRecordSet.class) 061 { 062 count++; 063 setId("RS" + count); 064 } 065 066 setInitialData(new ArrayList<Object>()); 067 setServiceName(SERVICE_NAME); 068 setCursor(1); 069 setVersion(1); 070 rows = new ArrayList<List<Object>>(); 071 initialRowCount = 0; 072 } 073 074 public String getId() { 075 return (String) serverInfo.get(SI_ID); 076 } 077 public void setId(String id) { 078 serverInfo.put(SI_ID, id); 079 } 080 081 public int getTotalCount() { 082 Object value = serverInfo.get(SI_TOTAL_COUNT); 083 if (value != null) 084 return ((Integer) value).intValue(); 085 return 0; 086 } 087 public void setTotalCount(int totalCount) { 088 serverInfo.put(SI_TOTAL_COUNT, Integer.valueOf(totalCount)); 089 } 090 091 public List<?> getInitialData() { 092 return (List<?>)serverInfo.get(SI_INITIAL_DATA); 093 } 094 public void setInitialData(List<?> initialData) { 095 serverInfo.put(SI_INITIAL_DATA, initialData); 096 } 097 098 public Map<String, Object> getRecords(int from, int count) { 099 100 List<List<Object>> page = rows.subList(from - 1, from - 1 + count); 101 102 Map<String, Object> records = new HashMap<String, Object>(); 103 records.put("Page", page); 104 records.put("Cursor", Integer.valueOf(from + 1)); 105 106 return records; 107 108 } 109 110 public int getCursor() { 111 Object value = serverInfo.get(SI_CURSOR); 112 if (value != null) 113 return ((Integer) value).intValue(); 114 return 0; 115 } 116 public void setCursor(int cursor) { 117 serverInfo.put(SI_CURSOR, Integer.valueOf(cursor)); 118 } 119 120 public String getServiceName() { 121 return (String) serverInfo.get(SI_SERVICE_NAME); 122 } 123 public void setServiceName(String serviceName) { 124 serverInfo.put(SI_SERVICE_NAME, serviceName); 125 } 126 127 public String[] getColumnNames() { 128 return (String[]) serverInfo.get(SI_COLUMN_NAMES); 129 } 130 public void setColumnNames(String[] columnNames) { 131 serverInfo.put(SI_COLUMN_NAMES, columnNames); 132 } 133 134 public double getVersion() { 135 Object value = serverInfo.get(SI_VERSION); 136 if (value != null) 137 return ((Double) value).doubleValue(); 138 return 0; 139 } 140 public void setVersion(double version) { 141 serverInfo.put(SI_VERSION, new Double(version)); 142 } 143 144 public List<List<Object>> rows() { 145 return rows; 146 } 147 148 public void populate(ResultSet rs) throws IOException { 149 150 try { 151 ResultSetMetaData rsmd = rs.getMetaData(); 152 int columnCount = rsmd.getColumnCount(); 153 String[] columnNames = new String[columnCount]; 154 155 int rowIndex = 0; 156 List<List<Object>> initialData = new ArrayList<List<Object>>(); 157 while (rs.next()) { 158 rowIndex++; 159 List<Object> row = new ArrayList<Object>(); 160 for (int column = 0; column < columnCount; column++) { 161 if (rowIndex == 1) { 162 columnNames[column] = rsmd.getColumnName(column + 1); 163 } 164 row.add(rs.getObject(column + 1)); 165 } 166 if (rowIndex == 1) { 167 setColumnNames(columnNames); 168 } 169 rows.add(row); 170 if (rowIndex <= initialRowCount) { 171 initialData.add(row); 172 } 173 } 174 setTotalCount(rowIndex); 175 setInitialData(initialData); 176 setColumnNames(columnNames); 177 } catch (SQLException e) { 178 throw new IOException(e.getMessage()); 179 } 180 181 } 182 183 /** 184 * @param columnNames 185 * @param rows ArrayList containing a ArrayList for each row 186 */ 187 public void populate(String[] columnNames, List<List<Object>> rows) { 188 this.rows = rows; 189 190 List<List<Object>> initialData = 191 rows.subList( 192 0, 193 (initialRowCount > rows.size() 194 ? rows.size() 195 : initialRowCount)); // NOTE: sublist semantics are [fromIndex, toIndex] 196 setInitialData(initialData); 197 setTotalCount(rows.size()); 198 setColumnNames(columnNames); 199 } 200 201 /** 202 * @param list List of JavaBeans, all beans should be of the same type 203 * @param ignoreProperties properties that should not be added to the RecordSet 204 */ 205 public void populate(List<?> list, String[] ignoreProperties) 206 throws 207 IllegalArgumentException, 208 IllegalAccessException, 209 InvocationTargetException { 210 211 List<String> names = new ArrayList<String> (); 212 Object firstBean = list.get(0); 213 214 PropertyDescriptor[] properties = Introspector.getPropertyDescriptors(firstBean.getClass()); 215 if (properties == null) 216 properties = new PropertyDescriptor[0]; 217 218 for (int i = 0; i < properties.length; i++) { 219 PropertyDescriptor descriptor = properties[i]; 220 if (!ignoreProperty(descriptor, ignoreProperties)) 221 names.add(descriptor.getName()); 222 } 223 String[] columnNames = new String[names.size()]; 224 columnNames = names.toArray(columnNames); 225 setColumnNames(columnNames); 226 227 int rowIndex = 0; 228 List<List<Object>> initialData = new ArrayList<List<Object>>(); 229 Iterator<?> iterator = list.iterator(); 230 while (iterator.hasNext()) { 231 rowIndex++; 232 Object bean = iterator.next(); 233 List<Object> row = new ArrayList<Object>(); 234 for (int i = 0; i < properties.length; i++) { 235 PropertyDescriptor descriptor = properties[i]; 236 if (!ignoreProperty(descriptor, ignoreProperties)) { 237 Object value = null; 238 Method readMethod = descriptor.getReadMethod(); 239 if (readMethod != null) { 240 value = readMethod.invoke(bean, new Object[0]); 241 } 242 row.add(value); 243 } 244 } 245 rows.add(row); 246 if (rowIndex <= initialRowCount) { 247 initialData.add(row); 248 } 249 } 250 setInitialData(initialData); 251 setTotalCount(rows.size()); 252 log.debug("%s", this); 253 } 254 255 private boolean ignoreProperty( 256 PropertyDescriptor descriptor, 257 String[] ignoreProperties) { 258 259 boolean ignore = false; 260 if (descriptor.getName().equals("class")) { 261 ignore = true; 262 } else { 263 for (int i = 0; i < ignoreProperties.length; i++) { 264 String ignoreProp = ignoreProperties[i]; 265 if (ignoreProp.equals(descriptor.getName())) { 266 log.debug("Ignoring %s", descriptor.getName()); 267 ignore = true; 268 break; 269 } 270 } 271 } 272 return ignore; 273 } 274 275 @Override 276 public String toString() { 277 278 StringBuffer info = new StringBuffer(); 279 addInfo(info, SI_ID, getId()); 280 addInfo(info, SI_TOTAL_COUNT, getTotalCount()); 281 addInfo(info, SI_CURSOR, getCursor()); 282 addInfo(info, SI_SERVICE_NAME, getServiceName()); 283 addInfo(info, SI_VERSION, getVersion()); 284 StringBuffer names = new StringBuffer(); 285 String[] columnNames = getColumnNames(); 286 if (columnNames != null) { 287 for (int i = 0; i < columnNames.length; i++) { 288 String name = columnNames[i]; 289 if (i > 0) { 290 names.append(", "); 291 } 292 names.append(name); 293 } 294 } 295 addInfo(info, SI_COLUMN_NAMES, names); 296 addInfo(info, SI_INITIAL_DATA, getInitialData().toString()); 297 return info.toString(); 298 } 299 300 private void addInfo(StringBuffer info, String name, int value) { 301 addInfo(info, name, new Integer(value)); 302 } 303 304 private void addInfo(StringBuffer info, String name, double value) { 305 addInfo(info, name, new Double(value)); 306 } 307 308 private void addInfo(StringBuffer info, String name, Object value) { 309 info.append(name); 310 info.append(" = "); 311 info.append(value); 312 info.append('\n'); 313 } 314}