Annotation of java/classes/org/w3c/tools/jdbc/JdbcBeanSerializer.java, revision 1.6

1.1       bmahe       1: // JdbcBeanSerializer.java
1.6     ! bmahe       2: // $Id: JdbcBeanSerializer.java,v 1.5 2000/07/07 15:36:13 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;
                      8: import java.beans.IntrospectionException;
                      9: import java.beans.Introspector;
                     10: import java.beans.PropertyChangeListener;
                     11: import java.beans.PropertyChangeEvent;
                     12: import java.beans.PropertyDescriptor;
                     13: 
                     14: import java.lang.reflect.Method;
                     15: import java.lang.reflect.InvocationTargetException;
                     16: 
                     17: import java.sql.ResultSet;
1.2       bmahe      18: import java.sql.SQLException;
1.1       bmahe      19: 
1.5       bmahe      20: import java.util.Enumeration;
1.1       bmahe      21: import java.util.Hashtable;
1.2       bmahe      22: import java.util.Properties;
1.1       bmahe      23: import java.util.Vector;
                     24: 
1.2       bmahe      25: import org.w3c.tools.jdbc.JdbcServer;
                     26: 
1.1       bmahe      27: /**
1.6     ! bmahe      28:  * @version $Revision: 1.5 $
1.1       bmahe      29:  * @author  Beno�t Mah� (bmahe@w3.org)
                     30:  */
                     31: public class JdbcBeanSerializer implements PropertyChangeListener {
                     32:     
                     33:     /**
1.5       bmahe      34:      * Bean modified?
                     35:      */
                     36:     protected boolean modified = false;
                     37: 
                     38:     /**
1.1       bmahe      39:      * Our bean.
                     40:      */
                     41:     protected JdbcBeanInterface bean = null;
                     42: 
                     43:     /**
                     44:      * The associated JdbcBean
                     45:      */
                     46:     protected JdbcBeanInterface beans[] = null;
                     47: 
                     48:     /**
                     49:      * The ResultSet
                     50:      */
                     51:     protected ResultSet result = null;
                     52: 
                     53:     /**
1.2       bmahe      54:      * The Foreign keys <(class,class), String[]>
                     55:      */
                     56:     protected static Hashtable foreignKeys = new Hashtable();
                     57: 
                     58:     public static void registerForeignKeys(Class beanclass1, Class beanclass2)
                     59:     {
                     60:        Integer key = new Integer(beanclass1.hashCode() & 
                     61:                                  beanclass2.hashCode());
1.5       bmahe      62:        if (! foreignKeys.containsKey(key)) {
1.2       bmahe      63:            foreignKeys.put(key, computeForeignKeys(beanclass1, beanclass2));
                     64:        }
                     65:     }
                     66: 
                     67:     public static String[] getForeignKeys(Class beanclass1,
                     68:                                          Class beanclass2)
                     69:     {
                     70:        Integer key = new Integer(beanclass1.hashCode() & 
                     71:                                  beanclass2.hashCode());
                     72:        String keys[] = (String[]) foreignKeys.get(key);
                     73:        if (keys == null) {
                     74:            keys = computeForeignKeys(beanclass1, beanclass2);
                     75:            foreignKeys.put(key, keys);
                     76:        }
                     77:        return keys;
                     78:     }
                     79: 
                     80:     protected static String[] computeForeignKeys(Class beanclass1,
                     81:                                                 Class beanclass2) 
                     82:     {
                     83:        try {
                     84:            BeanInfo           bi1    = Introspector.getBeanInfo(beanclass1);
                     85:            PropertyDescriptor pds1[] = bi1.getPropertyDescriptors();
                     86: 
                     87:            BeanInfo           bi2    = Introspector.getBeanInfo(beanclass2);
                     88:            PropertyDescriptor pds2[] = bi2.getPropertyDescriptors();
                     89:        
                     90:            Vector foreign = new Vector();
                     91:            
                     92:            for(int cpt1 = 0 ; cpt1 < pds1.length ; cpt1++) {
                     93:                PropertyDescriptor pd1 = pds1[cpt1];
                     94:                for (int cpt2 = 0 ; cpt2 < pds2.length ; cpt2++) {
                     95:                    PropertyDescriptor pd2 = pds2[cpt2];
                     96:                    if ((! pd2.isHidden()) 
                     97:                        && (! pd1.isHidden())
                     98:                        && (pd1.getName().equals(pd2.getName()))) {
                     99:                        foreign.addElement(pd1.getName());
                    100:                    }
                    101:                }
                    102:            }
                    103:            String keys[] = new String[foreign.size()];
                    104:            foreign.copyInto(keys);
                    105:            return keys;
                    106:        } catch (IntrospectionException ex) {
                    107:            return new String[0];
                    108:        }
                    109:     }
                    110: 
                    111:     /**
1.1       bmahe     112:      * The modified properties
                    113:      */
1.2       bmahe     114:     protected static Hashtable properties = new Hashtable();
                    115: 
                    116:     protected static String getId(JdbcBeanInterface bean, String property) {
                    117:        StringBuffer buffer = 
                    118:            new StringBuffer(String.valueOf(bean.hashCode()));
                    119:        buffer.append(".").append(property);
                    120:        return buffer.toString();
                    121:     }
1.1       bmahe     122: 
1.2       bmahe     123:     protected static void addProperty(JdbcBeanInterface bean, 
                    124:                                      String property, 
                    125:                                      Object value) 
1.1       bmahe     126:     {
1.2       bmahe     127:        String id = getId(bean, property);
                    128:        if (id != null) {
                    129:            properties.put(id, value);
1.1       bmahe     130:        }
                    131:     }
                    132: 
1.2       bmahe     133:     protected static Object getProperty(JdbcBeanInterface bean,
                    134:                                        PropertyDescriptor pd) 
1.1       bmahe     135:     {
1.2       bmahe     136:        String id = getId(bean, pd.getName());
                    137:        if (id != null) {
                    138:            return properties.get(id);
1.1       bmahe     139:        }
1.2       bmahe     140:        return null;
1.1       bmahe     141:     }
                    142: 
1.5       bmahe     143:     protected static void removeProperties(JdbcBeanInterface bean) {
                    144:        Enumeration keys = properties.keys();
                    145:        StringBuffer buffer = 
                    146:            new StringBuffer(String.valueOf(bean.hashCode()));
                    147:        buffer.append(".");
                    148:        String beankey = buffer.toString();
                    149:        while (keys.hasMoreElements()) {
                    150:            String key = (String)keys.nextElement();
                    151:            if (key.startsWith(beankey)) {
                    152:                properties.remove(key);
                    153:            }
                    154:        }
                    155:     }
                    156: 
                    157:     protected void markModified(boolean modified) {
                    158:        this.modified = modified;
                    159:     }
                    160: 
                    161:     protected boolean isModified() {
                    162:        return modified;
                    163:     }
                    164: 
1.1       bmahe     165:     /**
                    166:      * PropertyChangeListener implementation: This method gets called when
                    167:      * a bound property is changed.
                    168:      * @param evt A PropertyChangeEvent object describing the event source 
                    169:      * and the property that has changed.
                    170:      */
                    171:     public void propertyChange(PropertyChangeEvent evt) {
                    172:        Object source = evt.getSource();
1.5       bmahe     173:        String name   = evt.getPropertyName();
                    174:        Object value  = evt.getNewValue();
1.2       bmahe     175:        if (source == bean) {
1.5       bmahe     176:            if (value instanceof JdbcBeanInterface) {
                    177:                registerForeignKeys(bean.getClass(), value.getClass());
1.4       bmahe     178:                // delete cached bean descriptors
                    179:                this.beans = null;
1.5       bmahe     180:                // update listeners
                    181:                JdbcBeanInterface oldbean = 
                    182:                    (JdbcBeanInterface)evt.getOldValue();
                    183:                JdbcBeanInterface newbean = (JdbcBeanInterface)value;
                    184:                if (oldbean != null) {
                    185:                    removeProperties(oldbean);
                    186:                    oldbean.removePropertyChangeListener(this);
                    187:                }
                    188:                newbean.addPropertyChangeListener(this);
                    189:            } else {
1.2       bmahe     190:                JdbcBeanInterface bean = (JdbcBeanInterface)source;
                    191:                addProperty(bean, name, evt.getNewValue());
1.5       bmahe     192:                markModified(true);
                    193:            }
                    194:        } else {
                    195:            markModified(true);
1.1       bmahe     196:        }
                    197:     }
                    198: 
1.2       bmahe     199:     /**
                    200:      * Get the raw value of the given property, split the operator and
                    201:      * the value and convert the raw value into a SQL value.<p>
                    202:      * ie "~A.*" will become { " ~ " , "'A.*'" }
                    203:      * @param bean the property holder
                    204:      * @param pd the property descriptor
                    205:      */
                    206:     protected String[] getSQLOperatorNValue(JdbcBeanInterface bean, 
                    207:                                            PropertyDescriptor pd) 
1.1       bmahe     208:     {
                    209:        Class  type = pd.getPropertyType();
                    210:        Method m    = pd.getReadMethod(); 
                    211:        if (m != null) { // are we authozired to read it?
                    212:            Object value = getProperty(bean, pd); // use the cache
                    213:            if (value == null) {
                    214:                return null;
                    215:            }
                    216:            if (type == String.class) {
1.2       bmahe     217:                String split[] = getSQLOperator((String)value);
1.1       bmahe     218:                StringBuffer buffer = new StringBuffer("'");
1.2       bmahe     219:                buffer.append(SQL.encode(split[1])).append("'");
                    220:                split[1] = buffer.toString();
                    221:                return split;
                    222:            } else { // operator always '='
                    223:                String split[] = { " = ", String.valueOf(value) };
                    224:                return split;
1.1       bmahe     225:            }
                    226:        }
                    227:        return null;
                    228:     }
                    229: 
                    230:     /**
1.5       bmahe     231:      * Get the SQL value of the given property.
                    232:      * @param bean the property holder
                    233:      * @param pd the property descriptor
                    234:      */
                    235:     protected String getSQLValue(JdbcBeanInterface bean, 
                    236:                                 PropertyDescriptor pd) 
                    237:     {
                    238:        Class  type = pd.getPropertyType();
                    239:        Method m    = pd.getReadMethod(); 
                    240:        if (m != null) { // are we authozired to read it?
                    241:            Object value = getProperty(bean, pd); // use the cache
                    242:            if (value == null) {
                    243:                return null;
                    244:            }
                    245:            if (type == String.class) { // String => quote
                    246:                String split[] = getSQLOperator((String)value);
                    247:                StringBuffer buffer = new StringBuffer("'");
                    248:                buffer.append(SQL.encode((String)value)).append("'");
                    249:                return buffer.toString();
                    250:            } else { // not a String => no quote
                    251:                return String.valueOf(value);
                    252:            }
                    253:        }
                    254:        return null;
                    255:     }
                    256: 
                    257:     /**
1.2       bmahe     258:      * Split the SQL operator and the value, (default operator is '=')
                    259:      * example:<br>
                    260:      * "~*.*toto.*" will become { "~*", ".*toto.*" }<br>
                    261:      * but "\~*.*toto.*" will become { "=", "~*.*toto.*" }
                    262:      * <p>possible operators are:
                    263:      * <table border=0>
                    264:      * <tr><td> &lt; </td><td>Less than?</td></tr> 
                    265:      * <tr><td> &lt;= </td><td>Less than or equals?</td></tr>  
                    266:      * <tr><td> &lt;&gt; </td><td>Not equal?</td></tr>  
                    267:      * <tr><td> = </td><td>Equals?</td></tr>  
                    268:      * <tr><td> &gt; </td><td>Greater than?</td></tr>
                    269:      * <tr><td> &gt;= </td><td>Greater than or equals?</td></tr>
                    270:      * <tr><td> ~~ </td><td>LIKE</td></tr>
                    271:      * <tr><td> !~~ </td><td>NOT LIKE</td></tr>
                    272:      * <tr><td> ~ </td><td>Match (regex), case sensitive</td></tr>
                    273:      * <tr><td> ~* </td><td>Match (regex), case insensitive</td></tr>
                    274:      * <tr><td> !~ </td><td>Does not match (regex), case sensitive </td></tr>
                    275:      * <tr><td> !~* </td><td>Does not match (regex), case insensitive</td></tr>
                    276:      * </table>
                    277:      */
                    278:     protected String[] getSQLOperator(String value) {
                    279:        String result[] = new String[2];
                    280:        char c = value.charAt(0);
                    281:        switch (c) 
                    282:            {
                    283:            case '~':
                    284:                c = value.charAt(1);
                    285:                if (c == '*') {                       // ~*
                    286:                    result[0] = " ~* ";
                    287:                    result[1] = value.substring(2);
                    288:                } else if (c == '~') {                // ~~
                    289:                    result[0] = " ~~ ";
                    290:                    result[1] = value.substring(2);
                    291:                } else {                              // ~
                    292:                    result[0] = " ~ ";
                    293:                    result[1] = value.substring(1);
                    294:                }
                    295:                break;
                    296:            case '<':
                    297:                c = value.charAt(1);
                    298:                if (c == '=') {                       // <=
                    299:                    result[0] = " <= ";
                    300:                    result[1] = value.substring(2);
                    301:                } else if (c == '>') {                // <>
                    302:                    result[0] = " <> ";
                    303:                    result[1] = value.substring(2);
                    304:                } else {                              // <
                    305:                    result[0] = " < ";
                    306:                    result[1] = value.substring(1);
                    307:                }
                    308:                break;
                    309:            case '>':
                    310:                c = value.charAt(1);
                    311:                if (c == '=') {                      // >=
                    312:                    result[0] = " >= ";
                    313:                    result[1] = value.substring(2);
                    314:                } else {                             // >
                    315:                    result[0] = " > ";
                    316:                    result[1] = value.substring(1);
                    317:                }
                    318:                break;
                    319:            case '!':
                    320:                if (c == '~') {
                    321:                    c = value.charAt(2);
                    322:                    if (c == '~') {                 // !~~
                    323:                        result[0] = " !~~ ";
                    324:                        result[1] = value.substring(3);
                    325:                    } else if (c == '*') {          // !~* 
                    326:                        result[0] = " !~* ";
                    327:                        result[1] = value.substring(3);
                    328:                    } else {                        // !~
                    329:                        result[0] = " !~ ";
                    330:                        result[1] = value.substring(2);
                    331:                    }
                    332:                    break;
                    333:                } 
                    334:            case '\\':
                    335:                value = value.substring(1);
                    336:            case '=':                               // =
                    337:            default:
                    338:                result[0] = " = ";
                    339:                result[1] = value;
                    340:            }
                    341:        return result;
                    342:     }
                    343: 
                    344:     /**
1.1       bmahe     345:      * @param name
                    346:      * @param value
                    347:      * @param buf
                    348:      */
1.5       bmahe     349:     private void append(String name, 
                    350:                        String operator,
                    351:                        String value, 
                    352:                        String separator,
                    353:                        StringBuffer buf)
                    354:     {
                    355:        if (buf.length() > 0) {
                    356:            buf.append(separator).append(" ");
                    357:        }
                    358:        buf.append(name).append(operator).append(value).append(" ");
                    359:     }
                    360: 
                    361:     /**
                    362:      * @param name
                    363:      * @param value
                    364:      * @param namesbuffer
                    365:      * @param valuesbuffer
                    366:      */
                    367:     private void appendInsert(String name, 
1.2       bmahe     368:                              String value, 
1.5       bmahe     369:                              StringBuffer namesbuffer,
                    370:                              StringBuffer valuesbuffer)
1.1       bmahe     371:     {
1.5       bmahe     372:        if (namesbuffer.length() > 0) {
                    373:            namesbuffer.append(", ").append(name);
                    374:            valuesbuffer.append(", ").append(value);
                    375:        } else {
                    376:            namesbuffer.append("(").append(name);
                    377:            valuesbuffer.append("(").append(value);
1.1       bmahe     378:        }
                    379:     }
                    380: 
                    381:     protected JdbcBeanInterface[] getJdbcBeans() {
                    382:        if (beans != null) {
                    383:            return beans;
                    384:        }
                    385:        try {
                    386:            BeanInfo info = Introspector.getBeanInfo(bean.getClass());
                    387:            Vector   vb   = new Vector();
                    388:            PropertyDescriptor pds[] = info.getPropertyDescriptors();
                    389:            for (int i = 0 ; i < pds.length ; i++) {
                    390:                PropertyDescriptor pd = pds[i];
1.5       bmahe     391:                if ((! pd.isHidden()) &&  
                    392:                    (JdbcBeanUtil.isJdbcBean(pd.getPropertyType()))) {
1.1       bmahe     393:                    Method m = pd.getReadMethod();
                    394:                    if (m != null) {
                    395:                        Object value = m.invoke(bean, null);
                    396:                        if (value != null) {
                    397:                            vb.addElement(value);
                    398:                        }
                    399:                    }
                    400:                }
                    401:            }
                    402:            beans = new JdbcBeanInterface[vb.size()];
                    403:            vb.copyInto(beans);
                    404:            return beans;
                    405:        } catch (IntrospectionException ex) {
                    406:            return null;
                    407:        } catch (IllegalAccessException ex) {
                    408:            return null;
                    409:        } catch (InvocationTargetException ex) {
                    410:            return null;
                    411:        }
                    412:     }
                    413: 
                    414:     protected void appendForeignKeys(StringBuffer tables,
                    415:                                     StringBuffer buffer,
                    416:                                     PropertyDescriptor pds[])
1.2       bmahe     417:        throws IntrospectionException //FIXME
1.1       bmahe     418:     {
                    419:        JdbcBeanInterface jbeans[] = getJdbcBeans();
                    420:        if (jbeans != null) { // FORGEIGN KEYs
                    421:            for (int i = 0 ; i < jbeans.length ; i++) {
                    422:                JdbcBeanInterface jbean = jbeans[i];
1.2       bmahe     423:                // foreign keys
                    424:                String keys[] = getForeignKeys(jbean.getClass(),
                    425:                                               bean.getClass());
                    426:                for (int f = 0 ; f < keys.length ; f++) {
                    427:                    String key = keys[f];
1.5       bmahe     428:                    append(jbean.getJdbcTable()+"."+key,
                    429:                           " = ",
                    430:                           bean.getJdbcTable()+"."+key,
                    431:                           "AND",
                    432:                           buffer);
1.2       bmahe     433:                }
                    434:                // value now
1.1       bmahe     435:                BeanInfo bi = Introspector.getBeanInfo(jbean.getClass());
                    436:                PropertyDescriptor jpds[] = bi.getPropertyDescriptors();
                    437:                for (int jpd_cpt = 0 ; jpd_cpt < jpds.length ; jpd_cpt++) {
                    438:                    PropertyDescriptor jpd = jpds[jpd_cpt];
                    439:                    if (jpd.isHidden()) {
                    440:                        continue;
                    441:                    }
                    442:                    String jname = jpd.getName();
1.2       bmahe     443:                    String split[] = getSQLOperatorNValue(jbean, jpd);
                    444:                    if (split != null) {
1.5       bmahe     445:                        append(jbean.getJdbcTable()+"."+jname,
                    446:                               split[0],
                    447:                               split[1],
                    448:                               "AND",
                    449:                               buffer);
1.1       bmahe     450:                    }
1.2       bmahe     451:                }
                    452:                if (tables.length() > 0) {
                    453:                    tables.append(", "+jbean.getJdbcTable());
                    454:                } else {
                    455:                    tables.append(jbean.getJdbcTable());
1.1       bmahe     456:                }
                    457:            }
                    458:        }
                    459:     }
                    460: 
1.5       bmahe     461:     protected String computeSQLSelect(String orderby[], boolean all) {
1.1       bmahe     462:        try {
                    463:            BeanInfo     info   = Introspector.getBeanInfo(bean.getClass());
                    464:            StringBuffer buffer = new StringBuffer();
                    465:            String       table  = bean.getJdbcTable();
                    466:            StringBuffer tables = new StringBuffer(table);
                    467:            PropertyDescriptor pds[] = info.getPropertyDescriptors();
1.5       bmahe     468:            if (all) {
                    469:                // FOREIGN KEYs
                    470:                appendForeignKeys(tables, buffer, pds);
                    471:            }
1.1       bmahe     472:            // known values
                    473:            for (int i = 0 ; i < pds.length ; i++) { 
                    474:                PropertyDescriptor pd = pds[i];
                    475:                if (! pd.isHidden()) {
1.2       bmahe     476:                    String split[] = getSQLOperatorNValue(bean, pd);
                    477:                    if (split != null) {
1.5       bmahe     478:                        append(table+"."+pd.getName(), 
                    479:                               split[0],
                    480:                               split[1],
                    481:                               "AND",
                    482:                               buffer);
1.1       bmahe     483:                    }
                    484:                }
                    485:            }
                    486:            // build SQL request
                    487:            if (buffer.length() > 0) {
                    488:                tables.append(" WHERE ");
                    489:                tables.insert(0, "SELECT * FROM ");
                    490:                tables.append(buffer.toString());
1.2       bmahe     491:                buffer = tables;
1.1       bmahe     492:            } else {
1.2       bmahe     493:                buffer = new StringBuffer("SELECT * FROM ");
                    494:                buffer.append(table);
                    495:            }
                    496:            if (orderby != null) {
                    497:                buffer.append(" ORDER BY ");
                    498:                for (int i = 0 ; i < orderby.length ; i++) {
                    499:                    if (i != 0) {
                    500:                        buffer.append(", ");
                    501:                    }
                    502:                    buffer.append(orderby[i]);
                    503:                }
1.1       bmahe     504:            }
1.2       bmahe     505:            return buffer.toString();
1.1       bmahe     506:        } catch (IntrospectionException ex) {
                    507:            return null;
                    508:        }
                    509:     }
                    510: 
1.5       bmahe     511:     /**
                    512:      * Compute the SQL request necessary to update the Database.
                    513:      * @return a String
                    514:      */
                    515:     protected String computeSQLInsert() {
                    516:        try {
                    517:            BeanInfo info = Introspector.getBeanInfo(bean.getClass());
                    518:            PropertyDescriptor pds[]  = info.getPropertyDescriptors();
                    519:            StringBuffer namesbuffer  = new StringBuffer();
                    520:            StringBuffer valuesbuffer = new StringBuffer();
                    521:            for (int i = 0 ; i < pds.length ; i++) { 
                    522:                PropertyDescriptor pd = pds[i];
                    523:                if (! pd.isHidden()) {  
                    524:                    String value = getSQLValue(bean, pd);
                    525:                    if (value != null) {
                    526:                        appendInsert(pd.getName(), 
                    527:                                     value, 
                    528:                                     namesbuffer, 
                    529:                                     valuesbuffer);
                    530:                    }
                    531:                }
                    532:            }
                    533:            if (namesbuffer.length() > 0) {
                    534:                StringBuffer request = new StringBuffer("INSERT INTO ");
                    535:                request.append(bean.getJdbcTable()).append(" ");
                    536:                request.append(namesbuffer).append(") ");
                    537:                request.append("VALUES ").append(valuesbuffer).append(")");
                    538:                return request.toString();
                    539:            } else {
                    540:                return null;
                    541:            }
                    542:        } catch (IntrospectionException ex) {
                    543:            return null;
                    544:        }
                    545:     }
                    546: 
                    547:     protected String computeSQLDelete() {
                    548:        try {
                    549:            BeanInfo     info   = Introspector.getBeanInfo(bean.getClass());
                    550:            StringBuffer buffer = new StringBuffer();
                    551:            StringBuffer table = new StringBuffer(bean.getJdbcTable());
                    552:            PropertyDescriptor pds[] = info.getPropertyDescriptors();
                    553:            // known values
                    554:            for (int i = 0 ; i < pds.length ; i++) {
                    555:                PropertyDescriptor pd = pds[i];
                    556:                if (! pd.isHidden()) {
                    557:                    String split[] = getSQLOperatorNValue(bean, pd);
                    558:                    if (split != null) {
                    559:                        append(pd.getName(), split[0], split[1],"AND", buffer);
                    560:                    }
                    561:                }
                    562:            }
                    563:            // build SQL request
                    564:            if (buffer.length() > 0) {
                    565:                table.append(" WHERE ");
                    566:                table.insert(0, "DELETE FROM ");
                    567:                table.append(buffer.toString());
                    568:                buffer = table;
                    569:            } else {
                    570:                return null;
                    571:            }
                    572:            return buffer.toString();
                    573:        } catch (IntrospectionException ex) {
                    574:            return null;
                    575:        }
                    576:     }
                    577: 
                    578:     protected String computeSQLUpdate(String primarykeys[]) {
                    579:        try {
                    580:            BeanInfo     info     = Introspector.getBeanInfo(bean.getClass());
                    581:            StringBuffer buffer   = new StringBuffer();
                    582:            StringBuffer pkbuffer = new StringBuffer();
                    583:            StringBuffer table    = new StringBuffer(bean.getJdbcTable());
                    584:            PropertyDescriptor pds[] = info.getPropertyDescriptors();
                    585:            // known values
                    586:            for (int i = 0 ; i < pds.length ; i++) {
                    587:                PropertyDescriptor pd = pds[i];
                    588:                if (! pd.isHidden()) {
                    589:                    String name = pd.getName();
                    590:                    String split[] = getSQLOperatorNValue(bean, pd);
                    591:                    if (split != null) {
                    592:                        if (JdbcBeanUtil.isIn(name, primarykeys)) {
                    593:                            append(name, split[0], split[1], "AND", pkbuffer);
                    594:                        } else {
                    595:                            append(name, split[0], split[1], ",", buffer);
                    596:                        }
                    597:                    }
                    598:                }
                    599:            }
                    600:            // build SQL request
                    601:            if (buffer.length() > 0) {
                    602:                table.append(" SET ");
                    603:                table.insert(0, "UPDATE ");
                    604:                table.append(buffer.toString());
                    605:                table.append(" WHERE ");
                    606:                table.append(pkbuffer.toString());
                    607:                buffer = table;
                    608:            } else {
                    609:                return null;
                    610:            }
                    611:            return buffer.toString();
                    612:        } catch (IntrospectionException ex) {
                    613:            return null;
                    614:        }
                    615:     }
                    616: 
1.2       bmahe     617:     protected JdbcServer getJdbcServer() {
                    618:        Properties props = new Properties();
                    619:        Jdbc.setMaxConn(props, bean.getMaxConn());
                    620:        return JdbcServer.getServer(bean.getJdbcURI(), 
                    621:                                    bean.getJdbcUser(), 
                    622:                                    bean.getJdbcPassword(), 
                    623:                                    bean.getJdbcDriver(), 
                    624:                                    props);
                    625:     }
                    626: 
1.5       bmahe     627:     protected void executeSQLQuery(String sqlrequest) 
                    628:        throws SQLException
                    629:     {
                    630:        result = getJdbcServer().runQuery(sqlrequest, false);
                    631:     }
                    632: 
                    633:     protected int executeSQLUpdate(String sqlrequest) 
1.2       bmahe     634:        throws SQLException
                    635:     {
1.5       bmahe     636:        return getJdbcServer().runUpdate(sqlrequest, false);
1.2       bmahe     637:     }
                    638: 
                    639:     public void select() {
1.5       bmahe     640:        select((String[])null, true);
                    641:     }
                    642: 
                    643:     public void select(boolean all) {
                    644:        select((String[])null, all);
1.2       bmahe     645:     }
                    646: 
                    647:     public void select(String orderby) {
                    648:        String array[] = { orderby };
1.5       bmahe     649:        select(array, true);
                    650:     }
                    651: 
                    652:     public void select(String orderby, boolean all) {
                    653:        String array[] = { orderby };
                    654:        select(array, all);
1.2       bmahe     655:     }
                    656: 
                    657:     public void select(String orderby[]) {
1.5       bmahe     658:        select(orderby, true);
                    659:     }
                    660: 
                    661:     public void select(String orderby[], boolean all) {
                    662:        String sql = computeSQLSelect(orderby, all);
                    663:        try {
                    664:            executeSQLQuery(sql);
                    665:        } catch (SQLException ex) {
                    666:            System.out.println("SQL STATE: "+ex.getSQLState());
                    667:            ex.printStackTrace();
                    668:            result = null;
                    669:        }
                    670:     }
                    671: 
                    672:     public boolean insert() {
                    673:        if (! isModified()) { // nothing new to insert
                    674:            return false;
                    675:        }
                    676:        JdbcBeanInterface beans[] = getJdbcBeans();
                    677:        for (int i = 0 ; i < beans.length ; i++) { 
                    678:            JdbcBeanInterface jbean = beans[i];
                    679:            JdbcBeanSerializer ser  = jbean.getSerializer();
                    680:            if (ser.isModified()) {
                    681:                // insert associated bean
                    682:                ser.insert();
                    683:                // update our foreign key
                    684:                updateForeignKeys(jbean); 
                    685:            }
                    686:        }
                    687:        if (! bean.getReadOnly()) {
                    688:            // ok insert ourself now
                    689:            String request = computeSQLInsert();
                    690:            try {
                    691:                // insert (could fail without being critical)
                    692:                // ie: when the row is already in the table
                    693:                executeSQLUpdate(request);
                    694:            } catch (SQLException ex) {
                    695:                System.err.println(ex.getMessage());
                    696:            }
                    697:        }
                    698:        // update value automatically generated by the DB (index, ...)
                    699:        select(false);
                    700:        try {
                    701:            if (result == null) {
                    702:                return false;
                    703:            }
                    704:            if (result.first()) {
                    705:                return updateProperties(result, false);
                    706:            } else {
                    707:                return false;
                    708:            }
                    709:        } catch (SQLException ex) {
                    710:            ex.printStackTrace();
                    711:            return false;
                    712:        }
                    713:     }
                    714: 
                    715:     public boolean update(String primarykey) {
                    716:        String array[] = { primarykey };
                    717:        return update(array);
                    718:     }
                    719: 
                    720:     public boolean update(String primarykeys[]) {
                    721:        if (! isModified()) { // noting to update
                    722:            return false;
                    723:        }
                    724:        JdbcBeanInterface beans[] = getJdbcBeans();
                    725:        for (int i = 0 ; i < beans.length ; i++) { 
                    726:            JdbcBeanInterface jbean = beans[i];
                    727:            JdbcBeanSerializer ser  = jbean.getSerializer();
                    728:            if (ser.isModified()) {
                    729:                // insert associated bean
                    730:                ser.insert();
                    731:                // update our foreign key
                    732:                updateForeignKeys(jbean);
                    733:            }
                    734:        }
                    735:        String sql = computeSQLUpdate(primarykeys);
                    736:        try {
                    737:            int nb = executeSQLUpdate(sql);
                    738:            return (nb > 0);
                    739:        } catch (SQLException ex) {
                    740:            ex.printStackTrace();
                    741:        }
                    742:        return false;
                    743:     }
                    744: 
                    745:     public boolean delete() {
                    746:        if (bean.getReadOnly()) {
                    747:            return false;
                    748:        }
                    749:        String sql = computeSQLDelete();
1.2       bmahe     750:        try {
1.5       bmahe     751:            int nb = executeSQLUpdate(sql);
                    752:            System.err.println("NB : "+nb);
                    753:            return (nb > 0);
1.2       bmahe     754:        } catch (SQLException ex) {
1.5       bmahe     755:            System.out.println("SQL STATE: "+ex.getSQLState());
1.2       bmahe     756:            ex.printStackTrace();
                    757:            result = null;
1.5       bmahe     758:            return false; // FIXME VERIFY
1.2       bmahe     759:        }
                    760:     }
                    761: 
                    762:     /**
                    763:      * Go to the first row
                    764:      * @return false if there is no first row
                    765:      */
                    766:     public boolean first() {
                    767:        try {
                    768:            if (result == null) {
                    769:                return false;
                    770:            }
                    771:            if (result.first()) {
1.5       bmahe     772:                return updateProperties(result);
1.2       bmahe     773:            }
                    774:        } catch (SQLException ex) { }
                    775:        return false;
                    776:     }
                    777: 
                    778:     /**
                    779:      * Update our bean with the value of the next row
                    780:      * @return false if there is no more row
                    781:      */
                    782:     public boolean next() {
                    783:        try {
                    784:            if (result == null) {
                    785:                return false;
                    786:            }
                    787:            if (result.next()) {
1.5       bmahe     788:                return updateProperties(result);
1.2       bmahe     789:            }
                    790:        } catch (SQLException ex) { }
                    791:        return false;
                    792:     }
                    793: 
1.5       bmahe     794:     /**
                    795:      * Clean cached properties (relative to our bean)
                    796:      */
                    797:     public void clean() {
                    798:        removeProperties(bean);
                    799:     }
                    800: 
                    801:     protected boolean updateProperties(ResultSet result) {
                    802:        return updateProperties(result, true);
                    803:     }
                    804: 
                    805:     protected boolean updateProperties(ResultSet result, boolean all) {
1.2       bmahe     806:        try {
                    807:            BeanInfo info = Introspector.getBeanInfo(bean.getClass());
                    808:            PropertyDescriptor pds[] = info.getPropertyDescriptors();
                    809:            for (int i = 0 ; i < pds.length ; i++) {
                    810:                PropertyDescriptor pd = pds[i];
                    811:                if (! pd.isHidden()) {
                    812:                    try {
                    813:                        Object value  = result.getObject(pd.getName());
                    814:                        Class propertyclass = pd.getPropertyType();
                    815:                        value = SQL.getMatchingValue(propertyclass, value);
                    816:                        if (value != null) {
                    817:                            Object values[] = { value };
                    818:                            Method setter = pd.getWriteMethod();
                    819:                            if (setter != null) {
                    820:                                try {
                    821:                                    setter.invoke(bean, values);
                    822:                                } catch (IllegalAccessException ex) {
                    823:                                    ex.printStackTrace();
                    824:                                    // nothing to do
                    825:                                } catch (InvocationTargetException ex) {
                    826:                                    ex.printStackTrace();
                    827:                                    // still nothing to do
                    828:                                } catch (IllegalArgumentException ex) {
                    829:                                    ex.printStackTrace();
                    830:                                    // nothing to do
                    831:                                }
                    832:                            }
                    833:                        }
                    834:                    } catch (SQLException ex) { // not found
                    835:                        // nothing to do
                    836:                    }
                    837:                }
                    838:            }
1.5       bmahe     839:            if (all) {
                    840:                // update the associated beans
                    841:                JdbcBeanInterface beans[] = getJdbcBeans();
                    842:                for (int i = 0 ; i < beans.length ; i++) {
                    843:                    beans[i].getSerializer().updateProperties(result);
                    844:                }
1.2       bmahe     845:            }
1.5       bmahe     846:            markModified(false);
1.2       bmahe     847:            return true;
                    848:        } catch (IntrospectionException ex) {
                    849:            return false;
                    850:        }
1.5       bmahe     851:     }
                    852: 
                    853:     protected PropertyDescriptor getPropertyDescriptor(String property) {
                    854:        try {
                    855:            BeanInfo bi = Introspector.getBeanInfo(bean.getClass());
                    856:            PropertyDescriptor pds[] = bi.getPropertyDescriptors();
                    857:            for (int i = 0 ; i < pds.length ; i++) {
                    858:                PropertyDescriptor pd = pds[i];
                    859:                if (pd.getName().equals(property)) {
                    860:                    return pd;
                    861:                }
                    862:            }
                    863:            return null;
                    864:        } catch (IntrospectionException ex) {
                    865:            return null;
                    866:        }
                    867:     }
                    868: 
                    869:     protected void updateForeignKeys(JdbcBeanInterface jbean) {
                    870:        String keys[] = getForeignKeys(jbean.getClass(), bean.getClass());
                    871:        JdbcBeanSerializer ser = jbean.getSerializer();
                    872:        for (int i = 0 ; i < keys.length ; i++) { 
                    873:            try {
                    874:                String             key    = keys[i];
                    875:                PropertyDescriptor wkeypd = getPropertyDescriptor(key);
                    876:                PropertyDescriptor rkeypd = ser.getPropertyDescriptor(key);
                    877:                Method             reader = rkeypd.getReadMethod();
                    878:                Method             writer = wkeypd.getWriteMethod();
                    879:                Object value = reader.invoke(jbean, null);
                    880:                if (value != null) {
                    881:                    Object array[] = { value };
                    882:                    writer.invoke(bean, array);
                    883:                }
                    884:            } catch (IllegalAccessException ex) {
                    885:                ex.printStackTrace();
                    886:            } catch (InvocationTargetException ex) {
                    887:                ex.printStackTrace();
                    888:            }
                    889:        }
                    890:     }
                    891: 
1.6     ! bmahe     892:     /**
        !           893:      * Called by the Garbage Collector.
        !           894:      */
1.5       bmahe     895:     protected void finalize() 
                    896:        throws Throwable
                    897:     {
                    898:        // cleanup (static) cached properties
                    899:        removeProperties(this.bean);
1.2       bmahe     900:     }
                    901: 
1.1       bmahe     902:     public JdbcBeanSerializer(JdbcBeanInterface bean) {
1.2       bmahe     903:        this.bean = bean;
1.1       bmahe     904:        bean.addPropertyChangeListener(this);
                    905:     }
                    906: 
                    907: }
                    908: 
                    909: 

Webmaster