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