001 /*
002 * www.openamf.org
003 *
004 * Distributable under LGPL license.
005 * See terms of license at gnu.org.
006 */
007
008 package flex.messaging.io;
009
010 import java.io.IOException;
011 import java.lang.reflect.InvocationTargetException;
012 import java.lang.reflect.Method;
013 import java.sql.ResultSet;
014 import java.sql.ResultSetMetaData;
015 import java.sql.SQLException;
016 import java.util.ArrayList;
017 import java.util.HashMap;
018 import java.util.Iterator;
019 import java.util.List;
020 import java.util.Map;
021
022 import org.granite.logging.Logger;
023 import org.granite.util.Introspector;
024 import 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 */
031 public 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 }