Annotation of java/classes/org/w3c/tools/jdbc/JdbcBeanSerializer.java, revision 1.17
1.1 bmahe 1: // JdbcBeanSerializer.java
1.17 ! ylafon 2: // $Id: JdbcBeanSerializer.java,v 1.16 2001/01/24 10:24:58 bmahe Exp $
1.1 bmahe 3: // (c) COPYRIGHT MIT, INRIA and Keio, 2000.
4: // Please first read the full copyright statement in file COPYRIGHT.html
5: package org.w3c.tools.jdbc;
6:
7: import java.beans.BeanInfo;
1.9 bmahe 8: import java.beans.Beans;
1.1 bmahe 9: import java.beans.IntrospectionException;
10: import java.beans.Introspector;
11: import java.beans.PropertyChangeListener;
12: import java.beans.PropertyChangeEvent;
13: import java.beans.PropertyDescriptor;
14:
1.9 bmahe 15: import java.io.IOException;
16:
1.1 bmahe 17: import java.lang.reflect.Method;
18: import java.lang.reflect.InvocationTargetException;
19:
20: import java.sql.ResultSet;
1.7 bmahe 21: import java.sql.ResultSetMetaData;
1.2 bmahe 22: import java.sql.SQLException;
1.1 bmahe 23:
1.5 bmahe 24: import java.util.Enumeration;
1.1 bmahe 25: import java.util.Hashtable;
1.2 bmahe 26: import java.util.Properties;
1.1 bmahe 27: import java.util.Vector;
28:
29: /**
1.13 bmahe 30: * Read <a href="http://www.w3.org/Jigsaw/Doc/Programmer/jspdb.html">http://www.w3.org/Jigsaw/Doc/Programmer/jspdb.html</a>
31: * to know how to use this class.
1.17 ! ylafon 32: * @version $Revision: 1.16 $
1.1 bmahe 33: * @author Beno�t Mah� (bmahe@w3.org)
34: */
35: public class JdbcBeanSerializer implements PropertyChangeListener {
1.12 ylafon 36:
1.1 bmahe 37: /**
1.5 bmahe 38: * Bean modified?
39: */
1.13 bmahe 40: private boolean modified = false;
1.5 bmahe 41:
42: /**
1.1 bmahe 43: * Our bean.
44: */
45: protected JdbcBeanInterface bean = null;
46:
47: /**
48: * The associated JdbcBean
49: */
1.13 bmahe 50: private JdbcBeanInterface beans[] = null;
1.1 bmahe 51:
52: /**
1.9 bmahe 53: * INTERSECT, UNION, EXCEPT.
54: */
55: protected final static int NOTHING = -1;
56: protected final static int INTERSECT = 10;
57: protected final static int UNION = 20;
58: protected final static int EXCEPT = 30;
59:
60: protected int priority[] = { NOTHING, NOTHING, NOTHING };
61:
62: protected JdbcBeanSerializer intersect_serializer = null;
63: protected JdbcBeanSerializer union_serializer = null;
64: protected JdbcBeanSerializer except_serializer = null;
65:
66: /**
1.1 bmahe 67: * The ResultSet
68: */
69: protected ResultSet result = null;
70:
71: /**
1.7 bmahe 72: * The tables/bean used to generate the SQL request (in the correct
73: * order)
74: */
1.13 bmahe 75: private Vector beantables = null;
1.7 bmahe 76:
77: /**
1.2 bmahe 78: * The Foreign keys <(class,class), String[]>
79: */
1.13 bmahe 80: private static Hashtable foreignKeys = new Hashtable();
1.2 bmahe 81:
1.13 bmahe 82: private void registerForeignKeys(Class beanclass1,
83: Class beanclass2)
1.2 bmahe 84: {
85: Integer key = new Integer(beanclass1.hashCode() &
86: beanclass2.hashCode());
1.5 bmahe 87: if (! foreignKeys.containsKey(key)) {
1.2 bmahe 88: foreignKeys.put(key, computeForeignKeys(beanclass1, beanclass2));
89: }
90: }
91:
1.13 bmahe 92: private String[] getForeignKeys(Class beanclass1,
93: Class beanclass2)
1.2 bmahe 94: {
95: Integer key = new Integer(beanclass1.hashCode() &
96: beanclass2.hashCode());
97: String keys[] = (String[]) foreignKeys.get(key);
98: if (keys == null) {
99: keys = computeForeignKeys(beanclass1, beanclass2);
100: foreignKeys.put(key, keys);
101: }
102: return keys;
103: }
104:
1.13 bmahe 105: private String[] computeForeignKeys(Class beanclass1,
106: Class beanclass2)
1.2 bmahe 107: {
108: try {
109: BeanInfo bi1 = Introspector.getBeanInfo(beanclass1);
110: PropertyDescriptor pds1[] = bi1.getPropertyDescriptors();
111:
112: BeanInfo bi2 = Introspector.getBeanInfo(beanclass2);
113: PropertyDescriptor pds2[] = bi2.getPropertyDescriptors();
114:
115: Vector foreign = new Vector();
116:
117: for(int cpt1 = 0 ; cpt1 < pds1.length ; cpt1++) {
118: PropertyDescriptor pd1 = pds1[cpt1];
119: for (int cpt2 = 0 ; cpt2 < pds2.length ; cpt2++) {
120: PropertyDescriptor pd2 = pds2[cpt2];
121: if ((! pd2.isHidden())
122: && (! pd1.isHidden())
1.7 bmahe 123: && (equalsForeignKeys(pd1.getName(),pd2.getName()))) {
1.2 bmahe 124: foreign.addElement(pd1.getName());
125: }
126: }
127: }
128: String keys[] = new String[foreign.size()];
129: foreign.copyInto(keys);
130: return keys;
131: } catch (IntrospectionException ex) {
132: return new String[0];
133: }
134: }
135:
136: /**
1.7 bmahe 137: * toto_username == username
138: */
1.13 bmahe 139: private static boolean equalsForeignKeys(String key1, String key2) {
1.7 bmahe 140: int idx1 = key1.lastIndexOf("_");
141: if (idx1 != -1) {
142: key1 = key1.substring(idx1);
143: }
144: int idx2 = key2.lastIndexOf("_");
145: if (idx2 != -1) {
146: key2 = key2.substring(idx2);
147: }
148: return key1.equals(key2);
149: }
150:
1.5 bmahe 151: protected void markModified(boolean modified) {
152: this.modified = modified;
153: }
154:
155: protected boolean isModified() {
156: return modified;
157: }
158:
1.1 bmahe 159: /**
160: * PropertyChangeListener implementation: This method gets called when
161: * a bound property is changed.
162: * @param evt A PropertyChangeEvent object describing the event source
163: * and the property that has changed.
164: */
165: public void propertyChange(PropertyChangeEvent evt) {
166: Object source = evt.getSource();
1.5 bmahe 167: String name = evt.getPropertyName();
168: Object value = evt.getNewValue();
1.2 bmahe 169: if (source == bean) {
1.7 bmahe 170: if (value == null) {
171: PropertyDescriptor pd = getPropertyDescriptor(name);
172: if (JdbcBeanUtil.isJdbcBean(pd.getPropertyType())) {
173: // delete cached bean descriptors
174: this.beans = null;
175: // update listeners
176: JdbcBeanInterface oldbean =
177: (JdbcBeanInterface)evt.getOldValue();
178: if (oldbean != null) {
1.9 bmahe 179: PropertyCache.removeProperties(oldbean);
1.7 bmahe 180: oldbean.removePropertyChangeListener(this);
181: }
182: }
183: } else if (value instanceof JdbcBeanInterface) {
1.5 bmahe 184: registerForeignKeys(bean.getClass(), value.getClass());
1.4 bmahe 185: // delete cached bean descriptors
186: this.beans = null;
1.5 bmahe 187: // update listeners
188: JdbcBeanInterface oldbean =
189: (JdbcBeanInterface)evt.getOldValue();
190: JdbcBeanInterface newbean = (JdbcBeanInterface)value;
191: if (oldbean != null) {
1.9 bmahe 192: PropertyCache.removeProperties(oldbean);
1.5 bmahe 193: oldbean.removePropertyChangeListener(this);
194: }
195: newbean.addPropertyChangeListener(this);
196: } else {
1.2 bmahe 197: JdbcBeanInterface bean = (JdbcBeanInterface)source;
1.9 bmahe 198: PropertyCache.addProperty(bean, name, evt.getNewValue());
1.5 bmahe 199: markModified(true);
200: }
201: } else {
202: markModified(true);
1.1 bmahe 203: }
204: }
205:
1.2 bmahe 206: /**
207: * Get the raw value of the given property, split the operator and
208: * the value and convert the raw value into a SQL value.<p>
209: * ie "~A.*" will become { " ~ " , "'A.*'" }
210: * @param bean the property holder
211: * @param pd the property descriptor
212: */
1.13 bmahe 213: private String[] getSQLOperatorNValue(JdbcBeanInterface bean,
214: PropertyDescriptor pd)
1.1 bmahe 215: {
216: Class type = pd.getPropertyType();
217: Method m = pd.getReadMethod();
218: if (m != null) { // are we authozired to read it?
1.9 bmahe 219: // use the cache
220: Object value = PropertyCache.getProperty(bean, pd);
1.1 bmahe 221: if (value == null) {
222: return null;
223: }
1.10 bmahe 224: return SQL.getSQLOperator(value);
1.1 bmahe 225: }
226: return null;
227: }
228:
229: /**
1.5 bmahe 230: * Get the SQL value of the given property.
231: * @param bean the property holder
232: * @param pd the property descriptor
233: */
1.13 bmahe 234: private String getSQLValue(JdbcBeanInterface bean,
235: PropertyDescriptor pd)
1.5 bmahe 236: {
237: Class type = pd.getPropertyType();
238: Method m = pd.getReadMethod();
239: if (m != null) { // are we authozired to read it?
1.9 bmahe 240: // use the cache
241: Object value = PropertyCache.getProperty(bean, pd);
1.5 bmahe 242: if (value == null) {
243: return null;
244: }
1.10 bmahe 245: return SQL.getSQLValue(value);
1.5 bmahe 246: }
247: return null;
248: }
249:
250: /**
1.1 bmahe 251: * @param name
252: * @param value
253: * @param buf
254: */
1.5 bmahe 255: private void append(String name,
256: String operator,
257: String value,
258: String separator,
259: StringBuffer buf)
260: {
261: if (buf.length() > 0) {
262: buf.append(separator).append(" ");
263: }
264: buf.append(name).append(operator).append(value).append(" ");
265: }
266:
267: /**
268: * @param name
269: * @param value
270: * @param namesbuffer
271: * @param valuesbuffer
272: */
273: private void appendInsert(String name,
1.2 bmahe 274: String value,
1.5 bmahe 275: StringBuffer namesbuffer,
276: StringBuffer valuesbuffer)
1.1 bmahe 277: {
1.5 bmahe 278: if (namesbuffer.length() > 0) {
279: namesbuffer.append(", ").append(name);
280: valuesbuffer.append(", ").append(value);
281: } else {
282: namesbuffer.append("(").append(name);
283: valuesbuffer.append("(").append(value);
1.1 bmahe 284: }
285: }
286:
1.13 bmahe 287: private JdbcBeanInterface[] getJdbcBeans() {
1.1 bmahe 288: if (beans != null) {
289: return beans;
290: }
291: try {
292: BeanInfo info = Introspector.getBeanInfo(bean.getClass());
293: Vector vb = new Vector();
294: PropertyDescriptor pds[] = info.getPropertyDescriptors();
295: for (int i = 0 ; i < pds.length ; i++) {
296: PropertyDescriptor pd = pds[i];
1.5 bmahe 297: if ((! pd.isHidden()) &&
298: (JdbcBeanUtil.isJdbcBean(pd.getPropertyType()))) {
1.1 bmahe 299: Method m = pd.getReadMethod();
300: if (m != null) {
1.17 ! ylafon 301: Object value = m.invoke(bean, (Object [])null);
1.1 bmahe 302: if (value != null) {
303: vb.addElement(value);
304: }
305: }
306: }
307: }
308: beans = new JdbcBeanInterface[vb.size()];
309: vb.copyInto(beans);
310: return beans;
311: } catch (IntrospectionException ex) {
312: return null;
313: } catch (IllegalAccessException ex) {
314: return null;
315: } catch (InvocationTargetException ex) {
316: return null;
317: }
318: }
319:
1.13 bmahe 320: private void appendForeignKeys(Vector tables,
321: StringBuffer buffer,
322: String properties[])
1.8 bmahe 323: throws IntrospectionException
1.7 bmahe 324: {
325: BeanInfo info = Introspector.getBeanInfo(bean.getClass());
326: PropertyDescriptor pds[] = info.getPropertyDescriptors();
1.9 bmahe 327: appendForeignKeys(tables, buffer, pds, properties);
1.7 bmahe 328: }
329:
1.13 bmahe 330: private void appendForeignKeys(Vector tables,
331: StringBuffer buffer,
332: PropertyDescriptor pds[],
333: String properties[])
1.8 bmahe 334: throws IntrospectionException
1.1 bmahe 335: {
336: JdbcBeanInterface jbeans[] = getJdbcBeans();
1.9 bmahe 337: if (jbeans != null) { // FOREIGN KEYs
1.1 bmahe 338: for (int i = 0 ; i < jbeans.length ; i++) {
339: JdbcBeanInterface jbean = jbeans[i];
1.2 bmahe 340: // foreign keys
341: String keys[] = getForeignKeys(jbean.getClass(),
342: bean.getClass());
343: for (int f = 0 ; f < keys.length ; f++) {
344: String key = keys[f];
1.9 bmahe 345: if ((properties == null) ||
346: (JdbcBeanUtil.isIn(key, properties))) {
347: append(jbean.getJdbcTable()+"."+key,
348: " = ",
349: bean.getJdbcTable()+"."+key,
350: "AND",
351: buffer);
352: }
1.2 bmahe 353: }
1.8 bmahe 354: BeanInfo bi = null;
355: PropertyDescriptor jpds[] = null;
1.2 bmahe 356: // value now
1.8 bmahe 357: bi = Introspector.getBeanInfo(jbean.getClass());
358: jpds = bi.getPropertyDescriptors();
1.1 bmahe 359: for (int jpd_cpt = 0 ; jpd_cpt < jpds.length ; jpd_cpt++) {
360: PropertyDescriptor jpd = jpds[jpd_cpt];
361: if (jpd.isHidden()) {
362: continue;
363: }
364: String jname = jpd.getName();
1.9 bmahe 365: if ((properties == null) ||
366: (JdbcBeanUtil.isIn(jname, properties))) {
367: String split[] = getSQLOperatorNValue(jbean, jpd);
368: if (split != null) {
369: append(jbean.getJdbcTable()+"."+jname,
370: split[0],
371: split[1],
372: "AND",
373: buffer);
374: }
1.1 bmahe 375: }
1.2 bmahe 376: }
1.7 bmahe 377: tables.addElement(jbean);
378: // test FIXME recursive stuff
1.9 bmahe 379: jbean.getSerializer().appendForeignKeys(tables,
380: buffer,
381: properties);
1.1 bmahe 382: }
383: }
384: }
385:
1.9 bmahe 386: protected String computeSQLCount(boolean all,
387: boolean distinct,
388: String properties[])
389: {
1.11 bmahe 390: String count = (distinct) ? "DISTINCT count(*)" : "count(*)";
1.13 bmahe 391: return computeSQLSelect(all, count, properties);
1.7 bmahe 392: }
393:
1.13 bmahe 394: private String computeSQLSelect(String orderby[],
395: boolean asc[],
396: boolean all)
1.7 bmahe 397: {
1.9 bmahe 398: return computeSQLSelect(orderby, asc, all, "*", null);
1.7 bmahe 399: }
400:
1.13 bmahe 401: private String computeSQLSelect(String orderby[],
402: boolean asc[],
403: boolean all,
404: String select)
1.7 bmahe 405: {
1.9 bmahe 406: return computeSQLSelect(orderby, asc, all, select, null);
407: }
408:
409: protected String computeSQLSelect(String orderby[],
410: boolean asc[],
411: boolean all,
412: String select,
413: String properties[])
414: {
1.13 bmahe 415: String sql = computeSQLSelect(all, select, properties);
1.11 bmahe 416: StringBuffer buffer = new StringBuffer(sql);
417: if (orderby != null) {
418: buffer.append(" ORDER BY ");
419: for (int j = 0 ; j < orderby.length ; j++) {
420: if (j != 0) {
421: buffer.append(", ");
422: }
423: buffer.append(orderby[j]);
424: if (! asc[j]) {
425: buffer.append(" DESC");
426: }
427: }
428: }
429: return buffer.toString();
430:
431: }
432:
1.13 bmahe 433: private String computeSQLSelect(boolean all,
434: String select,
435: String properties[])
1.11 bmahe 436: {
1.1 bmahe 437: try {
438: BeanInfo info = Introspector.getBeanInfo(bean.getClass());
439: StringBuffer buffer = new StringBuffer();
440: String table = bean.getJdbcTable();
1.7 bmahe 441: this.beantables = new Vector();
442: beantables.addElement(bean);
443:
1.1 bmahe 444: PropertyDescriptor pds[] = info.getPropertyDescriptors();
1.5 bmahe 445: if (all) {
446: // FOREIGN KEYs
1.9 bmahe 447: appendForeignKeys(beantables, buffer, pds, properties);
1.5 bmahe 448: }
1.1 bmahe 449: // known values
450: for (int i = 0 ; i < pds.length ; i++) {
451: PropertyDescriptor pd = pds[i];
452: if (! pd.isHidden()) {
1.9 bmahe 453: String jname = pd.getName();
454: if ((properties == null) ||
455: (JdbcBeanUtil.isIn(jname, properties))) {
456: String split[] = getSQLOperatorNValue(bean, pd);
457: if (split != null) {
458: append(table+"."+jname,
459: split[0],
460: split[1],
461: "AND",
462: buffer);
463: }
1.1 bmahe 464: }
465: }
466: }
467: // build SQL request
468: if (buffer.length() > 0) {
1.7 bmahe 469: StringBuffer tables = new StringBuffer();
470: for (int i = 0 ; i < beantables.size() ; i++) {
471: JdbcBeanInterface jbean =
472: (JdbcBeanInterface)beantables.elementAt(i);
473: if (i != 0) {
474: tables.append(", ");
475: }
476: tables.append(jbean.getJdbcTable());
477: }
1.1 bmahe 478: tables.append(" WHERE ");
1.7 bmahe 479: tables.insert(0, "SELECT "+select+" FROM ");
1.1 bmahe 480: tables.append(buffer.toString());
1.2 bmahe 481: buffer = tables;
1.1 bmahe 482: } else {
1.8 bmahe 483: buffer = new StringBuffer("SELECT "+select+" FROM ");
1.2 bmahe 484: buffer.append(table);
485: }
1.9 bmahe 486: // union? intersect? except?
487: for (int i = 0 ; i < priority.length ; i++) {
488: int p = priority[i];
489: if (p == NOTHING) {
490: break;
491: }
492: switch (p)
493: {
494: case INTERSECT:
1.14 bmahe 495: if (intersect_serializer != null) {
496: String intersect =
497: intersect_serializer.computeSQLSelect(all,
498: select,
1.13 bmahe 499: properties);
1.14 bmahe 500: buffer.append(" INTERSECT (").append(intersect);
501: buffer.append(")");
502: }
1.9 bmahe 503: break;
504: case UNION:
1.14 bmahe 505: if (union_serializer != null) {
506: String union =
507: union_serializer.computeSQLSelect(all,
508: select,
509: properties);
510: buffer.append(" UNION (").append(union);
511: buffer.append(")");
512: }
1.9 bmahe 513: break;
514: case EXCEPT:
1.14 bmahe 515: if (except_serializer != null) {
516: String except =
517: except_serializer.computeSQLSelect(all,
518: select,
519: properties);
520: buffer.append(" EXCEPT (").append(except);
521: buffer.append(")");
522: }
1.9 bmahe 523: break;
524: default:
525: // unreached (I hope)
1.7 bmahe 526: }
1.1 bmahe 527: }
1.2 bmahe 528: return buffer.toString();
1.1 bmahe 529: } catch (IntrospectionException ex) {
530: return null;
531: }
532: }
533:
1.5 bmahe 534: /**
535: * Compute the SQL request necessary to update the Database.
536: * @return a String
537: */
538: protected String computeSQLInsert() {
539: try {
540: BeanInfo info = Introspector.getBeanInfo(bean.getClass());
541: PropertyDescriptor pds[] = info.getPropertyDescriptors();
542: StringBuffer namesbuffer = new StringBuffer();
543: StringBuffer valuesbuffer = new StringBuffer();
544: for (int i = 0 ; i < pds.length ; i++) {
545: PropertyDescriptor pd = pds[i];
546: if (! pd.isHidden()) {
547: String value = getSQLValue(bean, pd);
548: if (value != null) {
549: appendInsert(pd.getName(),
550: value,
551: namesbuffer,
552: valuesbuffer);
553: }
554: }
555: }
556: if (namesbuffer.length() > 0) {
557: StringBuffer request = new StringBuffer("INSERT INTO ");
558: request.append(bean.getJdbcTable()).append(" ");
559: request.append(namesbuffer).append(") ");
560: request.append("VALUES ").append(valuesbuffer).append(")");
561: return request.toString();
562: } else {
563: return null;
564: }
565: } catch (IntrospectionException ex) {
566: return null;
567: }
568: }
569:
570: protected String computeSQLDelete() {
571: try {
572: BeanInfo info = Introspector.getBeanInfo(bean.getClass());
573: StringBuffer buffer = new StringBuffer();
574: StringBuffer table = new StringBuffer(bean.getJdbcTable());
575: PropertyDescriptor pds[] = info.getPropertyDescriptors();
576: // known values
577: for (int i = 0 ; i < pds.length ; i++) {
578: PropertyDescriptor pd = pds[i];
579: if (! pd.isHidden()) {
580: String split[] = getSQLOperatorNValue(bean, pd);
581: if (split != null) {
582: append(pd.getName(), split[0], split[1],"AND", buffer);
583: }
584: }
585: }
586: // build SQL request
587: if (buffer.length() > 0) {
588: table.append(" WHERE ");
589: table.insert(0, "DELETE FROM ");
590: table.append(buffer.toString());
591: buffer = table;
592: } else {
593: return null;
594: }
595: return buffer.toString();
596: } catch (IntrospectionException ex) {
597: return null;
598: }
599: }
600:
601: protected String computeSQLUpdate(String primarykeys[]) {
602: try {
603: BeanInfo info = Introspector.getBeanInfo(bean.getClass());
604: StringBuffer buffer = new StringBuffer();
605: StringBuffer pkbuffer = new StringBuffer();
606: StringBuffer table = new StringBuffer(bean.getJdbcTable());
607: PropertyDescriptor pds[] = info.getPropertyDescriptors();
608: // known values
609: for (int i = 0 ; i < pds.length ; i++) {
610: PropertyDescriptor pd = pds[i];
611: if (! pd.isHidden()) {
612: String name = pd.getName();
613: String split[] = getSQLOperatorNValue(bean, pd);
614: if (split != null) {
615: if (JdbcBeanUtil.isIn(name, primarykeys)) {
616: append(name, split[0], split[1], "AND", pkbuffer);
617: } else {
618: append(name, split[0], split[1], ",", buffer);
619: }
620: }
621: }
622: }
623: // build SQL request
624: if (buffer.length() > 0) {
625: table.append(" SET ");
626: table.insert(0, "UPDATE ");
627: table.append(buffer.toString());
628: table.append(" WHERE ");
629: table.append(pkbuffer.toString());
630: buffer = table;
631: } else {
632: return null;
633: }
634: return buffer.toString();
635: } catch (IntrospectionException ex) {
636: return null;
637: }
638: }
639:
1.2 bmahe 640: protected JdbcServer getJdbcServer() {
641: Properties props = new Properties();
642: Jdbc.setMaxConn(props, bean.getMaxConn());
643: return JdbcServer.getServer(bean.getJdbcURI(),
644: bean.getJdbcUser(),
645: bean.getJdbcPassword(),
646: bean.getJdbcDriver(),
647: props);
648: }
649:
1.13 bmahe 650: private void executeSQLQuery(String sqlrequest)
1.5 bmahe 651: throws SQLException
652: {
653: result = getJdbcServer().runQuery(sqlrequest, false);
654: }
655:
1.13 bmahe 656: private int executeSQLUpdate(String sqlrequest)
1.2 bmahe 657: throws SQLException
658: {
1.5 bmahe 659: return getJdbcServer().runUpdate(sqlrequest, false);
1.2 bmahe 660: }
1.12 ylafon 661:
1.9 bmahe 662: /**
663: * Count the number or row with columns matching the value of the
664: * bean properties.
665: * @return an int
666: */
1.7 bmahe 667: public int count() {
1.9 bmahe 668: return count(true, false, null);
669: }
670:
671: /**
672: * Count the number or row with columns matching the value of the
673: * given properties.
674: * @param properties The property names
675: * @return an int
676: */
677: public int count(String properties[]) {
678: return count(true, false, properties);
1.7 bmahe 679: }
680:
1.9 bmahe 681: /**
682: * Count the number or row with columns matching the value of the
683: * bean properties.
684: * @param all (join with associated beans?)
685: * @return an int
686: */
1.7 bmahe 687: public int count(boolean all) {
1.9 bmahe 688: return count(all, false, null);
1.8 bmahe 689: }
690:
1.9 bmahe 691: /**
692: * Count the number or row with columns matching the value of the
693: * bean properties
694: * @param all (join with associated beans?)
695: * @param distinct (SELECT DISTINCT?)
696: * @return an int
697: */
1.8 bmahe 698: public int count(boolean all, boolean distinct) {
1.9 bmahe 699: return count(all, distinct, null);
700: }
701:
702: /**
703: * Count the number or row with columns matching the value of the
704: * given properties.
705: * @param all (join with associated beans?)
706: * @param distinct (SELECT DISTINCT?)
707: * @param properties The property names
708: * @return an int
709: */
710: public int count(boolean all, boolean distinct, String properties[]) {
711: String sql = computeSQLCount(all, distinct, properties);
1.7 bmahe 712: try {
713: executeSQLQuery(sql);
714: if (result.first()) {
715: return result.getInt(1);
716: } else {
717: return 0;
718: }
719: } catch (SQLException ex) {
720: System.out.println("SQL STATE: "+ex.getSQLState());
721: ex.printStackTrace();
722: return 0;
723: } finally {
724: result = null;
725: beantables = null;
726: }
1.9 bmahe 727:
1.7 bmahe 728: }
1.9 bmahe 729:
1.8 bmahe 730: /**
731: * Perform a sql select to update the beans properties.
732: */
1.2 bmahe 733: public void select() {
1.7 bmahe 734: boolean array[] = { true };
1.8 bmahe 735: select((String[])null, array, true, false);
1.5 bmahe 736: }
737:
1.8 bmahe 738: /**
739: * Perform a sql select to update the beans properties.
740: * @param all join with attached beans? (default is true)
741: */
1.5 bmahe 742: public void select(boolean all) {
1.7 bmahe 743: boolean array[] = { true };
1.8 bmahe 744: select((String[])null, array, all, false);
1.2 bmahe 745: }
746:
1.8 bmahe 747: /**
748: * Perform a sql select to update the beans properties.
749: * @param orderby orderby rule
750: */
1.2 bmahe 751: public void select(String orderby) {
752: String array[] = { orderby };
1.7 bmahe 753: boolean arrayb[] = { true };
1.8 bmahe 754: select(array, arrayb, true, false);
1.5 bmahe 755: }
756:
1.8 bmahe 757: /**
758: * Perform a sql select to update the beans properties.
759: * @param orderby orderby rule
760: * @param asc boolean if true orderby is ASC if false it it
761: * DESC (relative to the orderby[] parameter)
762: * @param all join with attached beans? (default is true)
763: */
764: public void select(String orderby,
765: boolean asc,
766: boolean all)
767: {
1.5 bmahe 768: String array[] = { orderby };
1.7 bmahe 769: boolean arrayb[] = { asc };
1.8 bmahe 770: select(array, arrayb, all, false);
1.2 bmahe 771: }
772:
1.8 bmahe 773: /**
774: * Perform a sql select to update the beans properties.
775: * @param orderby orderby rule
776: * @param asc boolean if true orderby is ASC if false it it
777: * DESC (relative to the orderby[] parameter)
778: * @param all join with attached beans? (default is true)
779: * @param distinct if true, result won't have duplicate row (default is
780: * false)
781: */
782: public void select(String orderby,
783: boolean asc,
784: boolean all,
785: boolean distinct)
786: {
787: String array[] = { orderby };
788: boolean arrayb[] = { asc };
789: select(array, arrayb, all, distinct);
790: }
791:
792: /**
793: * Perform a sql select to update the beans properties.
794: * @param orderby array of orderby rules (ASC by default)
795: */
1.2 bmahe 796: public void select(String orderby[]) {
1.7 bmahe 797: boolean array[] = { true };
1.8 bmahe 798: select(orderby, array, true, false);
799: }
800:
801: /**
802: * Perform a sql select to update the beans properties.
803: * @param orderby array of orderby rules
804: * @param asc array of boolean if true orderby is ASC if false it it
805: * DESC (relative to the orderby[] parameter)
806: * @param all join with attached beans? (default is true)
807: * @param distinct if true, result won't have duplicate row (default is
808: * false)
809: */
810: public void select(String orderby[],
811: boolean asc[],
812: boolean all,
813: boolean distinct)
814: {
815: String select = (distinct) ? "DISTINCT *" : "*";
816: String sql = computeSQLSelect(orderby, asc, all, select);
817: try {
818: executeSQLQuery(sql);
819: } catch (SQLException ex) {
820: System.out.println("SQL STATE: "+ex.getSQLState());
821: ex.printStackTrace();
822: result = null;
823: }
1.5 bmahe 824: }
825:
1.8 bmahe 826: /**
1.9 bmahe 827: * Perform a sql select to update the beans properties.
828: * @param orderby array of orderby rules
829: * @param asc array of boolean if true orderby is ASC if false it it
830: * DESC (relative to the orderby[] parameter)
831: * @param all join with attached beans? (default is true)
832: * @param distinct if true, result won't have duplicate row (default is
833: * @param toselect array of columns name to select
834: * false)
835: */
836: public void select(String orderby[],
837: boolean asc[],
838: boolean all,
839: boolean distinct,
840: String toselect[])
841: {
842: String query = null;
843: if (toselect != null) {
844: StringBuffer buffer = new StringBuffer();
845: for (int i = 0 ; i < toselect.length ; i++) {
846: if (i != 0) {
847: buffer.append(", ");
848: }
849: buffer.append(toselect[i]).append(" ");
850: }
851: query = buffer.toString();
852: } else {
853: query = "*";
854: }
855: String select = (distinct) ? "DISTINCT "+query : query;
856: String sql = computeSQLSelect(orderby, asc, all, select);
857: try {
858: executeSQLQuery(sql);
859: } catch (SQLException ex) {
860: System.out.println("SQL STATE: "+ex.getSQLState());
861: ex.printStackTrace();
862: result = null;
863: }
864: }
865:
866: /**
1.8 bmahe 867: * Perform a sql select to update only the given columns. (distinct flag is
868: * set as true.
869: * @param column the bean property to update
870: */
871: public void selectDistinct(String column) {
872: boolean array[] = { true };
873: String order[] = { column };
874: String sql = computeSQLSelect(order, array, false, "DISTINCT "+column);
1.5 bmahe 875: try {
876: executeSQLQuery(sql);
1.8 bmahe 877: } catch (SQLException ex) {
878: System.out.println("SQL STATE: "+ex.getSQLState());
879: ex.printStackTrace();
880: result = null;
881: }
882: }
883:
1.14 bmahe 884: private void setPriority(int p) {
1.9 bmahe 885: int idx = 0;
886: while ((idx < priority.length) && (priority[idx] != NOTHING)) {
887: if (priority[idx] == p) { // already set
888: return;
889: }
890: idx++;
891: }
892: priority[idx] = p;
1.8 bmahe 893: }
894:
1.13 bmahe 895: /**
896: * USE THIS METHOD ONLY BEFORE SELECT QUERIES.
897: * This will produce a select query with an INTERSECT statement in it
898: * using the values of the given bean.
899: * @param ibean the intersect bean
900: */
1.9 bmahe 901: public JdbcBeanSerializer intersect(JdbcBeanInterface ibean) {
902: setPriority(INTERSECT);
903: intersect_serializer = ibean.getSerializer();
904: return intersect_serializer;
1.8 bmahe 905: }
906:
1.13 bmahe 907: /**
908: * USE THIS METHOD ONLY BEFORE QUERIES.
909: * This will produce a select query with an UNION statement in it
910: * using the values of the given bean.
911: * @param ibean the intersect bean
912: */
1.9 bmahe 913: public JdbcBeanSerializer union(JdbcBeanInterface ubean) {
914: setPriority(UNION);
915: union_serializer = ubean.getSerializer();
916: return union_serializer;
1.8 bmahe 917: }
918:
1.13 bmahe 919: /**
920: * USE THIS METHOD ONLY BEFORE SELECT QUERIES.
921: * This will produce a select query with an EXCEPT statement in it
922: * using the values of the given bean.
923: * @param ibean the intersect bean
924: */
1.9 bmahe 925: public JdbcBeanSerializer except(JdbcBeanInterface ebean) {
926: setPriority(EXCEPT);
927: except_serializer = ebean.getSerializer();
928: return except_serializer;
1.14 bmahe 929: }
930:
931: /**
932: * Remove the intersect bean
933: */
934: public void removeIntersectBean() {
935: intersect_serializer = null;
936:
937: }
938:
939: /**
940: * Remove the union bean
941: */
942: public void removeUnionBean() {
943: union_serializer = null;
944:
945: }
946:
947: /**
948: * Remove the except bean
949: */
950: public void removeExceptBean() {
951: except_serializer = null;
1.5 bmahe 952: }
953:
1.13 bmahe 954: /**
955: * Insert the current bean values in the associated table.
956: * @return false if the INSERT request failed.
957: */
1.5 bmahe 958: public boolean insert() {
959: if (! isModified()) { // nothing new to insert
960: return false;
961: }
962: JdbcBeanInterface beans[] = getJdbcBeans();
963: for (int i = 0 ; i < beans.length ; i++) {
964: JdbcBeanInterface jbean = beans[i];
965: JdbcBeanSerializer ser = jbean.getSerializer();
966: if (ser.isModified()) {
967: // insert associated bean
968: ser.insert();
969: // update our foreign key
970: updateForeignKeys(jbean);
971: }
972: }
973: if (! bean.getReadOnly()) {
974: // ok insert ourself now
975: String request = computeSQLInsert();
976: try {
977: // insert (could fail without being critical)
978: // ie: when the row is already in the table
979: executeSQLUpdate(request);
980: } catch (SQLException ex) {
981: System.err.println(ex.getMessage());
1.16 bmahe 982: return false;
1.5 bmahe 983: }
984: }
985: // update value automatically generated by the DB (index, ...)
986: select(false);
987: try {
988: if (result == null) {
989: return false;
990: }
991: if (result.first()) {
1.7 bmahe 992: return updateProperties(false);
1.5 bmahe 993: } else {
994: return false;
995: }
996: } catch (SQLException ex) {
997: ex.printStackTrace();
998: return false;
999: }
1000: }
1001:
1.13 bmahe 1002: /**
1003: * Update the row relative to our bean.
1004: * @param primarykey The primary key of the SQL table
1005: * @return false if the UPDATE request failed.
1006: */
1.5 bmahe 1007: public boolean update(String primarykey) {
1008: String array[] = { primarykey };
1009: return update(array);
1010: }
1011:
1.13 bmahe 1012: /**
1013: * Update the row relative to our bean.
1014: * @param primarykey The primary key of the SQL table
1015: * @return false if the UPDATE request failed.
1016: */
1.5 bmahe 1017: public boolean update(String primarykeys[]) {
1018: if (! isModified()) { // noting to update
1019: return false;
1020: }
1021: String sql = computeSQLUpdate(primarykeys);
1022: try {
1023: int nb = executeSQLUpdate(sql);
1024: return (nb > 0);
1025: } catch (SQLException ex) {
1026: ex.printStackTrace();
1027: }
1028: return false;
1029: }
1030:
1.13 bmahe 1031: /**
1032: * Delete the row relative to the current bean.
1033: * @return false if the DELETE request failed.
1034: */
1.5 bmahe 1035: public boolean delete() {
1036: if (bean.getReadOnly()) {
1037: return false;
1038: }
1039: String sql = computeSQLDelete();
1.2 bmahe 1040: try {
1.5 bmahe 1041: int nb = executeSQLUpdate(sql);
1042: return (nb > 0);
1.2 bmahe 1043: } catch (SQLException ex) {
1.5 bmahe 1044: System.out.println("SQL STATE: "+ex.getSQLState());
1.2 bmahe 1045: ex.printStackTrace();
1046: result = null;
1.5 bmahe 1047: return false; // FIXME VERIFY
1.2 bmahe 1048: }
1049: }
1050:
1051: /**
1052: * Go to the first row
1053: * @return false if there is no first row
1054: */
1055: public boolean first() {
1056: try {
1057: if (result == null) {
1058: return false;
1059: }
1060: if (result.first()) {
1.7 bmahe 1061: return updateProperties();
1.2 bmahe 1062: }
1063: } catch (SQLException ex) { }
1064: return false;
1065: }
1066:
1067: /**
1068: * Update our bean with the value of the next row
1069: * @return false if there is no more row
1070: */
1071: public boolean next() {
1072: try {
1073: if (result == null) {
1074: return false;
1075: }
1076: if (result.next()) {
1.7 bmahe 1077: return updateProperties();
1.2 bmahe 1078: }
1079: } catch (SQLException ex) { }
1080: return false;
1081: }
1082:
1.13 bmahe 1083: /**
1084: * Did we reached the last row?
1085: * @return true if the last row is reached
1086: */
1.7 bmahe 1087: public boolean isLast() {
1088: try {
1089: if (result == null) {
1090: return true;
1091: }
1092: return result.isLast();
1093: } catch (SQLException ex) { }
1094: return true;
1095: }
1096:
1.5 bmahe 1097: /**
1098: * Clean cached properties (relative to our bean)
1099: */
1100: public void clean() {
1.7 bmahe 1101: result = null;
1.9 bmahe 1102: PropertyCache.removeProperties(bean);
1103: markModified(false);
1.5 bmahe 1104: }
1105:
1.10 bmahe 1106: /**
1107: * Restore default value except for JdbcBean properties.
1108: */
1109: public void initBean() {
1110: try {
1111: BeanInfo info = Introspector.getBeanInfo(bean.getClass());
1112: PropertyDescriptor pds[] = info.getPropertyDescriptors();
1113: for (int i = 0 ; i < pds.length ; i++) {
1114: PropertyDescriptor pd = pds[i];
1115: if ((! pd.isHidden()) &&
1116: (! JdbcBeanUtil.isJdbcBean(pd.getPropertyType()))) {
1117: Method getter = pd.getReadMethod();
1118: Method setter = pd.getWriteMethod();
1119: Object value = null;
1120: if ((getter != null) && (setter != null)) {
1121: try {
1.17 ! ylafon 1122: value = getter.invoke(bean.getDefault(),
! 1123: (Object [])null);
1.10 bmahe 1124: Object array[] = { value };
1125: setter.invoke(bean, array);
1126: } catch (IllegalAccessException ex) {
1127: ex.printStackTrace();
1128: // nothing to do
1129: } catch (InvocationTargetException ex) {
1130: ex.printStackTrace();
1131: // still nothing to do
1132: } catch (IllegalArgumentException ex) {
1133: ex.printStackTrace();
1134: // nothing to do
1135: }
1136: }
1137: }
1138: }
1139: clean();
1140: } catch (IntrospectionException ex) {
1141: }
1142: }
1143:
1.13 bmahe 1144: private int findColumn(Vector tables, ResultSet result, String colname)
1.7 bmahe 1145: throws SQLException
1146: {
1147: String tablename = bean.getJdbcTable();
1148: ResultSetMetaData metadata = result.getMetaData();
1149: int cpt = 0;
1.15 bmahe 1150: if (metadata.getTableName(1).length() > 0) { // applicable
1.7 bmahe 1151: for (int i = 0 ; i < metadata.getColumnCount() ; i++) {
1152: String coltable = metadata.getTableName(i);
1.15 bmahe 1153: if ((metadata.getTableName(i).equalsIgnoreCase(tablename)) &&
1154: (metadata.getColumnName(i).equalsIgnoreCase(colname))) {
1.7 bmahe 1155: return i;
1156: }
1157: }
1158: } else { // not applicable
1159: // search all columns matching the given name
1160: Vector indexes = new Vector();
1161: try {
1162: for (int i = 1 ; i <= metadata.getColumnCount() ; i++) {
1163: if (metadata.getColumnName(i).equals(colname)) {
1164: indexes.addElement(new Integer(i));
1165: }
1166: }
1167: } catch (Exception ex) {
1168: ex.printStackTrace();
1169: }
1170: // find the good one
1171: if (indexes.size() == 0) {
1172: return -1;
1173: } else if (indexes.size() == 1) {
1174: return ((Integer)indexes.elementAt(0)).intValue();
1175: } else {
1176: int idxidx = 0;
1177: for (int i = 0 ; i < tables.size() ; i++) {
1178: JdbcBeanInterface jbean =
1179: (JdbcBeanInterface)tables.elementAt(i);
1180: if (jbean == bean) {
1181: return ((Integer)indexes.elementAt(idxidx)).intValue();
1182: }
1183: if (jbean.getSerializer().getPropertyDescriptor(colname) !=
1184: null) {
1185: // exists in this table
1186: idxidx++;
1187: }
1188: }
1189: }
1190: }
1191: return -1;
1.5 bmahe 1192: }
1193:
1.13 bmahe 1194: private boolean updateProperties() {
1.7 bmahe 1195: return updateProperties(this.beantables, this.result, true);
1196: }
1197:
1.13 bmahe 1198: private boolean updateProperties(boolean all) {
1.7 bmahe 1199: return updateProperties(this.beantables, this.result, all);
1200: }
1201:
1.13 bmahe 1202: private boolean updateProperties(Vector tables,
1203: ResultSet result)
1.7 bmahe 1204: {
1205: return updateProperties(tables, result, true);
1206: }
1207:
1.13 bmahe 1208: private boolean updateProperties(Vector tables,
1209: ResultSet result,
1210: boolean all)
1.7 bmahe 1211: {
1.2 bmahe 1212: try {
1213: BeanInfo info = Introspector.getBeanInfo(bean.getClass());
1214: PropertyDescriptor pds[] = info.getPropertyDescriptors();
1215: for (int i = 0 ; i < pds.length ; i++) {
1216: PropertyDescriptor pd = pds[i];
1217: if (! pd.isHidden()) {
1218: try {
1.7 bmahe 1219: int idx = findColumn(tables, result, pd.getName());
1220: if (idx != -1) {
1221: Object value = result.getObject(idx);
1222: Class propertyclass = pd.getPropertyType();
1223: value = SQL.getMatchingValue(propertyclass, value);
1224: if (value != null) {
1225: Object values[] = { value };
1226: Method setter = pd.getWriteMethod();
1227: if (setter != null) {
1228: try {
1229: setter.invoke(bean, values);
1230: } catch (IllegalAccessException ex) {
1231: ex.printStackTrace();
1232: // nothing to do
1233: } catch (InvocationTargetException ex) {
1234: ex.printStackTrace();
1235: // still nothing to do
1236: } catch (IllegalArgumentException ex) {
1237: ex.printStackTrace();
1238: // nothing to do
1239: }
1.2 bmahe 1240: }
1.9 bmahe 1241: } else {
1242: // default value
1243: Method getter = pd.getReadMethod();
1244: Method setter = pd.getWriteMethod();
1245: if ((getter != null) && (setter != null)) {
1246: try {
1247: value =
1248: getter.invoke(bean.getDefault(),
1.17 ! ylafon 1249: (Object [])null);
1.9 bmahe 1250: Object array[] = { value };
1251: setter.invoke(bean, array);
1252: } catch (IllegalAccessException ex) {
1253: ex.printStackTrace();
1254: // nothing to do
1255: } catch (InvocationTargetException ex) {
1256: ex.printStackTrace();
1257: // still nothing to do
1258: } catch (IllegalArgumentException ex) {
1259: ex.printStackTrace();
1260: // nothing to do
1261: }
1262: }
1.2 bmahe 1263: }
1264: }
1265: } catch (SQLException ex) { // not found
1266: // nothing to do
1267: }
1268: }
1269: }
1.5 bmahe 1270: if (all) {
1271: // update the associated beans
1272: JdbcBeanInterface beans[] = getJdbcBeans();
1273: for (int i = 0 ; i < beans.length ; i++) {
1.7 bmahe 1274: beans[i].getSerializer().updateProperties(tables, result);
1.5 bmahe 1275: }
1.2 bmahe 1276: }
1.5 bmahe 1277: markModified(false);
1.2 bmahe 1278: return true;
1279: } catch (IntrospectionException ex) {
1280: return false;
1281: }
1.5 bmahe 1282: }
1283:
1.9 bmahe 1284: /**
1285: * Update our bean property with the given bean property
1286: * (must be an instance of the same class).
1287: * @param ubean the bean to get new properties
1288: */
1289: public void updateProperties(JdbcBeanInterface ubean) {
1290: if (ubean.getClass() != bean.getClass()) {
1291: return;
1292: }
1293: try {
1294: BeanInfo bi = Introspector.getBeanInfo(bean.getClass());
1295: PropertyDescriptor pds[] = bi.getPropertyDescriptors();
1296: for (int i = 0 ; i < pds.length ; i++) {
1297: PropertyDescriptor pd = pds[i];
1298: if (! pd.isHidden()) {
1299: try {
1300: Method reader = pd.getReadMethod();
1301: Method writer = pd.getWriteMethod();
1.17 ! ylafon 1302: Object value = reader.invoke(ubean,
! 1303: (Object [])null);
1.9 bmahe 1304: if (value != null) {
1305: Object array[] = { value };
1306: writer.invoke(bean, array);
1307: }
1308: } catch (IllegalAccessException ex) {
1309: ex.printStackTrace();
1310: } catch (InvocationTargetException ex) {
1311: ex.printStackTrace();
1312: }
1313: }
1314: }
1315: } catch (IntrospectionException ex) {
1316: // nothing to do
1317: }
1318: }
1319:
1.13 bmahe 1320: private PropertyDescriptor getPropertyDescriptor(String property) {
1.5 bmahe 1321: try {
1322: BeanInfo bi = Introspector.getBeanInfo(bean.getClass());
1323: PropertyDescriptor pds[] = bi.getPropertyDescriptors();
1324: for (int i = 0 ; i < pds.length ; i++) {
1325: PropertyDescriptor pd = pds[i];
1326: if (pd.getName().equals(property)) {
1327: return pd;
1328: }
1329: }
1330: return null;
1331: } catch (IntrospectionException ex) {
1332: return null;
1333: }
1334: }
1335:
1.13 bmahe 1336: private void updateForeignKeys(JdbcBeanInterface jbean) {
1.5 bmahe 1337: String keys[] = getForeignKeys(jbean.getClass(), bean.getClass());
1338: JdbcBeanSerializer ser = jbean.getSerializer();
1339: for (int i = 0 ; i < keys.length ; i++) {
1340: try {
1341: String key = keys[i];
1342: PropertyDescriptor wkeypd = getPropertyDescriptor(key);
1343: PropertyDescriptor rkeypd = ser.getPropertyDescriptor(key);
1344: Method reader = rkeypd.getReadMethod();
1345: Method writer = wkeypd.getWriteMethod();
1.17 ! ylafon 1346: Object value = reader.invoke(jbean, (Object [])null);
1.5 bmahe 1347: if (value != null) {
1348: Object array[] = { value };
1349: writer.invoke(bean, array);
1350: }
1351: } catch (IllegalAccessException ex) {
1352: ex.printStackTrace();
1353: } catch (InvocationTargetException ex) {
1354: ex.printStackTrace();
1355: }
1356: }
1357: }
1358:
1.6 bmahe 1359: /**
1360: * Called by the Garbage Collector.
1361: */
1.5 bmahe 1362: protected void finalize()
1363: throws Throwable
1364: {
1365: // cleanup (static) cached properties
1.9 bmahe 1366: PropertyCache.removeProperties(this.bean);
1.2 bmahe 1367: }
1368:
1.13 bmahe 1369: /**
1370: * Constructor
1371: * @param bean the JdbcBean to serialize
1372: */
1.1 bmahe 1373: public JdbcBeanSerializer(JdbcBeanInterface bean) {
1.9 bmahe 1374: this.bean = bean;
1.1 bmahe 1375: bean.addPropertyChangeListener(this);
1376: }
1377:
1378: }
1379:
1380:
Webmaster