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