Source Code Cross Referenced for DbMgr.java in  » Project-Management » Activity-Manager » jfb » tools » activitymgr » core » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Project Management » Activity Manager » jfb.tools.activitymgr.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 2004-2006, Jean-François Brazeau. All rights reserved.
0003:         * 
0004:         * Redistribution and use in source and binary forms, with or without 
0005:         * modification, are permitted provided that the following conditions are met:
0006:         *
0007:         *  1. Redistributions of source code must retain the above copyright notice,
0008:         *     this list of conditions and the following disclaimer.
0009:         * 
0010:         *  2. Redistributions in binary form must reproduce the above copyright
0011:         *     notice, this list of conditions and the following disclaimer in the
0012:         *     documentation and/or other materials provided with the distribution.
0013:         * 
0014:         *  3. The name of the author may not be used to endorse or promote products
0015:         *     derived from this software without specific prior written permission.
0016:         *
0017:         * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0018:         * IMPLIEDWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0019:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0020:         * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0021:         * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
0022:         * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
0023:         * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0024:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
0025:         * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
0026:         * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0027:         */
0028:        package jfb.tools.activitymgr.core;
0029:
0030:        import java.io.IOException;
0031:        import java.io.InputStream;
0032:        import java.io.LineNumberReader;
0033:        import java.io.StringReader;
0034:        import java.sql.Connection;
0035:        import java.sql.PreparedStatement;
0036:        import java.sql.ResultSet;
0037:        import java.sql.SQLException;
0038:        import java.sql.Statement;
0039:        import java.text.SimpleDateFormat;
0040:        import java.util.ArrayList;
0041:        import java.util.Arrays;
0042:        import java.util.Calendar;
0043:        import java.util.Comparator;
0044:
0045:        import jfb.tools.activitymgr.core.beans.Collaborator;
0046:        import jfb.tools.activitymgr.core.beans.Contribution;
0047:        import jfb.tools.activitymgr.core.beans.Duration;
0048:        import jfb.tools.activitymgr.core.beans.Task;
0049:        import jfb.tools.activitymgr.core.beans.TaskSearchFilter;
0050:        import jfb.tools.activitymgr.core.beans.TaskSums;
0051:        import jfb.tools.activitymgr.core.util.StringHelper;
0052:
0053:        import org.apache.commons.dbcp.BasicDataSource;
0054:        import org.apache.log4j.Logger;
0055:
0056:        /**
0057:         * Classe offrant les services de base de persistence de 
0058:         * l'application.
0059:         */
0060:        public class DbMgr {
0061:
0062:            /** Logger */
0063:            private static Logger log = Logger.getLogger(DbMgr.class);
0064:
0065:            /** Formatteur de date */
0066:            private static SimpleDateFormat sdf = new SimpleDateFormat(
0067:                    "yyyyMMdd");
0068:
0069:            /** Datasource */
0070:            private static BasicDataSource ds = null;
0071:
0072:            /** Contexte de thread utilisé pour détecter les anomalies associées à la gestion de transaction */
0073:            private static ThreadLocal threadLocal = new ThreadLocal();
0074:
0075:            /**
0076:             * Initialise la connexion à la base de données.
0077:             * @param driverName le nom du driver JDBC.
0078:             * @param url l'URL de connexion au serveur.
0079:             * @param user l'identifiant de connexion/
0080:             * @param password le mot de passe de connexion.
0081:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0082:             */
0083:            protected static void initDatabaseAccess(String driverName,
0084:                    String url, String user, String password)
0085:                    throws DbException {
0086:                try {
0087:                    // Si la datasource existe on la ferme
0088:                    if (ds != null) {
0089:                        closeDatabaseAccess();
0090:                    }
0091:                    // Fermeture de la datasource
0092:                    BasicDataSource newDs = new BasicDataSource();
0093:
0094:                    // Initialisation de la Datasource
0095:                    newDs = new BasicDataSource();
0096:                    log.info("Connecting to '" + url + "'");
0097:                    newDs.setDriverClassName(driverName);
0098:                    newDs.setUrl(url);
0099:                    newDs.setUsername(user);
0100:                    newDs.setPassword(password);
0101:                    newDs.setDefaultAutoCommit(false);
0102:
0103:                    // Tentative de récupération d'une connexion
0104:                    // pour détecter les problèmes de connexion
0105:                    Connection con = newDs.getConnection();
0106:                    con.close();
0107:
0108:                    // Sauvegarde de la référence
0109:                    ds = newDs;
0110:                } catch (SQLException e) {
0111:                    log.info("SQL Exception", e);
0112:                    throw new DbException("Couldn't get a SQL Connection", e);
0113:                }
0114:            }
0115:
0116:            /**
0117:             * Ferme la base de données.
0118:             * @throws DbException levé en cas d'incident technique d'accès à la BDD.
0119:             */
0120:            protected static void closeDatabaseAccess() throws DbException {
0121:                try {
0122:                    if (ds != null) {
0123:                        // Récupération de la connexion
0124:                        Connection con = ds.getConnection();
0125:
0126:                        // Cas d'une base HSQLDB embarquée
0127:                        if (isEmbeddedHSQLDB(con)) {
0128:                            // Extinction de la base de données
0129:                            con.createStatement().execute("shutdown");
0130:                        }
0131:
0132:                        // Fermeture de la datasource
0133:                        ds.close();
0134:                        ds = null;
0135:                    }
0136:                } catch (SQLException e) {
0137:                    log.info("Incident SQL", e);
0138:                    throw new DbException(
0139:                            "Echec lors de la fermeture de la base de données",
0140:                            e);
0141:                }
0142:            }
0143:
0144:            /**
0145:             * Permet de commencer une transaction.
0146:             * 
0147:             * <p>Une connexion à la base de données est établie. Celle ci
0148:             * doit être validée par la couche appelante par une invocation
0149:             * de <code>endTransaction</code>.</p>
0150:             * 
0151:             * @return le contexte de transaction.
0152:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0153:             */
0154:            protected static DbTransaction beginTransaction()
0155:                    throws DbException {
0156:                try {
0157:                    // Est-on connecté à la BDD ?
0158:                    if (ds == null)
0159:                        throw new DbException(
0160:                                "Database connection not established", null);
0161:                    // Obtention d'une connexion
0162:                    Connection con = ds.getConnection();
0163:                    if (threadLocal.get() != null)
0164:                        throw new Error("Conflicting transaction");
0165:                    threadLocal.set(con);
0166:                    //log.debug("Active : " + ds.getNumActive() + ", Idle : " + ds.getNumIdle() + ", Connexion : " + con);
0167:                    return new DbTransaction(con);
0168:                } catch (SQLException e) {
0169:                    log.info("SQL Exception", e);
0170:                    throw new DbException("Couldn't get a SQL Connection", e);
0171:                }
0172:            }
0173:
0174:            /**
0175:             * Valide une transactrion.
0176:             * @param tx contexte de transaction.
0177:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0178:             */
0179:            protected static void commitTransaction(DbTransaction tx)
0180:                    throws DbException {
0181:                try {
0182:                    tx.getConnection().commit();
0183:                } catch (SQLException e) {
0184:                    log.info("Incident SQL", e);
0185:                    throw new DbException("Echec du commit", e);
0186:                }
0187:            }
0188:
0189:            /**
0190:             * Vérifie si les tables existent dans le modèle.
0191:             * @param tx le contexte de transaction.
0192:             * @return un booléen indiquant si la table spécifiée existe dans le modèle.
0193:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0194:             */
0195:            protected static boolean tablesExist(DbTransaction tx)
0196:                    throws DbException {
0197:                boolean tablesExist = true;
0198:                tablesExist &= tableExists(tx, "COLLABORATOR");
0199:                tablesExist &= tableExists(tx, "CONTRIBUTION");
0200:                tablesExist &= tableExists(tx, "DURATION");
0201:                tablesExist &= tableExists(tx, "TASK");
0202:                return tablesExist;
0203:            }
0204:
0205:            /**
0206:             * Vérifie si une table existe dans le modèle.
0207:             * @param tx le contexte de transaction.
0208:             * @param tableName le nom de la table.
0209:             * @return un booléen indiquant si la table spécifiée existe dans le modèle.
0210:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0211:             */
0212:            private static boolean tableExists(DbTransaction tx,
0213:                    String tableName) throws DbException {
0214:                PreparedStatement pStmt = null;
0215:                try {
0216:                    // Récupération de la connexion
0217:                    Connection con = tx.getConnection();
0218:
0219:                    // Recherche de la table
0220:                    ResultSet rs = con.getMetaData().getTables(null, null,
0221:                            tableName, new String[] { "TABLE" });
0222:
0223:                    // Récupération du résultat
0224:                    boolean exists = rs.next();
0225:
0226:                    // Retour du résultat
0227:                    return exists;
0228:                } catch (SQLException e) {
0229:                    log.info("Incident SQL", e);
0230:                    throw new DbException(
0231:                            "Echec lors du test d'existance de la table '"
0232:                                    + tableName + "'", e);
0233:                } finally {
0234:                    if (pStmt != null)
0235:                        try {
0236:                            pStmt.close();
0237:                        } catch (Throwable ignored) {
0238:                        }
0239:                }
0240:            }
0241:
0242:            /**
0243:             * Crée les tables du modèle de données.
0244:             * @param tx contexte de transaction.
0245:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0246:             */
0247:            protected static void createTables(DbTransaction tx)
0248:                    throws DbException {
0249:                Statement stmt = null;
0250:                try {
0251:                    // Récupération de la connexion
0252:                    Connection con = tx.getConnection();
0253:
0254:                    // Lecture du fichier SQL de création de la BDD
0255:                    String batchName = "sql/"
0256:                            + (isHSQLDB(con) ? "hsqldb.sql" : "mysqldb.sql");
0257:                    InputStream in = DbMgr.class.getResourceAsStream(batchName);
0258:                    String batchContent = null;
0259:                    try {
0260:                        batchContent = StringHelper.fromInputStream(in);
0261:                    } catch (IOException e) {
0262:                        log
0263:                                .info(
0264:                                        "I/O error while loading table creation SQL script.",
0265:                                        e);
0266:                        throw new DbException(
0267:                                "I/O error while loading table creation SQL script.",
0268:                                null);
0269:                    }
0270:
0271:                    // Découpage et exécution du batch
0272:                    stmt = con.createStatement();
0273:                    // TODO Externaliser le découpage du script SQL
0274:                    LineNumberReader lnr = new LineNumberReader(
0275:                            new StringReader(batchContent));
0276:                    StringBuffer buf = new StringBuffer();
0277:                    boolean proceed = true;
0278:                    do {
0279:                        String line = null;
0280:                        // On ne lit dans le flux que si la ligne courante n'est pas
0281:                        // encore totalement traitée
0282:                        if (line == null) {
0283:                            try {
0284:                                line = lnr.readLine();
0285:                            } catch (IOException e) {
0286:                                log
0287:                                        .info(
0288:                                                "Unexpected I/O error while reading memory stream!",
0289:                                                e);
0290:                                throw new DbException(
0291:                                        "Unexpected I/O error while reading memory stream!",
0292:                                        null);
0293:                            }
0294:                            log.debug("Line read : '" + line + "'");
0295:                        }
0296:                        // Si le flux est vide, on sort de la boucle
0297:                        if (line == null) {
0298:                            proceed = false;
0299:                        }
0300:                        // Sinon on traite la ligne
0301:                        else {
0302:                            line = line.trim();
0303:                            // Si la ligne est un commentaire on l'ignore
0304:                            if (line.startsWith("--")) {
0305:                                line = null;
0306:                            } else {
0307:                                // Sinon on regarde si la ligne possède
0308:                                // un point virgule
0309:                                int idx = line.indexOf(';');
0310:                                // Si c'est le cas, on découpe la chaîne et on 
0311:                                // exécute la requête
0312:                                if (idx >= 0) {
0313:                                    buf.append(line.subSequence(0, idx));
0314:                                    line = line.substring(idx);
0315:                                    String sql = buf.toString();
0316:                                    buf.setLength(0);
0317:                                    log.debug(" - sql='" + sql + "'");
0318:                                    if (!"".equals(sql))
0319:                                        stmt.executeUpdate(sql);
0320:                                }
0321:                                // sinon on ajoute la ligne au buffer de requeête
0322:                                else {
0323:                                    buf.append(line);
0324:                                    buf.append('\n');
0325:                                }
0326:                            }
0327:                        }
0328:
0329:                    } while (proceed);
0330:
0331:                    // Test de l'existence des tables
0332:                    if (!tablesExist(tx))
0333:                        throw new DbException(
0334:                                "Database table creation failure", null);
0335:
0336:                    // Fermeture du statement
0337:                    stmt.close();
0338:                    stmt = null;
0339:                } catch (SQLException e) {
0340:                    log.info("Incident SQL", e);
0341:                    throw new DbException("Database table creation failure", e);
0342:                } finally {
0343:                    if (stmt != null)
0344:                        try {
0345:                            stmt.close();
0346:                        } catch (Throwable ignored) {
0347:                        }
0348:                }
0349:            }
0350:
0351:            /**
0352:             * Crée un collaborateur.
0353:             * 
0354:             * @param tx contexte de transaction.
0355:             * @param newCollaborator le collaborateur à créer.
0356:             * @return le collaborateur après création.
0357:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0358:             */
0359:            protected static Collaborator createCollaborator(DbTransaction tx,
0360:                    Collaborator newCollaborator) throws DbException {
0361:                PreparedStatement pStmt = null;
0362:                try {
0363:                    // Récupération de la connexion
0364:                    Connection con = tx.getConnection();
0365:
0366:                    // Préparation de la requête
0367:                    pStmt = con
0368:                            .prepareStatement("insert into collaborator (clb_login, clb_first_name, clb_last_name, clb_is_active) values (?, ?, ?, ?)");
0369:                    pStmt.setString(1, newCollaborator.getLogin());
0370:                    pStmt.setString(2, newCollaborator.getFirstName());
0371:                    pStmt.setString(3, newCollaborator.getLastName());
0372:                    pStmt.setBoolean(4, newCollaborator.getIsActive());
0373:                    pStmt.executeUpdate();
0374:
0375:                    // Récupération de l'identifiant généré
0376:                    long generatedId = getGeneratedId(pStmt);
0377:                    log.debug("Generated id=" + generatedId);
0378:                    newCollaborator.setId(generatedId);
0379:
0380:                    // Fermeture du statement
0381:                    pStmt.close();
0382:                    pStmt = null;
0383:
0384:                    // Retour du résultat
0385:                    return newCollaborator;
0386:                } catch (SQLException e) {
0387:                    log.info("Incident SQL", e);
0388:                    throw new DbException(
0389:                            "Echec lors de la création du collaborateur '"
0390:                                    + newCollaborator.getLogin() + "'", e);
0391:                } finally {
0392:                    if (pStmt != null)
0393:                        try {
0394:                            pStmt.close();
0395:                        } catch (Throwable ignored) {
0396:                        }
0397:                }
0398:            }
0399:
0400:            /**
0401:             * Crée une contribution.
0402:             * 
0403:             * @param tx contexte de transaction.
0404:             * @param newContribution la nouvelle contribution.
0405:             * @return la contribution après création.
0406:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0407:             */
0408:            protected static Contribution createContribution(DbTransaction tx,
0409:                    Contribution newContribution) throws DbException {
0410:                PreparedStatement pStmt = null;
0411:                try {
0412:                    // Récupération de la connexion
0413:                    Connection con = tx.getConnection();
0414:
0415:                    // Préparation de la requête
0416:                    pStmt = con
0417:                            .prepareStatement("insert into contribution (ctb_year, ctb_month, ctb_day, ctb_contributor, ctb_task, ctb_duration) values (?, ?, ?, ?, ?, ?)");
0418:                    pStmt.setInt(1, newContribution.getYear());
0419:                    pStmt.setInt(2, newContribution.getMonth());
0420:                    pStmt.setInt(3, newContribution.getDay());
0421:                    pStmt.setLong(4, newContribution.getContributorId());
0422:                    pStmt.setLong(5, newContribution.getTaskId());
0423:                    pStmt.setLong(6, newContribution.getDurationId());
0424:                    pStmt.executeUpdate();
0425:
0426:                    // Fermeture du statement
0427:                    pStmt.close();
0428:                    pStmt = null;
0429:
0430:                    // Retour du résultat
0431:                    return newContribution;
0432:                } catch (SQLException e) {
0433:                    log.info("Incident SQL", e);
0434:                    throw new DbException(
0435:                            "Echec lors de la création d'une contribution", e);
0436:                } finally {
0437:                    if (pStmt != null)
0438:                        try {
0439:                            pStmt.close();
0440:                        } catch (Throwable ignored) {
0441:                        }
0442:                }
0443:            }
0444:
0445:            /**
0446:             * Crée une contribution.
0447:             * 
0448:             * @param tx contexte de transaction.
0449:             * @param newDuration la nouvelle durée.
0450:             * @return la durée après création.
0451:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0452:             */
0453:            protected static Duration createDuration(DbTransaction tx,
0454:                    Duration newDuration) throws DbException {
0455:                PreparedStatement pStmt = null;
0456:                try {
0457:                    // Récupération de la connexion
0458:                    Connection con = tx.getConnection();
0459:
0460:                    // Préparation de la requête
0461:                    pStmt = con
0462:                            .prepareStatement("insert into duration (dur_id, dur_is_active) values (?, ?)");
0463:                    pStmt.setLong(1, newDuration.getId());
0464:                    pStmt.setBoolean(2, newDuration.getIsActive());
0465:                    pStmt.executeUpdate();
0466:
0467:                    // Fermeture du statement
0468:                    pStmt.close();
0469:                    pStmt = null;
0470:
0471:                    // Retour du résultat
0472:                    return newDuration;
0473:                } catch (SQLException e) {
0474:                    log.info("Incident SQL", e);
0475:                    throw new DbException(
0476:                            "Echec lors de la création de la durée : '"
0477:                                    + newDuration + "'", e);
0478:                } finally {
0479:                    if (pStmt != null)
0480:                        try {
0481:                            pStmt.close();
0482:                        } catch (Throwable ignored) {
0483:                        }
0484:                }
0485:            }
0486:
0487:            /**
0488:             * Crée une tache.
0489:             * 
0490:             * <p>La tache parent peut être nulle pour indiquer que la nouvelle tache
0491:             * est une tache racine.</p>
0492:             * 
0493:             * @param tx le contexte de transaction.
0494:             * @param parentTask la tache parent accueillant la nouvelle tache.
0495:             * @param newTask la nouvelle tache.
0496:             * @return la tache après création.
0497:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0498:             */
0499:            protected static Task createTask(DbTransaction tx, Task parentTask,
0500:                    Task newTask) throws DbException {
0501:                PreparedStatement pStmt = null;
0502:                try {
0503:                    // Récupération de la connexion
0504:                    Connection con = tx.getConnection();
0505:
0506:                    // Mise à jour du chemin de la tâche
0507:                    String parentPath = parentTask == null ? "" : parentTask
0508:                            .getFullPath();
0509:                    newTask.setPath(parentPath);
0510:
0511:                    // Génération du numéro de la tâche
0512:                    byte taskNumber = newTaskNumber(tx, parentPath);
0513:                    newTask.setNumber(taskNumber);
0514:
0515:                    // Préparation de la requête
0516:                    pStmt = con
0517:                            .prepareStatement("insert into task (tsk_path, tsk_number, tsk_code, tsk_name, tsk_budget, tsk_initial_cons, tsk_todo, tsk_comment) values (?, ?, ?, ?, ?, ?, ?, ?)");
0518:                    pStmt.setString(1, newTask.getPath());
0519:                    pStmt.setByte(2, newTask.getNumber());
0520:                    pStmt.setString(3, newTask.getCode());
0521:                    pStmt.setString(4, newTask.getName());
0522:                    pStmt.setLong(5, newTask.getBudget());
0523:                    pStmt.setLong(6, newTask.getInitiallyConsumed());
0524:                    pStmt.setLong(7, newTask.getTodo());
0525:                    pStmt.setString(8, newTask.getComment());
0526:                    pStmt.executeUpdate();
0527:
0528:                    // Récupération de l'identifiant généré
0529:                    long generatedId = getGeneratedId(pStmt);
0530:                    log.debug("Generated id=" + generatedId);
0531:                    newTask.setId(generatedId);
0532:
0533:                    // Fermeture du ResultSet
0534:                    pStmt.close();
0535:                    pStmt = null;
0536:
0537:                    // Retour du résultat
0538:                    return newTask;
0539:                } catch (SQLException e) {
0540:                    log.info("Incident SQL", e);
0541:                    throw new DbException(
0542:                            "Echec lors de la création de la tache '"
0543:                                    + newTask.getName() + "'", e);
0544:                } finally {
0545:                    if (pStmt != null)
0546:                        try {
0547:                            pStmt.close();
0548:                        } catch (Throwable ignored) {
0549:                        }
0550:                }
0551:            }
0552:
0553:            /**
0554:             * Vérifie si la durée est utilisée en base.
0555:             * @param tx le contexte de transaction.
0556:             * @param duration la durée à vérifier.
0557:             * @return un booléen indiquant si la durée est utilisée.
0558:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0559:             */
0560:            protected static boolean durationIsUsed(DbTransaction tx,
0561:                    Duration duration) throws DbException {
0562:                PreparedStatement pStmt = null;
0563:                ResultSet rs = null;
0564:                try {
0565:                    // Récupération de la connexion
0566:                    Connection con = tx.getConnection();
0567:
0568:                    // Préparation de la requête
0569:                    pStmt = con
0570:                            .prepareStatement("select count(*) from contribution where ctb_duration=?");
0571:                    pStmt.setLong(1, duration.getId());
0572:
0573:                    // Exécution de la requête
0574:                    rs = pStmt.executeQuery();
0575:
0576:                    // Préparation du résultat
0577:                    if (!rs.next())
0578:                        throw new DbException("Nothing returned by the query",
0579:                                null);
0580:                    boolean durationIsUsed = rs.getInt(1) > 0;
0581:
0582:                    // Fermeture du statement
0583:                    pStmt.close();
0584:                    pStmt = null;
0585:
0586:                    // Retour du résultat
0587:                    return durationIsUsed;
0588:                } catch (SQLException e) {
0589:                    log.info("Incident SQL", e);
0590:                    throw new DbException(
0591:                            "Echec lors de la vérification de l'utilisation de la durée '"
0592:                                    + duration + "'", e);
0593:                } finally {
0594:                    if (pStmt != null)
0595:                        try {
0596:                            pStmt.close();
0597:                        } catch (Throwable ignored) {
0598:                        }
0599:                }
0600:            }
0601:
0602:            /**
0603:             * Ferme une transactrion.
0604:             * @param tx le contexte de transaction.
0605:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0606:             */
0607:            protected static void endTransaction(DbTransaction tx)
0608:                    throws DbException {
0609:                try {
0610:                    tx.getConnection().close();
0611:                } catch (SQLException e) {
0612:                    log.info("Incident SQL", e);
0613:                    throw new DbException(
0614:                            "Echec lors de la cloture de la connexion", e);
0615:                }
0616:                threadLocal.set(null);
0617:            }
0618:
0619:            /**
0620:             * @param tx le contexte de transaction.
0621:             * @param collaboratorId l'identifiant du collaborateur recherché.
0622:             * @return le collaborateur dont l'identifiant est spécifié.
0623:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0624:             */
0625:            protected static Collaborator getCollaborator(DbTransaction tx,
0626:                    long collaboratorId) throws DbException {
0627:                PreparedStatement pStmt = null;
0628:                ResultSet rs = null;
0629:                try {
0630:                    // Récupération de la connexion
0631:                    Connection con = tx.getConnection();
0632:
0633:                    // Préparation de la requête
0634:                    pStmt = con
0635:                            .prepareStatement("select clb_id, clb_login, clb_first_name, clb_last_name, clb_is_active from collaborator where clb_id=?");
0636:                    pStmt.setLong(1, collaboratorId);
0637:
0638:                    // Exécution de la requête
0639:                    rs = pStmt.executeQuery();
0640:
0641:                    // Préparation du résultat
0642:                    Collaborator collaborator = null;
0643:                    if (rs.next())
0644:                        collaborator = rsToCollaborator(rs);
0645:
0646:                    // Fermeture du statement
0647:                    pStmt.close();
0648:                    pStmt = null;
0649:
0650:                    // Retour du résultat
0651:                    return collaborator;
0652:                } catch (SQLException e) {
0653:                    log.info("Incident SQL", e);
0654:                    throw new DbException(
0655:                            "Echec lors de la récupération du collaborateur d'identifiant '"
0656:                                    + collaboratorId + "'", e);
0657:                } finally {
0658:                    if (pStmt != null)
0659:                        try {
0660:                            pStmt.close();
0661:                        } catch (Throwable ignored) {
0662:                        }
0663:                }
0664:            }
0665:
0666:            /**
0667:             * Convertit le résultat d'une requête en collaborateur.
0668:             * @param rs le result set.
0669:             * @return le collaborateur.
0670:             * @throws SQLException levé en cas de problème SQL.
0671:             */
0672:            private static Collaborator rsToCollaborator(ResultSet rs)
0673:                    throws SQLException {
0674:                Collaborator collaborator = new Collaborator();
0675:                collaborator.setId(rs.getLong(1));
0676:                collaborator.setLogin(rs.getString(2));
0677:                collaborator.setFirstName(rs.getString(3));
0678:                collaborator.setLastName(rs.getString(4));
0679:                collaborator.setIsActive(rs.getBoolean(5));
0680:                return collaborator;
0681:            }
0682:
0683:            /**
0684:             * @param tx le contexte de transaction.
0685:             * @param login l'identifiant de connexion du collaborateur recherché.
0686:             * @return le collaborateur dont l'identifiant de connexion est spécifié.
0687:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0688:             */
0689:            protected static Collaborator getCollaborator(DbTransaction tx,
0690:                    String login) throws DbException {
0691:                PreparedStatement pStmt = null;
0692:                ResultSet rs = null;
0693:                try {
0694:                    // Récupération de la connexion
0695:                    Connection con = tx.getConnection();
0696:
0697:                    // Préparation de la requête
0698:                    pStmt = con
0699:                            .prepareStatement("select clb_id, clb_login, clb_first_name, clb_last_name, clb_is_active from collaborator where clb_login=?");
0700:                    pStmt.setString(1, login);
0701:
0702:                    // Exécution de la requête
0703:                    rs = pStmt.executeQuery();
0704:
0705:                    // Préparation du résultat
0706:                    Collaborator collaborator = null;
0707:                    if (rs.next())
0708:                        collaborator = rsToCollaborator(rs);
0709:
0710:                    // Fermeture du ResultSet
0711:                    pStmt.close();
0712:                    pStmt = null;
0713:
0714:                    // Retour du résultat
0715:                    return collaborator;
0716:                } catch (SQLException e) {
0717:                    log.info("Incident SQL", e);
0718:                    throw new DbException(
0719:                            "Echec lors de la récupération ddu collaborateur de login '"
0720:                                    + login + "'", e);
0721:                } finally {
0722:                    if (pStmt != null)
0723:                        try {
0724:                            pStmt.close();
0725:                        } catch (Throwable ignored) {
0726:                        }
0727:                }
0728:            }
0729:
0730:            /**
0731:             * @param tx le contexte de transaction.
0732:             * @param orderByClauseFieldIndex index de l'attribut utilisé pour le tri.
0733:             * @param ascendantSort booléen indiquant si le tri doit être ascendant.
0734:             * @param onlyActiveCollaborators booléen indiquant si l'on ne doit retourner que
0735:             * 		les collaborateurs actifs.
0736:             * @return la liste des collaborateurs.
0737:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0738:             */
0739:            protected static Collaborator[] getCollaborators(DbTransaction tx,
0740:                    int orderByClauseFieldIndex, boolean ascendantSort,
0741:                    boolean onlyActiveCollaborators) throws DbException {
0742:                PreparedStatement pStmt = null;
0743:                ResultSet rs = null;
0744:                try {
0745:                    // Récupération de la connexion
0746:                    Connection con = tx.getConnection();
0747:
0748:                    // Préparation de la requête
0749:                    StringBuffer request = new StringBuffer(
0750:                            "select clb_id, clb_login, clb_first_name, clb_last_name, clb_is_active from collaborator ");
0751:                    if (onlyActiveCollaborators)
0752:                        request.append("where clb_is_active=?");
0753:                    request.append("order by ");
0754:                    switch (orderByClauseFieldIndex) {
0755:                    case Collaborator.ID_FIELD_IDX:
0756:                        request.append("clb_id");
0757:                        break;
0758:                    case Collaborator.LOGIN_FIELD_IDX:
0759:                        request.append("clb_login");
0760:                        break;
0761:                    case Collaborator.FIRST_NAME_FIELD_IDX:
0762:                        request.append("clb_first_name");
0763:                        break;
0764:                    case Collaborator.LAST_NAME_FIELD_IDX:
0765:                        request.append("clb_last_name");
0766:                        break;
0767:                    case Collaborator.IS_ACTIVE_FIELD_IDX:
0768:                        request.append("clb_is_active");
0769:                        break;
0770:                    default:
0771:                        throw new DbException("Unknown field index '"
0772:                                + orderByClauseFieldIndex + "'.", null);
0773:                    }
0774:                    request.append(ascendantSort ? " asc" : " desc");
0775:                    pStmt = con.prepareStatement(request.toString());
0776:                    if (onlyActiveCollaborators)
0777:                        pStmt.setBoolean(1, true);
0778:
0779:                    // Exécution de la requête
0780:                    rs = pStmt.executeQuery();
0781:
0782:                    // Recherche des sous-taches
0783:                    ArrayList list = new ArrayList();
0784:                    while (rs.next())
0785:                        list.add(rsToCollaborator(rs));
0786:
0787:                    // Fermeture du ResultSet
0788:                    pStmt.close();
0789:                    pStmt = null;
0790:
0791:                    // Retour du résultat
0792:                    log.debug("  => found " + list.size() + " entrie(s)");
0793:                    return (Collaborator[]) list.toArray(new Collaborator[list
0794:                            .size()]);
0795:                } catch (SQLException e) {
0796:                    log.info("Incident SQL", e);
0797:                    throw new DbException(
0798:                            "Echec lors de la récupération des collaborateurs'",
0799:                            e);
0800:                } finally {
0801:                    if (pStmt != null)
0802:                        try {
0803:                            pStmt.close();
0804:                        } catch (Throwable ignored) {
0805:                        }
0806:                }
0807:            }
0808:
0809:            /**
0810:             * @param tx le contexte de transaction.
0811:             * @param contributor le collaborateur associé aux contributions.
0812:             * @param task la tache associée aux contributions.
0813:             * @param fromDate la date de départ.
0814:             * @param toDate la date de fin.
0815:             * @return la liste des contributions associées aux paramètres spécifiés.
0816:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0817:             */
0818:            protected static Contribution[] getContributions(DbTransaction tx,
0819:                    Collaborator contributor, Task task, Calendar fromDate,
0820:                    Calendar toDate) throws DbException {
0821:                log.debug("getContributions(" + contributor + ", " + task
0822:                        + ", " + sdf.format(fromDate.getTime()) + ", "
0823:                        + sdf.format(toDate.getTime()) + ")");
0824:                PreparedStatement pStmt = null;
0825:                ResultSet rs = null;
0826:                try {
0827:                    // Récupération de la connexion
0828:                    Connection con = tx.getConnection();
0829:
0830:                    // Préparation de la requête
0831:                    pStmt = con
0832:                            .prepareStatement("select ctb_year, ctb_month, ctb_day, ctb_contributor, ctb_task, ctb_duration from contribution where ctb_contributor=? and ctb_task=? and ctb_year*10000 + ( ctb_month*100 + ctb_day ) between ? and ?");
0833:                    pStmt.setLong(1, contributor.getId());
0834:                    pStmt.setLong(2, task.getId());
0835:                    pStmt.setString(3, sdf.format(fromDate.getTime()));
0836:                    pStmt.setString(4, sdf.format(toDate.getTime()));
0837:
0838:                    // Exécution de la requête
0839:                    rs = pStmt.executeQuery();
0840:
0841:                    // Extraction du résultat
0842:                    Contribution[] result = rsToContributions(rs);
0843:
0844:                    // Fermeture du ResultSet
0845:                    pStmt.close();
0846:                    pStmt = null;
0847:
0848:                    // Retour du résultat
0849:                    return result;
0850:                } catch (SQLException e) {
0851:                    log.info("Incident SQL", e);
0852:                    throw new DbException(
0853:                            "Echec lors de la récupération des contributions",
0854:                            e);
0855:                } finally {
0856:                    if (pStmt != null)
0857:                        try {
0858:                            pStmt.close();
0859:                        } catch (Throwable ignored) {
0860:                        }
0861:                }
0862:            }
0863:
0864:            /**
0865:             * Extrait les contributions du resultat de la requête SQL.
0866:             * @param rs le résultat de la requête SQL.
0867:             * @return les contributions extraites.
0868:             * @throws SQLException levé en cas d'incident avec la base de données.
0869:             */
0870:            private static Contribution[] rsToContributions(ResultSet rs)
0871:                    throws SQLException {
0872:                // Recherche des sous-taches
0873:                ArrayList list = new ArrayList();
0874:                while (rs.next()) {
0875:                    // Préparation du résultat
0876:                    Contribution contribution = new Contribution();
0877:                    contribution.setYear(rs.getInt(1));
0878:                    contribution.setMonth(rs.getInt(2));
0879:                    contribution.setDay(rs.getInt(3));
0880:                    contribution.setContributorId(rs.getInt(4));
0881:                    contribution.setTaskId(rs.getInt(5));
0882:                    contribution.setDurationId(rs.getLong(6));
0883:                    list.add(contribution);
0884:                }
0885:                log.debug("  => found " + list.size() + " entrie(s)");
0886:                return (Contribution[]) list.toArray(new Contribution[list
0887:                        .size()]);
0888:            }
0889:
0890:            /**
0891:             * Retourne les contributions associées aux paramètres spécifiés.
0892:             * 
0893:             * <p>Tous les paramètres sont facultatifs. Chaque paramètre spécifié agît
0894:             * comme un filtre sur le résultat. A l'inverse, l'omission d'un paramètre
0895:             * provoque l'inclusion de toutes les contributions, quelque soit leurs
0896:             * valeurs pour l'attribut considéré.</p>
0897:             * 
0898:             * <p>La spécification des paramètres répond aux mêmes règles que pour la
0899:             * méthode <code>getContributionsSum</code>.</p>
0900:             * 
0901:             * @param tx le contexte de transaction.
0902:             * @param task la tâche associée aux contributions (facultative).
0903:             * @param contributor le collaborateur associé aux contributions (facultatif).
0904:             * @param year l'année (facultative).
0905:             * @param month le mois (facultatif).
0906:             * @param day le jour (facultatif).
0907:             * @return les contributions.
0908:             * @throws DbException levé en cas d'incident technique d'accès à la base.
0909:             * 
0910:             * @see jfb.tools.activitymgr.core.DbMgr#getContributionsSum(DbTransaction, Task, Collaborator, Integer, Integer, Integer)
0911:             */
0912:            protected static Contribution[] getContributions(DbTransaction tx,
0913:                    Task task, Collaborator contributor, Integer year,
0914:                    Integer month, Integer day) throws DbException {
0915:                log.debug("getContributions(" + task + ", " + contributor
0916:                        + ", " + year + ", " + month + ", " + day + ")");
0917:                PreparedStatement pStmt = null;
0918:                ResultSet rs = null;
0919:                try {
0920:                    // Récupération de la connexion
0921:                    Connection con = tx.getConnection();
0922:
0923:                    StringBuffer baseRequest = new StringBuffer(
0924:                            "select ctb_year, ctb_month, ctb_day, ctb_contributor, ctb_task, ctb_duration from contribution, task where ctb_task=tsk_id");
0925:                    String orderByClause = " order by ctb_year, ctb_month, ctb_day, tsk_path, tsk_number, ctb_contributor, ctb_duration";
0926:                    // Cas ou la tache n'est pas spécifiée
0927:                    if (task == null) {
0928:                        // Préparation de la requête
0929:                        completeContributionRequest(baseRequest, contributor,
0930:                                year, month, day);
0931:                        baseRequest.append(orderByClause);
0932:                        String request = baseRequest.toString();
0933:                        pStmt = con.prepareStatement(request);
0934:                        completeContributionReqParams(pStmt, 1, contributor,
0935:                                year, month, day);
0936:                    }
0937:                    // Si la tache n'admet pas de sous-taches, le cumul de 
0938:                    // budget, de consommé initial, de reste à faire sont
0939:                    // égaux à ceux de la tache
0940:                    else if (task.getSubTasksCount() == 0) {
0941:                        // Préparation de la requête
0942:                        baseRequest.append(" and tsk_id=?");
0943:                        completeContributionRequest(baseRequest, contributor,
0944:                                year, month, day);
0945:                        baseRequest.append(orderByClause);
0946:                        String request = baseRequest.toString();
0947:                        pStmt = con.prepareStatement(request);
0948:                        pStmt.setLong(1, task.getId());
0949:                        log.debug(" taskId=" + task.getId());
0950:                        completeContributionReqParams(pStmt, 2, contributor,
0951:                                year, month, day);
0952:                    }
0953:                    // Sinon, il faut calculer
0954:                    else {
0955:                        // Paramètre pour la clause 'LIKE'
0956:                        String pathLike = task.getFullPath() + "%";
0957:
0958:                        // Préparation de la requête
0959:                        baseRequest.append(" and tsk_path like ?");
0960:                        completeContributionRequest(baseRequest, contributor,
0961:                                year, month, day);
0962:                        baseRequest.append(orderByClause);
0963:                        String request = baseRequest.toString();
0964:                        pStmt = con.prepareStatement(request);
0965:                        pStmt.setString(1, pathLike);
0966:                        completeContributionReqParams(pStmt, 2, contributor,
0967:                                year, month, day);
0968:                    }
0969:
0970:                    // Exécution de la requête
0971:                    log.debug("Request : " + baseRequest);
0972:                    rs = pStmt.executeQuery();
0973:
0974:                    // Extraction du résultat
0975:                    Contribution[] result = rsToContributions(rs);
0976:
0977:                    // Fermeture du statement
0978:                    pStmt.close();
0979:                    pStmt = null;
0980:
0981:                    // Retour du résultat
0982:                    return result;
0983:                } catch (SQLException e) {
0984:                    log.info("Incident SQL", e);
0985:                    throw new DbException(
0986:                            "Echec lors de la récupération des contributions",
0987:                            e);
0988:                } finally {
0989:                    try {
0990:                        if (pStmt != null)
0991:                            pStmt.close();
0992:                    } catch (Throwable ignored) {
0993:                    }
0994:                }
0995:            }
0996:
0997:            /**
0998:             * Calcule le nombre des contributions associée aux paramètres spécifiés.
0999:             * 
1000:             * <p>Tous les paramètres sont facultatifs. Chaque paramètre spécifié agît
1001:             * comme un filtre sur le résultat. A l'inverse, l'omission d'un paramètre
1002:             * provoque l'inclusion de toutes les contributions, quelque soit leurs
1003:             * valeurs pour l'attribut considéré.</p>
1004:             * 
1005:             * <p>En spécifiant la tache X, on connaîtra la somme des contribution pour
1006:             * la taches X. En ne spécifiant pas de tache, la somme sera effectuée quelque
1007:             * soit les tâches.</p>
1008:             * 
1009:             * @param tx le contexte de transaction.
1010:             * @param task la tâche associée aux contributions (facultative).
1011:             * @param contributor le collaborateur associé aux contributions (facultatif).
1012:             * @param year l'année (facultative).
1013:             * @param month le mois (facultatif).
1014:             * @param day le jour (facultatif).
1015:             * @return la seomme des contributions.
1016:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1017:             */
1018:            protected static long getContributionsNb(DbTransaction tx,
1019:                    Task task, Collaborator contributor, Integer year,
1020:                    Integer month, Integer day) throws DbException {
1021:                log.debug("getContributionsSum(" + task + ", " + contributor
1022:                        + ", " + year + ", " + month + ", " + day + ")");
1023:                return getContributionsAggregation(tx, "count(ctb_duration)",
1024:                        task, contributor, year, month, day);
1025:            }
1026:
1027:            /**
1028:             * Calcule le cumuls des consommations associees aux contributions pour
1029:             * les paramètres spécifiés.
1030:             * 
1031:             * <p>Tous les paramètres sont facultatifs. Chaque paramètre spécifié agît
1032:             * comme un filtre sur le résultat. A l'inverse, l'omission d'un paramètre
1033:             * provoque l'inclusion de toutes les contributions, quelque soit leurs
1034:             * valeurs pour l'attribut considéré.</p>
1035:             * 
1036:             * <p>En spécifiant la tache X, on connaîtra la somme des contribution pour
1037:             * la taches X. En ne spécifiant pas de tache, la somme sera effectuée quelque
1038:             * soit les tâches.</p>
1039:             * 
1040:             * @param tx le contexte de transaction.
1041:             * @param task la tâche associée aux contributions (facultative).
1042:             * @param contributor le collaborateur associé aux contributions (facultatif).
1043:             * @param year l'année (facultative).
1044:             * @param month le mois (facultatif).
1045:             * @param day le jour (facultatif).
1046:             * @return la seomme des contributions.
1047:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1048:             */
1049:            protected static long getContributionsSum(DbTransaction tx,
1050:                    Task task, Collaborator contributor, Integer year,
1051:                    Integer month, Integer day) throws DbException {
1052:                log.debug("getContributionsSum(" + task + ", " + contributor
1053:                        + ", " + year + ", " + month + ", " + day + ")");
1054:                return getContributionsAggregation(tx, "sum(ctb_duration)",
1055:                        task, contributor, year, month, day);
1056:            }
1057:
1058:            /**
1059:             * Calcule une aggregation associee aux contributions pour les paramètres
1060:             * spécifiés.
1061:             * 
1062:             * <p>Tous les paramètres sont facultatifs. Chaque paramètre spécifié agît
1063:             * comme un filtre sur le résultat. A l'inverse, l'omission d'un paramètre
1064:             * provoque l'inclusion de toutes les contributions, quelque soit leurs
1065:             * valeurs pour l'attribut considéré.</p>
1066:             * 
1067:             * <p>En spécifiant la tache X, on connaîtra la somme des contribution pour
1068:             * la taches X. En ne spécifiant pas de tache, la somme sera effectuée quelque
1069:             * soit les tâches.</p>
1070:             * 
1071:             * @param tx le contexte de transaction.
1072:             * @param aggregation la chaîne représentant l'aggrégation (ex: <code>sum(ctb_contribution)</code>).
1073:             * @param task la tâche associée aux contributions (facultative).
1074:             * @param contributor le collaborateur associé aux contributions (facultatif).
1075:             * @param year l'année (facultative).
1076:             * @param month le mois (facultatif).
1077:             * @param day le jour (facultatif).
1078:             * @return la seomme des contributions.
1079:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1080:             */
1081:            private static long getContributionsAggregation(DbTransaction tx,
1082:                    String aggregation, Task task, Collaborator contributor,
1083:                    Integer year, Integer month, Integer day)
1084:                    throws DbException {
1085:                log.debug("getContributionsSum(" + task + ", " + contributor
1086:                        + ", " + year + ", " + month + ", " + day + ")");
1087:                PreparedStatement pStmt = null;
1088:                ResultSet rs = null;
1089:                try {
1090:                    // Récupération de la connexion
1091:                    Connection con = tx.getConnection();
1092:
1093:                    StringBuffer baseRequest = new StringBuffer("select ")
1094:                            .append(aggregation)
1095:                            .append(
1096:                                    " from contribution, task where ctb_task=tsk_id");
1097:                    // Cas ou la tache n'est pas spécifiée
1098:                    if (task == null) {
1099:                        // Préparation de la requête
1100:                        completeContributionRequest(baseRequest, contributor,
1101:                                year, month, day);
1102:                        String request = baseRequest.toString();
1103:                        pStmt = con.prepareStatement(request);
1104:                        completeContributionReqParams(pStmt, 1, contributor,
1105:                                year, month, day);
1106:                    }
1107:                    // Si la tache n'admet pas de sous-taches, le cumul de 
1108:                    // budget, de consommé initial, de reste à faire sont
1109:                    // égaux à ceux de la tache
1110:                    else if (task.getSubTasksCount() == 0) {
1111:                        // Préparation de la requête
1112:                        baseRequest.append(" and tsk_id=?");
1113:                        completeContributionRequest(baseRequest, contributor,
1114:                                year, month, day);
1115:                        String request = baseRequest.toString();
1116:                        pStmt = con.prepareStatement(request);
1117:                        pStmt.setLong(1, task.getId());
1118:                        log.debug(" taskId=" + task.getId());
1119:                        completeContributionReqParams(pStmt, 2, contributor,
1120:                                year, month, day);
1121:                    }
1122:                    // Sinon, il faut calculer
1123:                    else {
1124:                        // Paramètre pour la clause 'LIKE'
1125:                        String pathLike = task.getFullPath() + "%";
1126:
1127:                        // Préparation de la requête
1128:                        baseRequest.append(" and tsk_path like ?");
1129:                        completeContributionRequest(baseRequest, contributor,
1130:                                year, month, day);
1131:                        String request = baseRequest.toString();
1132:                        pStmt = con.prepareStatement(request);
1133:                        pStmt.setString(1, pathLike);
1134:                        completeContributionReqParams(pStmt, 2, contributor,
1135:                                year, month, day);
1136:                    }
1137:
1138:                    // Exécution de la requête
1139:                    log.debug("Request : " + baseRequest);
1140:                    rs = pStmt.executeQuery();
1141:                    if (!rs.next())
1142:                        throw new DbException(
1143:                                "Nothing returned from this query", null);
1144:                    long agregation = rs.getLong(1);
1145:
1146:                    // Fermeture du statement
1147:                    pStmt.close();
1148:                    pStmt = null;
1149:
1150:                    // Retour du résultat
1151:                    log.info("agregation=" + agregation);
1152:                    return agregation;
1153:                } catch (SQLException e) {
1154:                    log.info("Incident SQL", e);
1155:                    throw new DbException(
1156:                            "Echec lors de la récupération des cumuls", e);
1157:                } finally {
1158:                    try {
1159:                        if (pStmt != null)
1160:                            pStmt.close();
1161:                    } catch (Throwable ignored) {
1162:                    }
1163:                }
1164:            }
1165:
1166:            /**
1167:             * @param tx le contexte de transaction.
1168:             * @param durationId l'identifiant de la durée.
1169:             * @return la durée.
1170:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1171:             */
1172:            protected static Duration getDuration(DbTransaction tx,
1173:                    long durationId) throws DbException {
1174:                PreparedStatement pStmt = null;
1175:                ResultSet rs = null;
1176:                try {
1177:                    // Récupération de la connexion
1178:                    Connection con = tx.getConnection();
1179:
1180:                    // Préparation de la requête
1181:                    pStmt = con
1182:                            .prepareStatement("select dur_id, dur_is_active from duration where dur_id=?");
1183:                    pStmt.setLong(1, durationId);
1184:
1185:                    // Exécution de la requête
1186:                    rs = pStmt.executeQuery();
1187:
1188:                    // Reécupération du résultat
1189:                    Duration duration = null;
1190:                    if (rs.next())
1191:                        duration = rsToDuration(rs);
1192:
1193:                    // Fermeture du ResultSet
1194:                    pStmt.close();
1195:                    pStmt = null;
1196:
1197:                    // Retour du résultat
1198:                    return duration;
1199:                } catch (SQLException e) {
1200:                    log.info("Incident SQL", e);
1201:                    throw new DbException(
1202:                            "Echec lors de la récupération dde la durée '"
1203:                                    + durationId + "'", e);
1204:                } finally {
1205:                    if (pStmt != null)
1206:                        try {
1207:                            pStmt.close();
1208:                        } catch (Throwable ignored) {
1209:                        }
1210:                }
1211:            }
1212:
1213:            /**
1214:             * @param tx le contexte de transaction.
1215:             * @param onlyActiveCollaborators booléen indiquant si l'on ne doit retourner que
1216:             * 		les collaborateurs actifs.
1217:             * @return la liste des durées.
1218:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1219:             */
1220:            protected static Duration[] getDurations(DbTransaction tx,
1221:                    boolean onlyActiveCollaborators) throws DbException {
1222:                PreparedStatement pStmt = null;
1223:                ResultSet rs = null;
1224:                try {
1225:                    // Récupération de la connexion
1226:                    Connection con = tx.getConnection();
1227:
1228:                    // Préparation de la requête
1229:                    StringBuffer request = new StringBuffer(
1230:                            "select dur_id, dur_is_active from duration ");
1231:                    if (onlyActiveCollaborators)
1232:                        request.append("where dur_is_active=?");
1233:                    request.append("order by dur_id asc");
1234:                    pStmt = con.prepareStatement(request.toString());
1235:                    if (onlyActiveCollaborators)
1236:                        pStmt.setBoolean(1, true);
1237:
1238:                    // Exécution de la requête
1239:                    rs = pStmt.executeQuery();
1240:
1241:                    // Recherche des sous-taches
1242:                    ArrayList list = new ArrayList();
1243:                    while (rs.next())
1244:                        list.add(rsToDuration(rs));
1245:
1246:                    // Fermeture du ResultSet
1247:                    pStmt.close();
1248:                    pStmt = null;
1249:
1250:                    // Retour du résultat
1251:                    return (Duration[]) list.toArray(new Duration[list.size()]);
1252:                } catch (SQLException e) {
1253:                    log.info("Incident SQL", e);
1254:                    throw new DbException(
1255:                            "Echec lors de la récupération des durées'", e);
1256:                } finally {
1257:                    if (pStmt != null)
1258:                        try {
1259:                            pStmt.close();
1260:                        } catch (Throwable ignored) {
1261:                        }
1262:                }
1263:            }
1264:
1265:            /**
1266:             * Convertit le résultat d'une requête en durée.
1267:             * @param rs le result set.
1268:             * @return la durée.
1269:             * @throws SQLException levé en cas de problème SQL.
1270:             */
1271:            private static Duration rsToDuration(ResultSet rs)
1272:                    throws SQLException {
1273:                Duration duration = new Duration();
1274:                duration.setId(rs.getLong(1));
1275:                duration.setIsActive(rs.getBoolean(2));
1276:                return duration;
1277:            }
1278:
1279:            /**
1280:             * @param tx le contexte de transaction.
1281:             * @param task la tache dont on veut connaitre la tache parent.
1282:             * @return la tache parent d'une tache spécifiée.
1283:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1284:             */
1285:            protected static Task getParentTask(DbTransaction tx, Task task)
1286:                    throws DbException {
1287:                Task parentTask = null;
1288:                String parentTaskFullPath = task.getPath();
1289:                // Si le chemin est vide, la tache parent est nulle (tache racine)
1290:                if (parentTaskFullPath != null
1291:                        && !"".equals(parentTaskFullPath)) {
1292:                    // Extraction du chemin et du numéro de la tache recherchée
1293:                    log.debug("Fullpath='" + parentTaskFullPath + "'");
1294:                    String path = parentTaskFullPath.substring(0,
1295:                            parentTaskFullPath.length() - 2);
1296:                    byte number = StringHelper.toByte(parentTaskFullPath
1297:                            .substring(parentTaskFullPath.length() - 2));
1298:                    log.debug(" => path=" + path);
1299:                    log.debug(" => number=" + number);
1300:
1301:                    // Recherche de la tache
1302:                    parentTask = getTask(tx, path, number);
1303:                }
1304:                // Retour du résultat
1305:                return parentTask;
1306:            }
1307:
1308:            /**
1309:             * @param tx le contexte de transaction.
1310:             * @param path le chemin dont on veut connaître les taches.
1311:             * @return la liste des taches associées à un chemin donné.
1312:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1313:             */
1314:            protected static Task[] getTasks(DbTransaction tx, String path)
1315:                    throws DbException {
1316:                PreparedStatement pStmt = null;
1317:                ResultSet rs = null;
1318:                try {
1319:                    // Récupération de la connexion
1320:                    Connection con = tx.getConnection();
1321:
1322:                    // Préparation de la requête
1323:                    pStmt = con
1324:                            .prepareStatement("select tsk_id from task where tsk_path=? order by tsk_number");
1325:                    pStmt.setString(1, path);
1326:
1327:                    // Exécution de la requête
1328:                    rs = pStmt.executeQuery();
1329:
1330:                    // Recherche des sous-taches
1331:                    ArrayList list = new ArrayList();
1332:                    while (rs.next()) {
1333:                        long taskId = rs.getLong(1);
1334:                        Task task = getTask(tx, taskId);
1335:                        list.add(task);
1336:                    }
1337:
1338:                    // Fermeture du ResultSet
1339:                    pStmt.close();
1340:                    pStmt = null;
1341:
1342:                    // Retour du résultat
1343:                    log.debug("  => found " + list.size() + " entrie(s)");
1344:                    return (Task[]) list.toArray(new Task[list.size()]);
1345:                } catch (SQLException e) {
1346:                    log.info("Incident SQL", e);
1347:                    throw new DbException(
1348:                            "Echec lors de la récupération des sous taches de chemin '"
1349:                                    + path + "'", e);
1350:                } finally {
1351:                    if (pStmt != null)
1352:                        try {
1353:                            pStmt.close();
1354:                        } catch (Throwable ignored) {
1355:                        }
1356:                }
1357:            }
1358:
1359:            /**
1360:             * @param tx le contexte de transaction.
1361:             * @param parentTask la tache parent dont on veut connaitre les sous-taches.
1362:             * @return la liste des sous-taches.
1363:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1364:             */
1365:            protected static Task[] getSubtasks(DbTransaction tx,
1366:                    Task parentTask) throws DbException {
1367:                // Récupération du chemin à partir de la tache parent
1368:                String fullpath = parentTask == null ? "" : parentTask
1369:                        .getFullPath();
1370:                log.debug("Looking for tasks with path='" + fullpath + "'");
1371:                return getTasks(tx, fullpath);
1372:            }
1373:
1374:            /**
1375:             * Retourn la liste des taches correspondant au filtre de recherche spécifié.
1376:             * @param tx le contexte de transaction.
1377:             * @param filter le filtre de recherche.
1378:             * @return la liste des taches correspondant au filtre de recherche spécifié.
1379:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1380:             */
1381:            protected static Task[] getTasks(DbTransaction tx,
1382:                    TaskSearchFilter filter) throws DbException {
1383:                PreparedStatement pStmt = null;
1384:                ResultSet rs = null;
1385:                try {
1386:                    // Récupération de la connexion
1387:                    Connection con = tx.getConnection();
1388:
1389:                    // Préparation de la requête
1390:                    StringBuffer request = new StringBuffer(
1391:                            "select tsk_id from task where ");
1392:                    // Ajout du nom de champ
1393:                    switch (filter.getFieldIndex()) {
1394:                    case TaskSearchFilter.TASK_NAME_FIELD_IDX:
1395:                        request.append("tsk_name");
1396:                        break;
1397:                    case TaskSearchFilter.TASK_CODE_FIELD_IDX:
1398:                        request.append("tsk_code");
1399:                        break;
1400:                    default:
1401:                        throw new DbException("Unknown field index '"
1402:                                + filter.getFieldIndex() + "'.", null);
1403:                    }
1404:                    // Ajout du critère de comparaison
1405:                    switch (filter.getCriteriaIndex()) {
1406:                    case TaskSearchFilter.IS_EQUAL_TO_CRITERIA_IDX:
1407:                        request.append("=?");
1408:                        break;
1409:                    case TaskSearchFilter.STARTS_WITH_CRITERIA_IDX:
1410:                    case TaskSearchFilter.ENDS_WITH_CRITERIA_IDX:
1411:                    case TaskSearchFilter.CONTAINS_WITH_CRITERIA_IDX:
1412:                        request.append(" like ?");
1413:                        break;
1414:                    default:
1415:                        throw new DbException("Unknown criteria index '"
1416:                                + filter.getCriteriaIndex() + "'.", null);
1417:                    }
1418:                    // Préparation de la requête
1419:                    log.debug("Search request : '" + request + "'");
1420:                    pStmt = con.prepareStatement(request.toString());
1421:                    String parameter = null;
1422:                    switch (filter.getCriteriaIndex()) {
1423:                    case TaskSearchFilter.IS_EQUAL_TO_CRITERIA_IDX:
1424:                        parameter = filter.getFieldValue();
1425:                        break;
1426:                    case TaskSearchFilter.STARTS_WITH_CRITERIA_IDX:
1427:                        parameter = filter.getFieldValue() + "%";
1428:                        break;
1429:                    case TaskSearchFilter.ENDS_WITH_CRITERIA_IDX:
1430:                        parameter = "%" + filter.getFieldValue();
1431:                        break;
1432:                    case TaskSearchFilter.CONTAINS_WITH_CRITERIA_IDX:
1433:                        parameter = "%" + filter.getFieldValue() + "%";
1434:                        break;
1435:                    default:
1436:                        throw new DbException("Unknown criteria index '"
1437:                                + filter.getCriteriaIndex() + "'.", null);
1438:                    }
1439:                    log.debug("Search parameter : '" + parameter + "'");
1440:                    pStmt.setString(1, parameter);
1441:
1442:                    // Exécution de la requête
1443:                    rs = pStmt.executeQuery();
1444:
1445:                    // Récupération du résultat
1446:                    ArrayList list = new ArrayList();
1447:                    while (rs.next()) {
1448:                        long taskId = rs.getLong(1);
1449:                        Task task = getTask(tx, taskId);
1450:                        list.add(task);
1451:                    }
1452:
1453:                    // Fermeture du ResultSet
1454:                    pStmt.close();
1455:                    pStmt = null;
1456:
1457:                    // Préparation du résultat
1458:                    Task[] tasks = (Task[]) list.toArray(new Task[list.size()]);
1459:
1460:                    // On trie les taches manuellement car le tri base de données
1461:                    // pose un problème dans la mesure ou la BDD considère le champ
1462:                    // tsk_path comme numérique pour le tri ce qui pose un pb
1463:                    // Ex : 
1464:                    // ROOT        (path : 01)
1465:                    //   +- T1     (path : 0101)
1466:                    //   |  +- T11 (path : 010101)
1467:                    //   |  +- T12 (path : 010102) 
1468:                    //   +- T2     (path : 0102)
1469:                    // Si on ramène l'ensemble des sous taches de ROOT, on voudrait avoir
1470:                    // dans l'ordre T1, T11, T12, T2
1471:                    // Avec un tri base de donnée, on obtiendrait T1, T2, T11, T12 ; T2 ne se
1472:                    // trouve pas ou on l'attend, ceci en raison du fait qu'en comparaison 
1473:                    // numérique 0102 est < à 010101 et à 010102. Par contre, en comparaison 
1474:                    // de chaînes (en java), on a bien 0102 > 010101 et 010102.
1475:                    Arrays.sort(tasks, new Comparator() {
1476:                        public int compare(Object o1, Object o2) {
1477:                            Task t1 = (Task) o1;
1478:                            Task t2 = (Task) o2;
1479:                            return t1.getFullPath().compareTo(t2.getFullPath());
1480:                        }
1481:
1482:                    });
1483:
1484:                    // Retour du résultat
1485:                    return tasks;
1486:                } catch (SQLException e) {
1487:                    log.info("Incident SQL", e);
1488:                    throw new DbException(
1489:                            "Unexpected error while searching tasks", e);
1490:                } finally {
1491:                    if (pStmt != null)
1492:                        try {
1493:                            pStmt.close();
1494:                        } catch (Throwable ignored) {
1495:                        }
1496:                }
1497:            }
1498:
1499:            /**
1500:             * @param tx le contexte de transaction.
1501:             * @param taskId l'identifiant de la tache recherchée.
1502:             * @return la tache dont l'identifiant est spécifié.
1503:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1504:             */
1505:            protected static Task getTask(DbTransaction tx, long taskId)
1506:                    throws DbException {
1507:                PreparedStatement pStmt = null;
1508:                ResultSet rs = null;
1509:                try {
1510:                    // Récupération de la connexion
1511:                    Connection con = tx.getConnection();
1512:
1513:                    // Préparation de la requête
1514:                    pStmt = con
1515:                            .prepareStatement("select tsk_path, tsk_number, tsk_code, tsk_name, tsk_budget, tsk_initial_cons, tsk_todo, tsk_comment from task where tsk_id=?");
1516:                    pStmt.setLong(1, taskId);
1517:
1518:                    // Exécution de la requête
1519:                    rs = pStmt.executeQuery();
1520:
1521:                    // Préparation du résultat
1522:                    Task task = null;
1523:                    if (rs.next()) {
1524:                        task = new Task();
1525:                        task.setId(taskId);
1526:                        task.setPath(rs.getString(1));
1527:                        task.setNumber(rs.getByte(2));
1528:                        task.setCode(rs.getString(3));
1529:                        task.setName(rs.getString(4));
1530:                        task.setBudget(rs.getLong(5));
1531:                        task.setInitiallyConsumed(rs.getLong(6));
1532:                        task.setTodo(rs.getLong(7));
1533:                        task.setComment(rs.getString(8));
1534:                    }
1535:                    // Fermeture du ResultSet
1536:                    pStmt.close();
1537:                    pStmt = null;
1538:
1539:                    // Si la tache existe bien
1540:                    if (task != null) {
1541:                        // Recherche du nombre de sous-taches
1542:                        String taskFullPath = task.getFullPath();
1543:                        pStmt = con
1544:                                .prepareStatement("select count(*) from task where tsk_path=?");
1545:                        pStmt.setString(1, taskFullPath);
1546:
1547:                        // Exécution de la requête
1548:                        rs = pStmt.executeQuery();
1549:                        if (rs.next()) {
1550:                            int subTasksCount = rs.getInt(1);
1551:                            task.setSubTasksCount(subTasksCount);
1552:                        }
1553:                        // Fermeture du ResultSet
1554:                        pStmt.close();
1555:                        pStmt = null;
1556:                    }
1557:
1558:                    // Retour du résultat
1559:                    return task;
1560:                } catch (SQLException e) {
1561:                    log.info("Incident SQL", e);
1562:                    throw new DbException(
1563:                            "Echec lors de la récupération de la tache d'identifiant '"
1564:                                    + taskId + "'", e);
1565:                } finally {
1566:                    if (pStmt != null)
1567:                        try {
1568:                            pStmt.close();
1569:                        } catch (Throwable ignored) {
1570:                        }
1571:                }
1572:            }
1573:
1574:            /**
1575:             * @param tx le contexte de transaction.
1576:             * @param taskPath le chemin de la tache recherchée.
1577:             * @param taskNumber le numéro de la tache recherchée.
1578:             * @return la tache dont le chemin et le numéro sont spécifiés.
1579:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1580:             */
1581:            protected static Task getTask(DbTransaction tx, String taskPath,
1582:                    byte taskNumber) throws DbException {
1583:                log.debug("getTask(" + taskPath + ", " + taskNumber + ")");
1584:                PreparedStatement pStmt = null;
1585:                ResultSet rs = null;
1586:                try {
1587:                    // Récupération de la connexion
1588:                    Connection con = tx.getConnection();
1589:
1590:                    // Préparation de la requête
1591:                    pStmt = con
1592:                            .prepareStatement("select tsk_id from task where tsk_path=? and tsk_number=?");
1593:                    pStmt.setString(1, taskPath);
1594:                    pStmt.setByte(2, taskNumber);
1595:
1596:                    // Exécution de la requête
1597:                    rs = pStmt.executeQuery();
1598:
1599:                    // Préparation du résultat
1600:                    Task task = null;
1601:                    if (rs.next()) {
1602:                        long taskId = rs.getLong(1);
1603:                        task = getTask(tx, taskId);
1604:                    }
1605:                    // Fermeture du ResultSet
1606:                    pStmt.close();
1607:                    pStmt = null;
1608:
1609:                    // Retour du résultat
1610:                    log.debug("task = " + task);
1611:                    return task;
1612:                } catch (SQLException e) {
1613:                    log.info("Incident SQL", e);
1614:                    throw new DbException(
1615:                            "Echec lors de la récupération de la tache N° "
1616:                                    + taskNumber + " du chemin '" + taskPath
1617:                                    + "'", e);
1618:                } finally {
1619:                    if (pStmt != null)
1620:                        try {
1621:                            pStmt.close();
1622:                        } catch (Throwable ignored) {
1623:                        }
1624:                }
1625:            }
1626:
1627:            /**
1628:             * @param tx le contexte de transaction.
1629:             * @param taskPath le chemin de la tache recherchée.
1630:             * @param taskCode le code de la tache recherchée.
1631:             * @return la tache dont le code et la tache parent sont spécifiés.
1632:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1633:             */
1634:            protected static Task getTask(DbTransaction tx, String taskPath,
1635:                    String taskCode) throws DbException {
1636:                PreparedStatement pStmt = null;
1637:                ResultSet rs = null;
1638:                try {
1639:                    // Récupération de la connexion
1640:                    Connection con = tx.getConnection();
1641:
1642:                    // Préparation de la requête
1643:                    pStmt = con
1644:                            .prepareStatement("select tsk_id from task where tsk_path=? and tsk_code=?");
1645:                    pStmt.setString(1, taskPath);
1646:                    pStmt.setString(2, taskCode);
1647:
1648:                    // Exécution de la requête
1649:                    rs = pStmt.executeQuery();
1650:
1651:                    // Préparation du résultat
1652:                    Task task = null;
1653:                    if (rs.next()) {
1654:                        long taskId = rs.getLong(1);
1655:                        task = getTask(tx, taskId);
1656:                    }
1657:                    // Fermeture du ResultSet
1658:                    pStmt.close();
1659:                    pStmt = null;
1660:
1661:                    // Retour du résultat
1662:                    return task;
1663:                } catch (SQLException e) {
1664:                    log.info("Incident SQL", e);
1665:                    throw new DbException(
1666:                            "Echec lors de la récupération de la tache de code '"
1667:                                    + taskCode + "'", e);
1668:                } finally {
1669:                    if (pStmt != null)
1670:                        try {
1671:                            pStmt.close();
1672:                        } catch (Throwable ignored) {
1673:                        }
1674:                }
1675:            }
1676:
1677:            /**
1678:             * @param tx le contexte de transaction.
1679:             * @param collaborator le collaborateur.
1680:             * @param fromDate date de début.
1681:             * @param toDate date de fin.
1682:             * @return la liste de taches associées au collaborateur entre les 2 dates spécifiées.
1683:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1684:             */
1685:            protected static Task[] getTasks(DbTransaction tx,
1686:                    Collaborator collaborator, Calendar fromDate,
1687:                    Calendar toDate) throws DbException {
1688:                log.debug("getTasks(" + collaborator + ", "
1689:                        + sdf.format(fromDate.getTime()) + ", "
1690:                        + sdf.format(toDate.getTime()) + ")");
1691:                PreparedStatement pStmt = null;
1692:                ResultSet rs = null;
1693:                try {
1694:                    // Récupération de la connexion
1695:                    Connection con = tx.getConnection();
1696:
1697:                    // Préparation de la requête
1698:                    pStmt = con
1699:                            .prepareStatement("select distinct ctb_task, tsk_path, tsk_number from contribution, task where ctb_task=tsk_id and ctb_contributor=? and ctb_year*10000 + ( ctb_month*100 + ctb_day ) between ? and ? order by tsk_path, tsk_number");
1700:                    pStmt.setLong(1, collaborator.getId());
1701:                    pStmt.setString(2, sdf.format(fromDate.getTime()));
1702:                    pStmt.setString(3, sdf.format(toDate.getTime()));
1703:
1704:                    // Exécution de la requête
1705:                    rs = pStmt.executeQuery();
1706:
1707:                    // Recherche des sous-taches
1708:                    ArrayList list = new ArrayList();
1709:                    while (rs.next()) {
1710:                        long taskId = rs.getLong(1);
1711:                        Task task = getTask(tx, taskId);
1712:                        list.add(task);
1713:                    }
1714:
1715:                    // Fermeture du ResultSet
1716:                    pStmt.close();
1717:                    pStmt = null;
1718:
1719:                    // Retour du résultat
1720:                    log.debug("  => found " + list.size() + " entrie(s)");
1721:                    return (Task[]) list.toArray(new Task[list.size()]);
1722:                } catch (SQLException e) {
1723:                    log.info("Incident SQL", e);
1724:                    throw new DbException(
1725:                            "Echec lors de la récupération des taches associées à un collaborateur",
1726:                            e);
1727:                } finally {
1728:                    if (pStmt != null)
1729:                        try {
1730:                            pStmt.close();
1731:                        } catch (Throwable ignored) {
1732:                        }
1733:                }
1734:            }
1735:
1736:            /**
1737:             * @param tx le contexte de transaction.
1738:             * @param task la tâche pour laquelle on souhaite connaître les totaux.
1739:             * @return les totaux associés à une tache (consommé, etc.).
1740:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1741:             */
1742:            protected static TaskSums getTaskSums(DbTransaction tx, Task task)
1743:                    throws DbException {
1744:                // TODO Factoriser cette méthose avec getContributionsSum
1745:                PreparedStatement pStmt = null;
1746:                ResultSet rs = null;
1747:                try {
1748:                    // Récupération de la connexion
1749:                    Connection con = tx.getConnection();
1750:
1751:                    // Préparation du résultat
1752:                    TaskSums taskSums = new TaskSums();
1753:
1754:                    // Si la tache n'admet pas de sous-taches, le cumul de 
1755:                    // budget, de consommé initial, de reste à faire sont
1756:                    // égaux à ceux de la tache
1757:                    if (task != null && task.getSubTasksCount() == 0) {
1758:                        taskSums.setBudgetSum(task.getBudget());
1759:                        taskSums.setInitiallyConsumedSum(task
1760:                                .getInitiallyConsumed());
1761:                        taskSums.setTodoSum(task.getTodo());
1762:
1763:                        // Calcul du consommé
1764:                        pStmt = con
1765:                                .prepareStatement("select sum(ctb_duration), count(ctb_duration) from contribution, task where ctb_task=tsk_id and tsk_id=?");
1766:                        pStmt.setLong(1, task.getId());
1767:                        rs = pStmt.executeQuery();
1768:                        if (!rs.next())
1769:                            throw new DbException(
1770:                                    "Nothing returned from this query", null);
1771:                        taskSums.setConsumedSum(rs.getLong(1));
1772:                        taskSums.setContributionsNb(rs.getLong(2));
1773:                        pStmt.close();
1774:                        pStmt = null;
1775:                    }
1776:                    // Sinon, il faut calculer
1777:                    else {
1778:                        // Paramètre pour la clause 'LIKE'
1779:                        String pathLike = (task == null ? "" : task
1780:                                .getFullPath())
1781:                                + "%";
1782:
1783:                        // Calcul des cumuls
1784:                        pStmt = con
1785:                                .prepareStatement("select sum(tsk_budget), sum(tsk_initial_cons), sum(tsk_todo) from task where tsk_path like ?");
1786:                        pStmt.setString(1, pathLike);
1787:                        rs = pStmt.executeQuery();
1788:                        if (!rs.next())
1789:                            throw new DbException(
1790:                                    "Nothing returned from this query", null);
1791:                        taskSums.setBudgetSum(rs.getLong(1));
1792:                        taskSums.setInitiallyConsumedSum(rs.getLong(2));
1793:                        taskSums.setTodoSum(rs.getLong(3));
1794:                        pStmt.close();
1795:                        pStmt = null;
1796:
1797:                        // Calcul du consommé
1798:                        pStmt = con
1799:                                .prepareStatement("select sum(ctb_duration), count(ctb_duration) from contribution, task where ctb_task=tsk_id and tsk_path like ?");
1800:                        pStmt.setString(1, pathLike);
1801:                        rs = pStmt.executeQuery();
1802:                        if (!rs.next())
1803:                            throw new DbException(
1804:                                    "Nothing returned from this query", null);
1805:                        taskSums.setConsumedSum(rs.getLong(1));
1806:                        taskSums.setContributionsNb(rs.getLong(2));
1807:                        pStmt.close();
1808:                        pStmt = null;
1809:
1810:                    }
1811:                    // Retour du résultat
1812:                    return taskSums;
1813:                } catch (SQLException e) {
1814:                    log.info("Incident SQL", e);
1815:                    throw new DbException(
1816:                            "Echec lors de la récupération des cumuls pour la tache d'identifiant '"
1817:                                    + task.getId() + "'", e);
1818:                } finally {
1819:                    try {
1820:                        if (pStmt != null)
1821:                            pStmt.close();
1822:                    } catch (Throwable ignored) {
1823:                    }
1824:                }
1825:            }
1826:
1827:            /**
1828:             * Supprime un collaborateur.
1829:             * @param tx le contexte de transaction.
1830:             * @param collaborator le collaborateur à supprimer.
1831:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1832:             */
1833:            protected static void removeCollaborator(DbTransaction tx,
1834:                    Collaborator collaborator) throws DbException {
1835:                PreparedStatement pStmt = null;
1836:                try {
1837:                    // Récupération de la connexion
1838:                    Connection con = tx.getConnection();
1839:
1840:                    // Préparation de la requête
1841:                    pStmt = con
1842:                            .prepareStatement("delete from collaborator where clb_id=?");
1843:                    pStmt.setLong(1, collaborator.getId());
1844:
1845:                    // Exécution de la requête
1846:                    int removed = pStmt.executeUpdate();
1847:                    if (removed != 1)
1848:                        throw new SQLException("No row was deleted");
1849:
1850:                    // Fermeture du statement
1851:                    pStmt.close();
1852:                    pStmt = null;
1853:
1854:                } catch (SQLException e) {
1855:                    log.info("Incident SQL", e);
1856:                    throw new DbException(
1857:                            "Echec lors de la suppression du collaborateur '"
1858:                                    + collaborator.getLogin() + "'", e);
1859:                } finally {
1860:                    if (pStmt != null)
1861:                        try {
1862:                            pStmt.close();
1863:                        } catch (Throwable ignored) {
1864:                        }
1865:                }
1866:            }
1867:
1868:            /**
1869:             * Supprime une contribution.
1870:             * @param tx le contexte de transaction.
1871:             * @param contribution la contribution à supprimer.
1872:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1873:             */
1874:            protected static void removeContribution(DbTransaction tx,
1875:                    Contribution contribution) throws DbException {
1876:                PreparedStatement pStmt = null;
1877:                try {
1878:                    // Récupération de la connexion
1879:                    Connection con = tx.getConnection();
1880:
1881:                    // Préparation de la requête
1882:                    pStmt = con
1883:                            .prepareStatement("delete from contribution where ctb_year=? and ctb_month=? and ctb_day=? and ctb_contributor=? and ctb_task=?");
1884:                    pStmt.setInt(1, contribution.getYear());
1885:                    pStmt.setInt(2, contribution.getMonth());
1886:                    pStmt.setInt(3, contribution.getDay());
1887:                    pStmt.setLong(4, contribution.getContributorId());
1888:                    pStmt.setLong(5, contribution.getTaskId());
1889:
1890:                    // Exécution de la requête
1891:                    int removed = pStmt.executeUpdate();
1892:                    if (removed != 1)
1893:                        throw new SQLException("No row was deleted");
1894:
1895:                    // Fermeture du statement
1896:                    pStmt.close();
1897:                    pStmt = null;
1898:                } catch (SQLException e) {
1899:                    log.info("Incident SQL", e);
1900:                    throw new DbException(
1901:                            "Echec lors de la suppression d'une contribution",
1902:                            e);
1903:                } finally {
1904:                    if (pStmt != null)
1905:                        try {
1906:                            pStmt.close();
1907:                        } catch (Throwable ignored) {
1908:                        }
1909:                }
1910:            }
1911:
1912:            /**
1913:             * Supprime une durée du référentiel de durées.
1914:             * @param tx le contexte de transaction.
1915:             * @param duration la durée à supprimer.
1916:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1917:             */
1918:            protected static void removeDuration(DbTransaction tx,
1919:                    Duration duration) throws DbException {
1920:                PreparedStatement pStmt = null;
1921:                try {
1922:                    // Récupération de la connexion
1923:                    Connection con = tx.getConnection();
1924:
1925:                    // Préparation de la requête
1926:                    pStmt = con
1927:                            .prepareStatement("delete from duration where dur_id=?");
1928:                    pStmt.setLong(1, duration.getId());
1929:
1930:                    // Exécution de la requête
1931:                    int removed = pStmt.executeUpdate();
1932:                    if (removed != 1)
1933:                        throw new SQLException("No row was deleted");
1934:
1935:                    // Fermeture du statement
1936:                    pStmt.close();
1937:                    pStmt = null;
1938:                } catch (SQLException e) {
1939:                    log.info("Incident SQL", e);
1940:                    throw new DbException(
1941:                            "Echec lors de la suppression de la durée '"
1942:                                    + duration + "'", e);
1943:                } finally {
1944:                    if (pStmt != null)
1945:                        try {
1946:                            pStmt.close();
1947:                        } catch (Throwable ignored) {
1948:                        }
1949:                }
1950:            }
1951:
1952:            /**
1953:             * Supprime une tache.
1954:             * @param tx le contexte de transaction.
1955:             * @param task la tache à supprimer.
1956:             * @throws DbException levé en cas d'incident technique d'accès à la base.
1957:             */
1958:            protected static void removeTask(DbTransaction tx, Task task)
1959:                    throws DbException {
1960:                PreparedStatement pStmt = null;
1961:                try {
1962:                    // Récupération de la connexion
1963:                    Connection con = tx.getConnection();
1964:
1965:                    // Control sur les sous taches
1966:                    Task[] subTasks = DbMgr.getSubtasks(tx, task);
1967:                    for (int i = 0; i < subTasks.length; i++) {
1968:                        DbMgr.removeTask(tx, subTasks[i]);
1969:                    }
1970:
1971:                    // Préparation de la requête
1972:                    pStmt = con
1973:                            .prepareStatement("delete from task where tsk_id=?");
1974:                    pStmt.setLong(1, task.getId());
1975:
1976:                    // Exécution de la requête
1977:                    int removed = pStmt.executeUpdate();
1978:                    if (removed != 1)
1979:                        throw new SQLException("No row was deleted");
1980:
1981:                    // Fermeture du statement
1982:                    pStmt.close();
1983:                    pStmt = null;
1984:                } catch (SQLException e) {
1985:                    log.info("Incident SQL", e);
1986:                    throw new DbException(
1987:                            "Echec lors de la suppression de la tache '" + task
1988:                                    + "'", e);
1989:                } finally {
1990:                    if (pStmt != null)
1991:                        try {
1992:                            pStmt.close();
1993:                        } catch (Throwable ignored) {
1994:                        }
1995:                }
1996:            }
1997:
1998:            /**
1999:             * Annule le modifications effectuées dans le cadre d'une transactrion.
2000:             * @param tx contexte de transaction.
2001:             * @throws DbException levé en cas d'incident technique d'accès à la base.
2002:             */
2003:            protected static void rollbackTransaction(DbTransaction tx)
2004:                    throws DbException {
2005:                try {
2006:                    tx.getConnection().rollback();
2007:                } catch (SQLException e) {
2008:                    log.info("Incident SQL", e);
2009:                    throw new DbException("Echec du rollback", e);
2010:                }
2011:            }
2012:
2013:            /**
2014:             * Modifie les attributs d'un collaborateur.
2015:             * @param tx contexte de transaction.
2016:             * @param collaborator le collaborateur à modifier.
2017:             * @return le collaborateur modifié.
2018:             * @throws DbException levé en cas d'incident technique d'accès à la base.
2019:             */
2020:            protected static Collaborator updateCollaborator(DbTransaction tx,
2021:                    Collaborator collaborator) throws DbException {
2022:                PreparedStatement pStmt = null;
2023:                try {
2024:                    // Récupération de la connexion
2025:                    Connection con = tx.getConnection();
2026:
2027:                    // Préparation de la requête
2028:                    pStmt = con
2029:                            .prepareStatement("update collaborator set clb_login=?, clb_first_name=?, clb_last_name=?, clb_is_active=? where clb_id=?");
2030:                    pStmt.setString(1, collaborator.getLogin());
2031:                    pStmt.setString(2, collaborator.getFirstName());
2032:                    pStmt.setString(3, collaborator.getLastName());
2033:                    pStmt.setBoolean(4, collaborator.getIsActive());
2034:                    pStmt.setLong(5, collaborator.getId());
2035:
2036:                    // Exécution de la requête
2037:                    int updated = pStmt.executeUpdate();
2038:                    if (updated != 1)
2039:                        throw new SQLException("No row was updated");
2040:
2041:                    // Fermeture du statement
2042:                    pStmt.close();
2043:                    pStmt = null;
2044:
2045:                    // Retour du résultat
2046:                    return collaborator;
2047:                } catch (SQLException e) {
2048:                    log.info("Incident SQL", e);
2049:                    throw new DbException(
2050:                            "Echec lors de la mise à jour du collaborateur '"
2051:                                    + collaborator.getLogin() + "'", e);
2052:                } finally {
2053:                    if (pStmt != null)
2054:                        try {
2055:                            pStmt.close();
2056:                        } catch (Throwable ignored) {
2057:                        }
2058:                }
2059:            }
2060:
2061:            /**
2062:             * Modifie les attributs d'une contribution.
2063:             * @param tx contexte de transaction.
2064:             * @param contribution la contribution à modifier.
2065:             * @return la contribution modifiée.
2066:             * @throws DbException levé en cas d'incident technique d'accès à la base.
2067:             */
2068:            protected static Contribution updateContribution(DbTransaction tx,
2069:                    Contribution contribution) throws DbException {
2070:                PreparedStatement pStmt = null;
2071:                try {
2072:                    // Récupération de la connexion
2073:                    Connection con = tx.getConnection();
2074:
2075:                    // Préparation de la requête
2076:                    pStmt = con
2077:                            .prepareStatement("update contribution set ctb_duration=? where ctb_year=? and ctb_month=? and ctb_day=? and ctb_contributor=? and ctb_task=?");
2078:                    pStmt.setLong(1, contribution.getDurationId());
2079:                    pStmt.setInt(2, contribution.getYear());
2080:                    pStmt.setInt(3, contribution.getMonth());
2081:                    pStmt.setInt(4, contribution.getDay());
2082:                    pStmt.setLong(5, contribution.getContributorId());
2083:                    pStmt.setLong(6, contribution.getTaskId());
2084:
2085:                    // Exécution de la requête
2086:                    int updated = pStmt.executeUpdate();
2087:                    if (updated != 1)
2088:                        throw new SQLException("No row was updated");
2089:
2090:                    // Fermeture du statement
2091:                    pStmt.close();
2092:                    pStmt = null;
2093:
2094:                    // Retour du résultat
2095:                    return contribution;
2096:                } catch (SQLException e) {
2097:                    log.info("Incident SQL", e);
2098:                    throw new DbException(
2099:                            "Echec lors de la mise à jour d'une contribution",
2100:                            e);
2101:                } finally {
2102:                    if (pStmt != null)
2103:                        try {
2104:                            pStmt.close();
2105:                        } catch (Throwable ignored) {
2106:                        }
2107:                }
2108:            }
2109:
2110:            /**
2111:             * Met à jour une durée.
2112:             * @param tx le contexte de transaction.
2113:             * @param duration la durée à mettre à jour.
2114:             * @return la durée mise à jour.
2115:             * @throws DbException levé en cas d'incident technique d'accès à la base.
2116:             */
2117:            protected static Duration updateDuration(DbTransaction tx,
2118:                    Duration duration) throws DbException {
2119:                PreparedStatement pStmt = null;
2120:                try {
2121:                    // Récupération de la connexion
2122:                    Connection con = tx.getConnection();
2123:
2124:                    // Préparation de la requête
2125:                    pStmt = con
2126:                            .prepareStatement("update duration set dur_is_active=? where dur_id=?");
2127:                    pStmt.setBoolean(1, duration.getIsActive());
2128:                    pStmt.setLong(2, duration.getId());
2129:
2130:                    // Exécution de la requête
2131:                    int updated = pStmt.executeUpdate();
2132:                    if (updated != 1)
2133:                        throw new SQLException("No row was updated");
2134:
2135:                    // Fermeture du statement
2136:                    pStmt.close();
2137:                    pStmt = null;
2138:
2139:                    // Retour du résultat
2140:                    return duration;
2141:                } catch (SQLException e) {
2142:                    log.info("Incident SQL", e);
2143:                    throw new DbException(
2144:                            "Echec lors de la mise à jour de la durée '"
2145:                                    + duration.getId() + "'", e);
2146:                } finally {
2147:                    if (pStmt != null)
2148:                        try {
2149:                            pStmt.close();
2150:                        } catch (Throwable ignored) {
2151:                        }
2152:                }
2153:            }
2154:
2155:            /**
2156:             * Change la tache d'une contribution.
2157:             * @param tx contexte de transaction.
2158:             * @param contribution la contribution.
2159:             * @param newContributionTask la tache à affecter.
2160:             * @return la contribution mise à jour.
2161:             * @throws DbException levé en cas d'incident technique d'accès à la base.
2162:             */
2163:            protected static Contribution changeContributionTask(
2164:                    DbTransaction tx, Contribution contribution,
2165:                    Task newContributionTask) throws DbException {
2166:                PreparedStatement pStmt = null;
2167:                try {
2168:                    // Récupération de la connexion
2169:                    Connection con = tx.getConnection();
2170:
2171:                    // Préparation de la requête
2172:                    pStmt = con
2173:                            .prepareStatement("update contribution set ctb_task=? where ctb_year=? and ctb_month=? and ctb_day=? and ctb_contributor=? and ctb_task=?");
2174:                    pStmt.setLong(1, newContributionTask.getId());
2175:                    pStmt.setInt(2, contribution.getYear());
2176:                    pStmt.setInt(3, contribution.getMonth());
2177:                    pStmt.setInt(4, contribution.getDay());
2178:                    pStmt.setLong(5, contribution.getContributorId());
2179:                    pStmt.setLong(6, contribution.getTaskId());
2180:
2181:                    // Exécution de la requête
2182:                    int updated = pStmt.executeUpdate();
2183:                    if (updated != 1)
2184:                        throw new SQLException("No row was updated");
2185:
2186:                    // Mise à jour de la contribution
2187:                    contribution.setTaskId(newContributionTask.getId());
2188:
2189:                    // Fermeture du statement
2190:                    pStmt.close();
2191:                    pStmt = null;
2192:
2193:                    // Retour du résultat
2194:                    return contribution;
2195:                } catch (SQLException e) {
2196:                    log.info("Incident SQL", e);
2197:                    throw new DbException(
2198:                            "Echec lors de la mise à jour d'une contribution",
2199:                            e);
2200:                } finally {
2201:                    if (pStmt != null)
2202:                        try {
2203:                            pStmt.close();
2204:                        } catch (Throwable ignored) {
2205:                        }
2206:                }
2207:            }
2208:
2209:            /**
2210:             * Modifie les attributs d'une tache.
2211:             * @param tx contexte de transaction.
2212:             * @param task la tache à modifier.
2213:             * @return la tache modifiée.
2214:             * @throws DbException levé en cas d'incident technique d'accès à la base.
2215:             */
2216:            protected static Task updateTask(DbTransaction tx, Task task)
2217:                    throws DbException {
2218:                PreparedStatement pStmt = null;
2219:                try {
2220:                    // Récupération de la connexion
2221:                    Connection con = tx.getConnection();
2222:
2223:                    // Préparation de la requête
2224:                    pStmt = con
2225:                            .prepareStatement("update task set tsk_path=?, tsk_number=?, tsk_code=?, tsk_name=?, tsk_budget=?, tsk_initial_cons=?, tsk_todo=?, tsk_comment=? where tsk_id=?");
2226:                    pStmt.setString(1, task.getPath());
2227:                    pStmt.setByte(2, task.getNumber());
2228:                    pStmt.setString(3, task.getCode());
2229:                    pStmt.setString(4, task.getName());
2230:                    pStmt.setLong(5, task.getBudget());
2231:                    pStmt.setLong(6, task.getInitiallyConsumed());
2232:                    pStmt.setLong(7, task.getTodo());
2233:                    pStmt.setString(8, task.getComment());
2234:                    pStmt.setLong(9, task.getId());
2235:
2236:                    // Exécution de la requête
2237:                    int updated = pStmt.executeUpdate();
2238:                    if (updated != 1)
2239:                        throw new SQLException("No row was updated");
2240:
2241:                    // Fermeture du statement
2242:                    pStmt.close();
2243:                    pStmt = null;
2244:
2245:                    // Retour du résultat
2246:                    return task;
2247:                } catch (SQLException e) {
2248:                    log.info("Incident SQL", e);
2249:                    throw new DbException(
2250:                            "Echec lors de la mise à jour de la tache '"
2251:                                    + task.getName() + "'", e);
2252:                } finally {
2253:                    if (pStmt != null)
2254:                        try {
2255:                            pStmt.close();
2256:                        } catch (Throwable ignored) {
2257:                        }
2258:                }
2259:            }
2260:
2261:            /**
2262:             * Complete la requete de calcul de la somme des contributions.
2263:             * @param requestBase buffer utilisé pour la construction de la requête.
2264:             * @param contributor le collaborateur ayant contribué à la tache (facultatif).
2265:             * @param year l'année (facultative)
2266:             * @param month le mois (facultatif)
2267:             * @param day le jour (facultatif)
2268:             */
2269:            private static void completeContributionRequest(
2270:                    StringBuffer requestBase, Collaborator contributor,
2271:                    Integer year, Integer month, Integer day) {
2272:                if (contributor != null)
2273:                    requestBase.append(" and ctb_contributor=?");
2274:                if (year != null)
2275:                    requestBase.append(" and ctb_year=?");
2276:                if (month != null)
2277:                    requestBase.append(" and ctb_month=?");
2278:                if (day != null)
2279:                    requestBase.append(" and ctb_day=?");
2280:                log.debug("built request : " + requestBase.toString());
2281:            }
2282:
2283:            /**
2284:             * Complete les paramètres de la requete de calcul de la somme des contributions.
2285:             * @param pStmt le statement.
2286:             * @param startIndex
2287:             * @param contributor le collaborateur ayant contribué à la tache (facultatif).
2288:             * @param year l'année (facultative)
2289:             * @param month le mois (facultatif)
2290:             * @param day le jour (facultatif)
2291:             * @throws SQLException levé en cas d'incident avec la base de données.
2292:             */
2293:            private static void completeContributionReqParams(
2294:                    PreparedStatement pStmt, int startIndex,
2295:                    Collaborator contributor, Integer year, Integer month,
2296:                    Integer day) throws SQLException {
2297:                int idx = startIndex;
2298:                log.debug("contributorId="
2299:                        + (contributor != null ? String.valueOf(contributor
2300:                                .getId()) : "null"));
2301:                log.debug("year=" + year);
2302:                log.debug("month=" + month);
2303:                log.debug("day=" + day);
2304:                if (contributor != null)
2305:                    pStmt.setLong(idx++, contributor.getId());
2306:                if (year != null)
2307:                    pStmt.setInt(idx++, year.intValue());
2308:                if (month != null)
2309:                    pStmt.setInt(idx++, month.intValue());
2310:                if (day != null)
2311:                    pStmt.setInt(idx++, day.intValue());
2312:            }
2313:
2314:            /**
2315:             * Génère un nouveau numéro de tache pour un chemin donné.
2316:             * @param tx le contexte de transaction.
2317:             * @param path le chemin considéré.
2318:             * @return le numéro généré.
2319:             * @throws DbException levé en cas d'incident technique d'accès à la base.
2320:             */
2321:            protected static byte newTaskNumber(DbTransaction tx, String path)
2322:                    throws DbException {
2323:                PreparedStatement pStmt = null;
2324:                ResultSet rs = null;
2325:                try {
2326:                    // Récupération de la connexion
2327:                    Connection con = tx.getConnection();
2328:
2329:                    // Recherche du max
2330:                    pStmt = con
2331:                            .prepareStatement("select max(tsk_number) from task where tsk_path=?");
2332:                    pStmt.setString(1, path);
2333:                    rs = pStmt.executeQuery();
2334:                    if (!rs.next())
2335:                        throw new DbException(
2336:                                "Nothing returned from this query", null);
2337:                    byte max = rs.getByte(1);
2338:                    log.debug("  => max= : " + max);
2339:
2340:                    // Fermeture du statement
2341:                    pStmt.close();
2342:                    pStmt = null;
2343:
2344:                    // Retour du résultat
2345:                    return (byte) (max + 1);
2346:                } catch (SQLException e) {
2347:                    log.info("Incident SQL", e);
2348:                    throw new DbException(
2349:                            "Echec lors de la génération d'un nouveau numéro de tache pour le chemin '"
2350:                                    + path + "'", e);
2351:                } finally {
2352:                    if (pStmt != null)
2353:                        try {
2354:                            pStmt.close();
2355:                        } catch (Throwable ignored) {
2356:                        }
2357:                }
2358:            }
2359:
2360:            /**
2361:             * Retourne l'identifiant généré automatiquement par la base de données.
2362:             * @param pStmt le statement SQL.
2363:             * @return l'identifiant généré.
2364:             * @throws DbException levé en cas d'incident technique d'accès à la base.
2365:             */
2366:            private static long getGeneratedId(PreparedStatement pStmt)
2367:                    throws DbException {
2368:                long generatedId = -1;
2369:                PreparedStatement pStmt1 = null;
2370:                try {
2371:                    // Récupération de la connexion
2372:                    Connection con = pStmt.getConnection();
2373:                    // Cas de HSQLDB
2374:                    if (isHSQLDB(con)) {
2375:                        log.debug("HSQL Database detected");
2376:                        pStmt1 = con.prepareStatement("call identity()");
2377:                        ResultSet rs = pStmt1.executeQuery();
2378:                        if (!rs.next())
2379:                            throw new DbException(
2380:                                    "Nothing returned from this query", null);
2381:                        generatedId = rs.getLong(1);
2382:
2383:                        // Fermeture du statement
2384:                        pStmt1.close();
2385:                        pStmt1 = null;
2386:                    } else {
2387:                        log.debug("Generic Database detected");
2388:                        // Récupération de l'identifiant généré
2389:                        ResultSet rs = pStmt.getGeneratedKeys();
2390:                        if (!rs.next())
2391:                            throw new DbException(
2392:                                    "Nothing returned from this query", null);
2393:                        generatedId = rs.getLong(1);
2394:                    }
2395:                    // Retour du résultat
2396:                    log.debug("Generated id=" + generatedId);
2397:                    return generatedId;
2398:                } catch (SQLException e) {
2399:                    log.info("Incident SQL", e);
2400:                    throw new DbException(
2401:                            "Echec lors de la récupération de l'identifiant du nouvel objet",
2402:                            e);
2403:                } finally {
2404:                    if (pStmt1 != null)
2405:                        try {
2406:                            pStmt1.close();
2407:                        } catch (Throwable ignored) {
2408:                        }
2409:                }
2410:            }
2411:
2412:            /**
2413:             * Indique si la BDD de données est une base HSQLDB.
2414:             * @param con la connexion SQL.
2415:             * @return un booléen indiquant si la BDD est de type HSQLDB.
2416:             * @throws DbException levé en cas d'incident technique d'accès à la base.
2417:             */
2418:            private static boolean isHSQLDB(Connection con) throws DbException {
2419:                try {
2420:                    // Récupération du nom de la base de données
2421:                    String dbName = con.getMetaData().getDatabaseProductName();
2422:                    log.debug("DbName=" + dbName);
2423:                    return "HSQL Database Engine".equals(dbName);
2424:                } catch (SQLException e) {
2425:                    log.info("Incident SQL", e);
2426:                    throw new DbException(
2427:                            "Echec lors de la récupération du nom de la BDD", e);
2428:                }
2429:            }
2430:
2431:            /**
2432:             * Indique si la BDD de données est une base HSQLDB embarquée.
2433:             * @param con la connexion SQL.
2434:             * @return un booléen indiquant si la BDD est de type HSQLDB embarquée.
2435:             * @throws DbException levé en cas d'incident technique d'accès à la base.
2436:             */
2437:            private static boolean isEmbeddedHSQLDB(Connection con)
2438:                    throws DbException {
2439:                try {
2440:                    // Récupération du nom de la base de données
2441:                    String dbName = con.getMetaData().getDatabaseProductName();
2442:                    log.debug("DbName=" + dbName);
2443:                    return isHSQLDB(con)
2444:                            && ds.getUrl().startsWith("jdbc:hsqldb:file");
2445:                } catch (SQLException e) {
2446:                    log.info("Incident SQL", e);
2447:                    throw new DbException(
2448:                            "Echec lors de la récupération du nom de la BDD", e);
2449:                }
2450:            }
2451:
2452:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.