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
029 package flex.messaging.io;
030
031 import java.io.IOException;
032 import java.lang.reflect.InvocationTargetException;
033 import java.lang.reflect.Method;
034 import java.sql.ResultSet;
035 import java.sql.ResultSetMetaData;
036 import java.sql.SQLException;
037 import java.util.ArrayList;
038 import java.util.HashMap;
039 import java.util.Iterator;
040 import java.util.List;
041 import java.util.Map;
042
043 import org.granite.logging.Logger;
044 import org.granite.util.Introspector;
045 import 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 */
052 public 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 }