1    package com.instantbank.component.lettertemplate.ejb;
2    
3    import java.util.ArrayList;
4    import java.util.Hashtable;
5    import java.text.SimpleDateFormat;
6    import java.text.DateFormat;
7    import java.util.Locale;
8    import java.util.Calendar;
9    import java.util.StringTokenizer;
10   import java.util.GregorianCalendar;
11   
12   // for accessing DB:
13   import java.sql.Types;
14   import java.sql.Connection;
15   import java.sql.Statement;
16   import java.sql.PreparedStatement;
17   import java.sql.CallableStatement;
18   import java.sql.ResultSet;
19   import java.sql.SQLException;
20   import java.sql.Date;
21   import javax.sql.DataSource;
22   
23   // streams:
24   import java.io.StringWriter;
25   import java.io.PrintWriter;
26   import java.io.InputStream;
27   import java.io.ByteArrayInputStream;
28   import java.rmi.RemoteException;
29   
30   // EJB:
31   import javax.ejb.EJBException;
32   import javax.naming.InitialContext;
33   import javax.ejb.FinderException;
34   
35   // util of EJB lettertemplate:
36   import com.instantbank.component.lettertemplate.util.*;
37   
38   // EJB job:
39   import com.instantbank.component.job.ejb.Job;
40   import com.instantbank.component.job.ejb.JobHome;
41   import com.instantbank.component.job.model.JobModel;
42   import com.instantbank.component.job.model.JobSELECTelement;
43   import com.instantbank.component.job.model.JobWHEREelement;
44   import com.instantbank.component.job.model.JobORDERelement;
45   import com.instantbank.component.job.util.Field;
46   import com.instantbank.component.job.util.Alias;
47   
48   // common util:
49   import com.instantbank.common.utilcomponents.CodeDescription;
50   import com.instantbank.common.utilcomponents.DatabaseNames;
51   import com.instantbank.common.utilcomponents.Debug;
52   import com.instantbank.common.utilcomponents.LetterTemplateExceptionMessage;
53   import com.instantbank.common.utilcomponents.LetterTemplateGlobals;
54   import com.instantbank.common.utilcomponents.JNDINames;
55   import com.instantbank.common.utilcomponents.DAOException;
56   import com.instantbank.common.utilcomponents.DAOUtil;
57   import com.instantbank.common.utilcomponents.CommonUtil;
58   import com.instantbank.common.utilcomponents.JNDINames;
59   import com.instantbank.common.utilcomponents.SqlUtils;
60   
61   /**
62    *  This class has JDBC calls required by EJB letterTemplate for
63    *  implementing its services
64    *
65    * @author Instant-bank (Consuelo Franky, Roberto Contreras)
66    * @created August 2002
67    */
68   public class LetterTemplateDAO {
69   
70     // attributes corresponding to EJB:
71   
72     /**
73      *  current company
74      */
75     String companyId;
76   
77     /**
78      * current user
79      */
80     Long userId;
81   
82     // attributes for connecting with the DB:
83   
84     /**
85      * connection with the database
86      */
87     private Connection dbConnection = null;
88   
89     /**
90      * datasource corresponding to the database
91      */
92     private DataSource datasource = null;
93   
94     // attributes for incrementing efficiency of some services :
95   
96     /**
97      * Format Date of US (Mon day, Year)
98      */
99     private DateFormat form = null;
100  
101    /**
102     * GregorianCalendar
103     */
104    private GregorianCalendar calendar = new GregorianCalendar();
105  
106    /**
107     * The Date of today
108     */
109    private java.util.Date toDay = null;
110  
111    /**
112     * calendars of current company
113     */
114    private Hashtable companyCalendars = null;
115  
116    /**
117     * for debugging
118     */
119    private Debug debug = null;
120  
121  
122    /**
123     *  Constructor: searchs the DataSource in the InitialContext
124     *
125     * @param companyId current company
126     * @param userId current user
127     * @exception DAOException Description of the Exception
128     * @throws DAOException Description of the Exception
129     */
130    public LetterTemplateDAO(String companyId, Long userId)
131       throws DAOException {
132      debug = new Debug();
133      debug.setDebugginOn(true);
134      debug.setPreMessage("** LetterTemplateDAO");
135  
136      this.companyId = companyId;
137      this.userId = userId;
138      datasource = DAOUtil.getDataSource(JNDINames.INSTANTBANKDB);
139      this.form = DateFormat.getDateInstance(DateFormat.LONG, Locale.US);
140      this.toDay = calendar.getTime();  // only MM-DD-YYYY
141    }
142  
143  
144    // JDBC METHODS WHICH SUPPORT EJB SERVICES CORRESPONDING TO
145    // LOADING OF LETTERS BASIC DATA
146  
147    /**
148     *  Loads data of DatabaseNames.LETT_FIELD of the current company
149     *  (i.e. restricting with DatabaseNames.LETT_COMPANY_FIELD)
150     *
151     * @return Hashtable of system Fields for current company
152     *           key: fieldId (in Long),
153     *           value: com.instantbank.component.job.util.Field object
154     * @exception DAOException
155     */
156    public Hashtable loadFields() throws DAOException {
157      debug.println("loadFields");
158  
159      PreparedStatement ps = null;
160      ResultSet rs = null;
161      String queryStrFields =
162        " SELECT f.field_id,  f.table_alias, f.root_type, "
163         + "     f.field_column, f.data_type,   f.menu_id,   "
164         + "     f.offset_type,  c.display_name "
165         + " FROM "
166         + DatabaseNames.LETT_FIELD + " f ,"
167         + DatabaseNames.LETT_COMPANY_FIELD + " c "
168         + " WHERE f.field_id = c.field_id  "
169         + "   AND c.code_company = ? "
170         + " ORDER BY f.field_id ";
171  
172      Hashtable answer = new Hashtable();
173  
174      try {
175        dbConnection = DAOUtil.getDBConnection(datasource);
176        ps = dbConnection.prepareStatement(queryStrFields);
177        ps.setLong(1, Long.parseLong(companyId));
178        ps.executeQuery();
179        rs = ps.getResultSet();
180        while(rs.next()) {
181          long fieldId = rs.getLong(1);
182          String tableAlias = rs.getString(2).trim();
183          String rootType = rs.getString(3);
184          String fieldColumn = rs.getString(4).trim();
185          String dataType = rs.getString(5);
186          long menuId = rs.getLong(6);
187          if(rs.wasNull()) {
188            menuId = LetterTemplateGlobals.UNDEF;
189          }
190          String offsetType = rs.getString(7);
191          String displayName = rs.getString(8);
192          answer.put(new Long(fieldId),
193            new Field(fieldId, tableAlias, rootType,
194            fieldColumn, dataType, menuId,
195            offsetType, displayName));
196        }
197      }
198      catch(Exception ae) {
199        debug.println("Exception:  " + ae.toString());
200        throw new DAOException
201          (LetterTemplateExceptionMessage.PROBLEM_LOAD_FIELDS
202           + ae.getMessage());
203      }
204      finally {
205        DAOUtil.closeResultSet(rs);
206        DAOUtil.closePreparedStatement(ps);
207        DAOUtil.closeConnection(dbConnection);
208      }
209      return answer;
210    }
211  
212  
213    /**
214     *  Loads company fields with display information and menu references
215     *  (for current company).
216     *  from DatabaseNames.LETT_FIELD_MENU, LETT_FIELD, LETT_COMPANY_FIELD,
217     *  ordered by display name
218     *
219     * @return ArrayList of company fields where each element is an
220     *           inner ArrayList composed of: fieldId(Long), displayName(String),
221     *           dataType(String), menuId(Long), menuName (String),
222     *           offsetType(String)
223     * @exception DAOException
224     */
225    public ArrayList loadFieldsDisplay() throws DAOException {
226      debug.println("loadFieldsDisplay");
227  
228      PreparedStatement ps = null;
229      ResultSet rs = null;
230      String queryStrFields =
231        " SELECT f.field_id, c.display_name, f.data_type, "
232         + "        f.menu_id,  m.description,  f.offset_type  "
233         + " FROM "
234         + DatabaseNames.LETT_FIELD_MENU + " m ,"
235         + DatabaseNames.LETT_FIELD + " f ,"
236         + DatabaseNames.LETT_COMPANY_FIELD + " c "
237         + " WHERE m.menu_id (+) = f.menu_id "
238         + "   AND f.field_id = c.field_id  "
239         + "   AND c.code_company = ? "
240         + " ORDER BY c.display_name ";
241  
242      ArrayList answer = new ArrayList();
243  
244      try {
245        dbConnection = DAOUtil.getDBConnection(datasource);
246        ps = dbConnection.prepareStatement(queryStrFields);
247        ps.setLong(1, Long.parseLong(companyId));
248        ps.executeQuery();
249        rs = ps.getResultSet();
250  
251        while(rs.next()) {
252          long fieldId = rs.getLong(1);
253          String displayName = rs.getString(2).trim();
254          String dataType = rs.getString(3);
255          long menuId = rs.getLong(4);
256          Long menuIdLong = null;
257          if(!rs.wasNull()) {
258            menuIdLong = new Long(menuId);
259          }
260          String menuName = rs.getString(5);
261          String offsetType = rs.getString(6);
262          ArrayList tuple = new ArrayList(6);
263          tuple.add(new Long(fieldId));
264          tuple.add(displayName);
265          tuple.add(dataType);
266          tuple.add(menuIdLong);
267          tuple.add(menuName);
268          tuple.add(offsetType);
269          answer.add(tuple);
270        }
271      }
272      catch(Exception ae) {
273        debug.println("Exception:  " + ae.toString());
274        throw new DAOException
275          (LetterTemplateExceptionMessage.PROBLEM_LOAD_FIELDS
276           + ae.getMessage());
277      }
278      finally {
279        DAOUtil.closeResultSet(rs);
280        DAOUtil.closePreparedStatement(ps);
281        DAOUtil.closeConnection(dbConnection);
282      }
283      return answer;
284    }
285  
286  
287    /**
288     *  Loads system field Menus with its values
289     *  ordered by description (name of menu);
290     *  from DatabaseNames.LETT_FIELD_MENU, LETT_FIELD_VALUE
291     *
292     * @return ArrayList of menus where each element is an
293     *           inner ArrayList composed of:
294     *           menuName(String), menuValues(ArrayList);
295     *           each menuValues element is a String[]
296     *           with an internalValue(String) and display(String)
297     * @exception DAOException
298     */
299    public ArrayList loadFieldMenus() throws DAOException {
300      debug.println("loadFieldMenus");
301  
302      PreparedStatement ps;
303  
304      PreparedStatement ps2;
305      ps = ps2 = null;
306      ResultSet rs;
307      ResultSet rs2;
308      rs = rs2 = null;
309      String queryStrFields =
310        " SELECT m.description, m.menu_type,"
311         + "        v.value, v.display, m.menu_select "
312         + " FROM "
313         + DatabaseNames.LETT_FIELD_MENU + " m ,"
314         + DatabaseNames.LETT_FIELD_VALUE + " v  "
315         + " WHERE m.menu_id = v.menu_id (+)"
316         + " ORDER BY m.description ";
317  
318      ArrayList answer = new ArrayList();
319  
320      try {
321        dbConnection = DAOUtil.getDBConnection(datasource);
322        ps = dbConnection.prepareStatement(queryStrFields);
323        ps.executeQuery();
324        rs = ps.getResultSet();
325  
326        String oldDescription = "";
327        ArrayList menuValues = null;
328        ArrayList menu = null;
329        int num = 0;
330        while(rs.next()) {
331          String newDescription = rs.getString(1).trim();
332          String menuType = rs.getString(2);
333  
334          if(menuType.equals(LetterTemplateGlobals.FIXED_MENU)) {
335            String[] value = new String[2];
336            value[0] = rs.getString(3).trim();
337            value[1] = rs.getString(4).trim();
338            if(!newDescription.equals(oldDescription)) {
339              if(num != 0) {
340                answer.add(menu);  // adds precedent menu
341              }
342              menuValues = new ArrayList();
343              menuValues.add(value);
344              menu = new ArrayList();
345              menu.add(newDescription);
346              menu.add(menuValues);
347              oldDescription = newDescription;
348            }
349            else {
350              menuValues.add(value);
351            }
352          }
353  
354          else {  // menuType is "table"
355            if(num != 0) {
356              answer.add(menu);  // adds precedent menu
357            }
358            menu = new ArrayList();  // initializes new menu
359            menu.add(newDescription);
360            menuValues = new ArrayList();
361            menu.add(menuValues);
362  
363            String sqlSelectTable = rs.getString(5);
364            ps2 = dbConnection.prepareStatement(sqlSelectTable);
365            ps2.executeQuery();
366            rs2 = ps2.getResultSet();
367            while(rs2.next()) {
368              String[] value = new String[2];
369              value[0] = rs2.getString(1).trim();
370              value[1] = rs2.getString(2).trim();
371              menuValues.add(value);
372            }
373            DAOUtil.closePreparedStatement(ps2);
374            oldDescription = newDescription;
375          }
376          num++;
377        }
378        if(num > 0) {
379          answer.add(menu);
380        }
381      }
382      catch(Exception ae) {
383        debug.println("Exception:  " + ae.toString());
384        throw new DAOException
385          (LetterTemplateExceptionMessage.PROBLEM_LOAD_MENUS
386           + ae.getMessage());
387      }
388      finally {
389        DAOUtil.closeResultSet(rs);
390        DAOUtil.closePreparedStatement(ps);
391        DAOUtil.closeConnection(dbConnection);
392      }
393      return answer;
394    }
395  
396  
397    /**
398     *  Loads data of DatabaseNames.LETT_ALIAS
399     *
400     * @return Hashtable of system Alias
401     *           key: String = tableAlias|rootType
402     *           value: com.instantbank.component.job.util.Alias object
403     * @exception DAOException
404     */
405    public Hashtable loadAlias() throws DAOException {
406      debug.println("loadAlias");
407  
408      PreparedStatement ps = null;
409      ResultSet rs = null;
410      String queryStrFields =
411        " SELECT table_alias, root_type, description, real_table, "
412         + "   field_category,  parent_table_alias, parent_join_column, "
413         + "   son_join_column, join_type, built_table "
414         + " FROM "
415         + DatabaseNames.LETT_ALIAS
416         + " ORDER BY root_type, table_alias ";
417  
418      Hashtable answer = new Hashtable();
419  
420      try {
421        dbConnection = DAOUtil.getDBConnection(datasource);
422        ps = dbConnection.prepareStatement(queryStrFields);
423        ps.executeQuery();
424        rs = ps.getResultSet();
425        while(rs.next()) {
426          String tableAlias = rs.getString(1).trim();
427          String rootType = rs.getString(2);
428          String description = rs.getString(3);
429          String realTable = rs.getString(4).trim();
430          String fieldCategory = rs.getString(5);
431          String parentTableAlias = rs.getString(6);
432          if(parentTableAlias != null) {
433            parentTableAlias = parentTableAlias.trim();
434          }
435          String parentJoinColumn = rs.getString(7);
436          if(parentJoinColumn != null) {
437            parentJoinColumn = parentJoinColumn.trim();
438          }
439          String sonJoinColumn = rs.getString(8);
440          if(sonJoinColumn != null) {
441            sonJoinColumn = sonJoinColumn.trim();
442          }
443          String joinType = rs.getString(9);
444          String builtTable = rs.getString(10);
445  
446          String key = tableAlias + "|" + rootType;
447          answer.put(key, new Alias(
448            tableAlias, rootType, description, realTable,
449            fieldCategory, parentTableAlias, parentJoinColumn,
450            sonJoinColumn, joinType, builtTable));
451        }
452      }
453      catch(Exception ae) {
454        debug.println("Exception:  " + ae.toString());
455        throw new DAOException
456          (LetterTemplateExceptionMessage.PROBLEM_LOAD_ALIAS
457           + ae.getMessage());
458      }
459      finally {
460        DAOUtil.closeResultSet(rs);
461        DAOUtil.closePreparedStatement(ps);
462        DAOUtil.closeConnection(dbConnection);
463      }
464      return answer;
465    }
466  
467  
468    /**
469     *  Loads name of letter variables of the current company, ordered by name
470     *  from DatabaseNames.LETT_FIELD and DatabaseNames.LETT_COMPANY_FIELD
471     *
472     * @return ArrayList of variables where each element is an
473     *           inner ArrayList with the following elements of a variable:
474     *             fieldId(Long): code of field (variable) in the system,
475     *             name(String): name of variable to display in user interface,
476     *             dataType(String): type of variable:
477     *                   numeric: LetterTemplateGlobals.FIELD_NUMERIC,
478     *                   string:  LetterTemplateGlobals.FIELD_STRING,
479     *                   date:    LetterTemplateGlobals.FIELD_DATE
480     *             offsetType(String): type of offset (relevant for date fields):
481     *                   no:            LetterTemplateGlobals.NO_OFFSET,
482     *                   chronological: LetterTemplateGlobals.CHRONO_DAYS_OFFSET,
483     *                   workable     : LetterTemplateGlobals.WORKABLE_DAYS_OFFSET
484     * @exception DAOException
485     */
486    public ArrayList loadVariables() throws DAOException {
487      debug.println("loading variables");
488  
489      PreparedStatement ps = null;
490      ResultSet rs = null;
491  
492      String queryStrFields =
493        " SELECT f.field_id, c.display_name, "
494         + "        f.data_type, f.offset_type "
495         + " FROM "
496         + DatabaseNames.LETT_FIELD + " f ,"
497         + DatabaseNames.LETT_COMPANY_FIELD + " c "
498         + " WHERE f.field_id = c.field_id  "
499         + "   AND c.code_company = ? "
500         + " ORDER BY c.display_name ";
501  
502      ArrayList answer = new ArrayList();
503  
504      try {
505        dbConnection = DAOUtil.getDBConnection(datasource);
506        ps = dbConnection.prepareStatement(queryStrFields);
507        ps.setLong(1, Long.parseLong(companyId));
508        ps.executeQuery();
509        rs = ps.getResultSet();
510        while(rs.next()) {
511          Long fieldId = new Long(rs.getLong(1));
512          String name = rs.getString(2);
513          String dataType = rs.getString(3);
514          String offsetType = rs.getString(4);
515          ArrayList tuple = new ArrayList(3);
516          tuple.add(fieldId);
517          tuple.add(name);
518          tuple.add(dataType);
519          tuple.add(offsetType);
520          answer.add(tuple);
521        }
522      }
523      catch(Exception ae) {
524        debug.println("Exception:  " + ae.toString());
525        throw new DAOException
526          (LetterTemplateExceptionMessage.PROBLEM_LOAD_VARIABLES
527           + ae.getMessage());
528      }
529      finally {
530        DAOUtil.closeResultSet(rs);
531        DAOUtil.closePreparedStatement(ps);
532        DAOUtil.closeConnection(dbConnection);
533      }
534      return answer;
535    }
536  
537  
538    /**
539     *  Loads code and description of format of letter variables from
540     *  DatabaseNames.LETT_FORMAT table; ordered by description
541     *
542     * @return CodeDescription[] object
543     *      with [code, description] of formats
544     * @exception DAOException
545     */
546    public CodeDescription[] loadVariableFormats()
547       throws DAOException {
548      debug.println("loading variable formats");
549  
550      PreparedStatement ps = null;
551      ResultSet rs = null;
552      String queryStr =
553        " SELECT code_format, description "
554         + " FROM " + DatabaseNames.LETT_FORMAT
555         + " ORDER BY description ";
556      CodeDescription[] answer = null;
557  
558      try {
559        dbConnection = DAOUtil.getDBConnection(datasource);
560        ps = dbConnection.prepareStatement(queryStr);
561        answer = DAOUtil.loadCodeDescription(ps, rs);
562      }
563      catch(Exception ae) {
564        debug.println("Exception:  " + ae.toString());
565        throw new DAOException
566          (LetterTemplateExceptionMessage.PROBLEM_LOAD_FORMATS
567           + ae.getMessage());
568      }
569      finally {
570        DAOUtil.closeResultSet(rs);
571        DAOUtil.closePreparedStatement(ps);
572        DAOUtil.closeConnection(dbConnection);
573      }
574      return answer;
575    }
576  
577  
578    /**
579     *  Loads code and description of printTypes; from
580     *  DatabaseNames.LETT_PRINT_TYPE table; ordered by description
581     *
582     * @return CodeDescription[] object
583     *      with [code, description] of printTypes
584     * @exception DAOException
585     */
586    public CodeDescription[] loadPrintTypes() throws DAOException {
587      debug.println("loading print types");
588  
589      PreparedStatement ps = null;
590      ResultSet rs = null;
591      String queryStr =
592        " SELECT code_print_type, description "
593         + " FROM " + DatabaseNames.LETT_PRINT_TYPE
594         + " ORDER BY description ";
595      CodeDescription[] answer = null;
596  
597      try {
598        dbConnection = DAOUtil.getDBConnection(datasource);
599        ps = dbConnection.prepareStatement(queryStr);
600        answer = DAOUtil.loadCodeDescription(ps, rs);
601      }
602      catch(Exception ae) {
603        debug.println("Exception:  " + ae.toString());
604        throw new DAOException
605          (LetterTemplateExceptionMessage.PROBLEM_LOAD_PRINTTYPES + ae.getMessage());
606      }
607      finally {
608        DAOUtil.closeResultSet(rs);
609        DAOUtil.closePreparedStatement(ps);
610        DAOUtil.closeConnection(dbConnection);
611      }
612      return answer;
613    }
614  
615  
616    // JDBC METHODS WHICH SUPPORT EJB SERVICES CORRESPONDING TO
617    // MANAGEMENT OF LETTERS CATEGORIES
618  
619    /**
620     *  Loads all [code, description] of the categories of the current company,
621     *  in DatabaseNames.LETT_CATEGORY; ordered by name
622     *
623     * @return CodeDescription[] object
624     *      with [code, description] of the categories
625     * @exception DAOException
626     */
627    public CodeDescription[] loadCategories()
628       throws DAOException {
629      debug.println("loading categories of current company");
630  
631      PreparedStatement ps = null;
632      ResultSet rs = null;
633      String queryStr =
634        " SELECT code_category, description "
635         + " FROM " + DatabaseNames.LETT_CATEGORY
636         + " WHERE code_company = ?"
637         + " ORDER BY description ";
638      CodeDescription[] answer = null;
639  
640      try {
641        String rtf =
642          CommonUtil.getApplicationProperty(JNDINames.RTF2FO_CONFIG_PATH);
643        debug.println("rtf = " + rtf);
644        dbConnection = DAOUtil.getDBConnection(datasource);
645        ps = dbConnection.prepareStatement(queryStr);
646        ps.setLong(1, Long.parseLong(companyId));
647        answer = DAOUtil.loadCodeDescription(ps, rs);
648      }
649      catch(Exception ae) {
650        //debug.println(CommonUtil.stackTraceToString(ae));
651        debug.println("Exception:  " + ae.getMessage());
652        throw new DAOException
653          (LetterTemplateExceptionMessage.PROBLEM_LOAD_CATEGORIES + ae.getMessage());
654      }
655      finally {
656        DAOUtil.closeResultSet(rs);
657        DAOUtil.closePreparedStatement(ps);
658        DAOUtil.closeConnection(dbConnection);
659      }
660      return answer;
661    }
662  
663  
664    /**
665     *  Applies a set of changes in the categories of the current company; in
666     *  DatabaseNames.LETT_CATEGORY;
667     *
668     * @param items ArrayList with 3 elements of
669     *      type String[] representing the attributes of items to apply code,
670     *      name and status status indicates if the item is for inserting,
671     *      deleting or updating
672     *      (LetterTemplateGlobals.INSERT, LetterTemplateGlobals.DELETE, LetterTemplateGlobals.UPDATE)
673     * @return ArrayList with 2 elements:
674     *      (0) possible problem (String),
675     *      (1) current categories list (CodeDescription[])
676     * @exception DAOException
677     */
678    public ArrayList applyItemsCategory(ArrayList items)
679       throws DAOException {
680      debug.println("applying a set of changes to categories of current company");
681  
682      PreparedStatement ps1;
683  
684      PreparedStatement ps2;
685  
686      PreparedStatement ps3;
687      ps1 = ps2 = ps3 = null;
688      boolean listsBuilted = false;
689      boolean successTransaction = false;
690      CodeDescription item = null;
691      ArrayList insertList = new ArrayList();
692      ArrayList deleteList = new ArrayList();
693      ArrayList updateList = new ArrayList();
694      int listSize;
695  
696      String insertStr =
697        " INSERT INTO " + DatabaseNames.LETT_CATEGORY
698         + "   (code_category, code_company, description)"
699         + " VALUES ("
700         + DatabaseNames.SEQ_LETT_CATEGORY + ".nextval,"
701         + "    ?, ?)";
702  
703      String deleteStr =
704        " DELETE " + DatabaseNames.LETT_CATEGORY
705         + " WHERE code_category = ?";
706  
707      String updateStr =
708        " UPDATE " + DatabaseNames.LETT_CATEGORY
709         + " SET description = ?"
710         + " WHERE code_category = ?";
711  
712      String problem = LetterTemplateGlobals.STR_UNDEF;
713      CodeDescription[] categoriesList = null;
714      ArrayList answer = null;
715  
716      // from items parameter, build 3 sets of items:
717      // items for inserting, deleting and updating
718      try {
719        String[] code = (String[])items.get(0);
720        String[] name = (String[])items.get(1);
721        String[] status = (String[])items.get(2);
722        int numItems = code.length;
723  
724        for(int i = 0; i < numItems; i++) {
725          item = new CodeDescription(Long.parseLong(code[i]), name[i]);
726          if(status[i].equals(LetterTemplateGlobals.INSERT)) {
727            insertList.add(item);
728          }
729          else if(status[i].equals(LetterTemplateGlobals.DELETE)) {
730            deleteList.add(item);
731          }
732          else if(status[i].equals(LetterTemplateGlobals.UPDATE)) {
733            updateList.add(item);
734          }
735          else {
736            throw new DAOException
737              (LetterTemplateExceptionMessage.ITEM_STATUS_INVALID);
738          }
739        }
740        listsBuilted = true;
741      }
742      catch(Exception e) {
743        debug.println("Exception building lists:  " + e.toString());
744        StringWriter sw = new StringWriter();
745        PrintWriter pw = new PrintWriter(sw);
746        e.printStackTrace(pw);
747        problem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_CHANGES_CATEGORIES
748           + e.getMessage()
749           + "|" + sw.toString();
750      }
751  
752      // apply sets of changes:
753      if(listsBuilted) {
754        String phase = "";
755        try {
756          dbConnection = DAOUtil.getDBConnection(datasource);
757          dbConnection.setAutoCommit(false);
758  
759          // apply set of inserts:
760          // TODO: try standard batch with BEA 7.0
761          phase = "insert";
762          ps1 = dbConnection.prepareStatement(insertStr);
763          listSize = insertList.size();
764          for(int i = 0; i < listSize; i++) {
765            item = (CodeDescription)(insertList.get(i));
766            ps1.setLong(1, Long.parseLong(companyId));
767            ps1.setString(2, item.getDescription());
768            //ps1.addBatch();
769            ps1.executeUpdate();
770          }
771          //ps1.executeBatch();
772  
773          // apply set of deletes:
774          phase = "delete";
775          ps2 = dbConnection.prepareStatement(deleteStr);
776          listSize = deleteList.size();
777          for(int i = 0; i < listSize; i++) {
778            item = (CodeDescription)(deleteList.get(i));
779            ps2.setLong(1, item.getCode());
780            int num = ps2.executeUpdate();
781            if(num == 0) {
782              throw new DAOException
783                (LetterTemplateExceptionMessage.PROBLEM_APPLYING_DELETES1_CATEGORIES);
784            }
785          }
786  
787          // apply set of updates:
788          phase = "update";
789          ps3 = dbConnection.prepareStatement(updateStr);
790          listSize = updateList.size();
791          for(int i = 0; i < listSize; i++) {
792            item = (CodeDescription)(updateList.get(i));
793            ps3.setString(1, item.getDescription());
794            ps3.setLong(2, item.getCode());
795            int num = ps3.executeUpdate();
796            if(num == 0) {
797              throw new DAOException
798                (LetterTemplateExceptionMessage.PROBLEM_APPLYING_UPDATES1_CATEGORIES);
799            }
800          }
801  
802          successTransaction = true;
803        }
804        catch(Exception ae) {
805          debug.println("Exception applying item to DB in phase " + phase
806             + " : " + ae.toString());
807          StringWriter sw = new StringWriter();
808          PrintWriter pw = new PrintWriter(sw);
809          ae.printStackTrace(pw);
810          String subproblem = null;
811          if(phase.equals("insert")) {
812            subproblem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_INSERTS_CATEGORIES;
813          }
814          else if(phase.equals("delete")) {
815            subproblem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_DELETES2_CATEGORIES;
816          }
817          else {
818            // phase.equals("update")
819            subproblem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_UPDATES2_CATEGORIES;
820          }
821          String categoryName = (item != null) ? item.getDescription() : "";
822          problem = subproblem
823             + "current category name: " + categoryName
824             + " :" + ae.getMessage() + "|" + sw.toString();
825        }
826        finally {
827          try {
828            if(successTransaction) {
829              dbConnection.commit();
830            }
831            else {
832              dbConnection.rollback();
833            }
834          }
835          catch(Exception e) {
836            debug.println("Exception resolving transaction:  " + e.toString());
837            StringWriter sw = new StringWriter();
838            PrintWriter pw = new PrintWriter(sw);
839            e.printStackTrace(pw);
840            problem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_CHANGES_CATEGORIES
841               + e.getMessage()
842               + "|" + sw.toString();
843          }
844          DAOUtil.closePreparedStatement(ps1);
845          DAOUtil.closePreparedStatement(ps2);
846          DAOUtil.closePreparedStatement(ps3);
847          DAOUtil.closeConnection(dbConnection);
848        }
849      }
850  
851      // get current categories list:
852      try {
853        categoriesList = this.loadCategories();
854        answer = new ArrayList(2);
855        answer.add(problem);
856        answer.add(categoriesList);
857      }
858      catch(Exception ae) {
859        throw new DAOException
860          (LetterTemplateExceptionMessage.PROBLEM_LOAD_CATEGORIES + ae.getMessage());
861      }
862      return answer;
863    }
864  
865  
866    // JDBC METHODS WHICH SUPPORT EJB SERVICES CORRESPONDING TO
867    // MANAGEMENT OF LETTERS IMAGES REPOSITORY
868  
869    /**
870     *  Stores a new image for the current company in
871     *  DatabaseNames.LETT_IMAGES_REPOSITORY
872     *
873     * @param nameImage name of image
874     * @param image bytes of image
875     * @return code (long) assigned to the image
876     * @exception DAOException
877     */
878    public long storeImageRepository(String nameImage, byte[] image)
879       throws DAOException {
880      debug.println("storing in repository a new image of name=" + nameImage);
881      PreparedStatement ps = null;
882      ResultSet rs = null;
883  
884      String queryName =
885        " SELECT name "
886         + " FROM " + DatabaseNames.LETT_IMAGES_REPOSITORY
887         + " WHERE code_company = ?  AND name = ?";
888  
889      String insertStr =
890        " INSERT INTO " + DatabaseNames.LETT_IMAGES_REPOSITORY
891         + "   (code_image, code_company, name, image)"
892         + " VALUES ("
893         + DatabaseNames.SEQ_LETT_IMAGE + ".nextval,"
894         + "    ?, ?, EMPTY_BLOB())";
895  
896      String queryImage =
897        " SELECT image "
898         + " FROM " + DatabaseNames.LETT_IMAGES_REPOSITORY
899         + " WHERE code_company = ?  AND name = ?";
900  
901      String queryCode =
902        " SELECT code_image "
903         + " FROM " + DatabaseNames.LETT_IMAGES_REPOSITORY
904         + " WHERE code_company = ?  AND name = ?";
905  
906      int numBytes;
907      boolean successTransaction = false;
908      long answer = LetterTemplateGlobals.UNDEF;
909  
910      try {
911        dbConnection = DAOUtil.getDBConnection(datasource);
912        dbConnection.setAutoCommit(false);
913  
914        // find if image is repeated :
915        ps = dbConnection.prepareStatement(queryName);
916        ps.setLong(1, Long.parseLong(companyId));
917        ps.setString(2, nameImage);
918        ps.executeQuery();
919        rs = ps.getResultSet();
920        if(rs.next()) {
921          debug.println("image already exists");
922          throw new DAOException
923            (LetterTemplateExceptionMessage.PROBLEM_STORE_IMAGE_REPEATED + nameImage);
924        }
925        DAOUtil.closePreparedStatement(ps);
926  
927        // initialize new tuple with BLOB type:
928        ps = dbConnection.prepareStatement(insertStr);
929        ps.setLong(1, Long.parseLong(companyId));
930        ps.setString(2, nameImage);
931        ps.executeUpdate();
932        DAOUtil.closePreparedStatement(ps);
933  
934        // obtain reference to BLOB field:
935        ps = dbConnection.prepareStatement(queryImage);
936        ps.setLong(1, Long.parseLong(companyId));
937        ps.setString(2, nameImage);
938        java.sql.Blob imageFieldRef = DAOUtil.getBlobReference(ps, rs);
939  
940        // write the image on the DB:
941        InputStream is = new ByteArrayInputStream(image);
942        DAOUtil.writeBlobData(imageFieldRef, is);
943        DAOUtil.closePreparedStatement(ps);
944  
945        // get the code assigned to image:
946        ps = dbConnection.prepareStatement(queryCode);
947        ps.setLong(1, Long.parseLong(companyId));
948        ps.setString(2, nameImage);
949        ps.executeQuery();
950        rs = ps.getResultSet();
951        rs.next();
952        answer = rs.getLong(1);
953  
954        successTransaction = true;
955      }
956      catch(Exception ae) {
957        debug.println("Exception:  " + ae.toString());
958        throw new DAOException
959          (LetterTemplateExceptionMessage.PROBLEM_STORE_IMAGE + ae.getMessage());
960      }
961      finally {
962        try {
963          if(successTransaction) {
964            dbConnection.commit();
965          }
966          else {
967            dbConnection.rollback();
968          }
969        }
970        catch(Exception e) {
971          debug.println("Exception resolving transaction:  " + e.toString());
972          throw new DAOException
973            (LetterTemplateExceptionMessage.PROBLEM_STORE_IMAGE + e.getMessage());
974        }
975        DAOUtil.closeResultSet(rs);
976        DAOUtil.closePreparedStatement(ps);
977        DAOUtil.closeConnection(dbConnection);
978      }
979      return answer;
980    }
981  
982  
983    /**
984     *  Loads all [code, description] of the images of the current company;
985     *  ordered by name from DatabaseNames.LETT_IMAGES_REPOSITORY
986     *
987     * @return CodeDescription[] object
988     *      with [code, description] of images
989     * @exception DAOException
990     */
991    public CodeDescription[] loadImagesNamesRepository()
992       throws DAOException {
993      debug.println("loading images names of current company");
994  
995      PreparedStatement ps = null;
996      ResultSet rs = null;
997      String queryStr =
998        " SELECT code_image, name "
999         + " FROM " + DatabaseNames.LETT_IMAGES_REPOSITORY
1000        + " WHERE code_company = ? "
1001        + " ORDER BY name ";
1002     CodeDescription[] answer = null;
1003     ArrayList data = new ArrayList();
1004 
1005     try {
1006       dbConnection = DAOUtil.getDBConnection(datasource);
1007       ps = dbConnection.prepareStatement(queryStr);
1008       ps.setLong(1, Long.parseLong(companyId));
1009       answer = DAOUtil.loadCodeDescription(ps, rs);
1010     }
1011     catch(Exception ae) {
1012       debug.println("Exception:  " + ae.toString());
1013       throw new DAOException
1014         (LetterTemplateExceptionMessage.PROBLEM_LOAD_IMAGES_NAMES + ae.getMessage());
1015     }
1016     finally {
1017       DAOUtil.closeResultSet(rs);
1018       DAOUtil.closePreparedStatement(ps);
1019       DAOUtil.closeConnection(dbConnection);
1020     }
1021     return answer;
1022   }
1023 
1024 
1025   /**
1026    *  Loads an image of the current company; from
1027    *  DatabaseNames.LETT_IMAGES_REPOSITORY
1028    *
1029    * @param nameImage name of image
1030    * @return byte[] with bytes of image
1031    * @exception DAOException
1032    */
1033   public byte[] loadImageRepository(String nameImage)
1034      throws DAOException {
1035     debug.println("loading an image of current company");
1036 
1037     PreparedStatement ps = null;
1038     ResultSet rs = null;
1039     String queryStr =
1040       " SELECT image "
1041        + " FROM " + DatabaseNames.LETT_IMAGES_REPOSITORY
1042        + " WHERE code_company = ?  AND name = ?";
1043     byte[] inBytes = new byte[65534];
1044     // buffer size
1045     byte[] image = new byte[LetterTemplateGlobals.MAX_IMAGE_SIZE];
1046     byte[] answer = null;
1047     int numBytes;
1048 
1049     try {
1050       dbConnection = DAOUtil.getDBConnection(datasource);
1051       ps = dbConnection.prepareStatement(queryStr);
1052       ps.setLong(1, Long.parseLong(companyId));
1053       ps.setString(2, nameImage);
1054       ps.executeQuery();
1055       rs = ps.getResultSet();
1056 
1057       java.sql.Blob theImage = null;
1058       if(rs.next()) {
1059         theImage = rs.getBlob(1);
1060         java.io.InputStream is = theImage.getBinaryStream();
1061 
1062         int contBytes = DAOUtil.inputStreamTobyte(is, image, inBytes);
1063 
1064         answer = new byte[contBytes];
1065         for(int i = 0; i < contBytes; i++) {
1066           answer[i] = image[i];
1067         }
1068       }
1069       else {
1070         debug.println("image not found in DB");
1071         throw new DAOException
1072           (LetterTemplateExceptionMessage.PROBLEM_LOAD_IMAGE_NOT_FOUND + nameImage);
1073       }
1074     }
1075     catch(Exception ae) {
1076       debug.println("Exception:  " + ae.toString());
1077       throw new DAOException
1078         (LetterTemplateExceptionMessage.PROBLEM_LOAD_IMAGE + ae.getMessage());
1079     }
1080     finally {
1081       DAOUtil.closeResultSet(rs);
1082       DAOUtil.closePreparedStatement(ps);
1083       DAOUtil.closeConnection(dbConnection);
1084     }
1085     return answer;
1086   }
1087 
1088 
1089   /**
1090    *  Removes an image of the current company in
1091    *  DatabaseNames.LETT_IMAGES_REPOSITORY
1092    *
1093    * @param nameImage name of image
1094    * @exception DAOException
1095    */
1096   public void removeImageRepository(String nameImage)
1097      throws DAOException {
1098     debug.println("removing an image of name=" + nameImage);
1099 
1100     PreparedStatement ps = null;
1101     String deleteStr =
1102       " DELETE " + DatabaseNames.LETT_IMAGES_REPOSITORY
1103        + " WHERE code_company = ?  AND name = ?";
1104     try {
1105       dbConnection = DAOUtil.getDBConnection(datasource);
1106       ps = dbConnection.prepareStatement(deleteStr);
1107       ps.setLong(1, Long.parseLong(companyId));
1108       ps.setString(2, nameImage);
1109       int num = ps.executeUpdate();
1110       if(num == 1) {
1111         // debug.println("tuple removed");
1112       }
1113       else {
1114         // num == 0
1115         throw new DAOException
1116           (LetterTemplateExceptionMessage.PROBLEM_DELETE_IMAGE_NOT_FOUND + nameImage);
1117       }
1118     }
1119     catch(Exception ae) {
1120       debug.println("Exception:  " + ae.toString());
1121       throw new DAOException
1122         (LetterTemplateExceptionMessage.PROBLEM_DELETE_IMAGE + ae.getMessage());
1123     }
1124     finally {
1125       DAOUtil.closePreparedStatement(ps);
1126       DAOUtil.closeConnection(dbConnection);
1127     }
1128     return;
1129   }
1130 
1131 
1132   /**
1133    *  Applies a set of changes in the images of the current company in
1134    *  DatabaseNames.LETT_IMAGES_REPOSITORY ;
1135    *
1136    * @param items ArrayList with 2 elements of
1137    *      type String[] representing the attributes of items to apply code,
1138    *      name and status; status indicates if the item is for deleting or
1139    *      updating (LetterTemplateGlobals.DELETE, LetterTemplateGlobals.UPDATE).
1140    * @return ArrayList with 2 elements:
1141    *      (0) possible problem (String),
1142    *      (1) current images list (CodeDescription[])
1143    * @exception DAOException
1144    */
1145   public ArrayList applyImagesRepository(ArrayList items)
1146      throws DAOException {
1147     debug.println("applying a set of changes to images of current company");
1148 
1149     PreparedStatement ps2;
1150 
1151     PreparedStatement ps3;
1152     ps2 = ps3 = null;
1153     boolean listsBuilted = false;
1154     boolean successTransaction = false;
1155     CodeDescription item = null;
1156     ArrayList deleteList = new ArrayList();
1157     ArrayList updateList = new ArrayList();
1158     int listSize;
1159 
1160     String deleteStr =
1161       " DELETE " + DatabaseNames.LETT_IMAGES_REPOSITORY
1162        + " WHERE code_image = ?";
1163 
1164     String updateStr =
1165       " UPDATE " + DatabaseNames.LETT_IMAGES_REPOSITORY
1166        + " SET name = ?"
1167        + " WHERE code_image = ?";
1168 
1169     String problem = LetterTemplateGlobals.STR_UNDEF;
1170     CodeDescription[] imagesList = null;
1171     ArrayList answer = null;
1172 
1173     // from items parameter, build 2 sets of items:
1174     // items for deleting and updating
1175     try {
1176       String[] code = (String[])items.get(0);
1177       String[] name = (String[])items.get(1);
1178       String[] status = (String[])items.get(2);
1179       int numItems = code.length;
1180 
1181       for(int i = 0; i < numItems; i++) {
1182         item = new CodeDescription(Long.parseLong(code[i]), name[i]);
1183         if(status[i].equals(LetterTemplateGlobals.DELETE)) {
1184           deleteList.add(item);
1185         }
1186         else if(status[i].equals(LetterTemplateGlobals.UPDATE)) {
1187           updateList.add(item);
1188         }
1189         else {
1190           throw new DAOException
1191             (LetterTemplateExceptionMessage.ITEM_STATUS_INVALID);
1192         }
1193       }
1194       listsBuilted = true;
1195     }
1196     catch(Exception e) {
1197       debug.println("Exception building lists:  " + e.toString());
1198       StringWriter sw = new StringWriter();
1199       PrintWriter pw = new PrintWriter(sw);
1200       e.printStackTrace(pw);
1201       problem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_CHANGES_IMAGES
1202          + e.getMessage()
1203          + "|" + sw.toString();
1204     }
1205 
1206     // apply sets of changes:
1207     if(listsBuilted) {
1208       String phase = "";
1209       try {
1210         dbConnection = DAOUtil.getDBConnection(datasource);
1211         dbConnection.setAutoCommit(false);
1212 
1213         // apply set of deletes:
1214         phase = "delete";
1215         ps2 = dbConnection.prepareStatement(deleteStr);
1216         listSize = deleteList.size();
1217         for(int i = 0; i < listSize; i++) {
1218           item = (CodeDescription)(deleteList.get(i));
1219           ps2.setLong(1, item.getCode());
1220           int num = ps2.executeUpdate();
1221           if(num == 0) {
1222             throw new DAOException
1223               (LetterTemplateExceptionMessage.PROBLEM_APPLYING_DELETES1_IMAGES);
1224           }
1225         }
1226 
1227         // apply set of updates:
1228         phase = "update";
1229         ps3 = dbConnection.prepareStatement(updateStr);
1230         listSize = updateList.size();
1231         for(int i = 0; i < listSize; i++) {
1232           item = (CodeDescription)(updateList.get(i));
1233           ps3.setString(1, item.getDescription());
1234           ps3.setLong(2, item.getCode());
1235           int num = ps3.executeUpdate();
1236           if(num == 0) {
1237             throw new DAOException
1238               (LetterTemplateExceptionMessage.PROBLEM_APPLYING_UPDATES1_IMAGES);
1239           }
1240         }
1241 
1242         successTransaction = true;
1243       }
1244       catch(Exception ae) {
1245         debug.println("Exception applying item to DB in phase " + phase
1246            + " : " + ae.toString());
1247         StringWriter sw = new StringWriter();
1248         PrintWriter pw = new PrintWriter(sw);
1249         ae.printStackTrace(pw);
1250         String subproblem = null;
1251         if(phase.equals("delete")) {
1252           subproblem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_DELETES2_IMAGES;
1253         }
1254         else {
1255           // phase.equals("update")
1256           subproblem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_UPDATES2_IMAGES;
1257         }
1258         String imageName = (item != null) ? item.getDescription() : "";
1259         problem = subproblem
1260            + "current image name: " + imageName
1261            + " :" + ae.getMessage() + "|" + sw.toString();
1262       }
1263       finally {
1264         try {
1265           if(successTransaction) {
1266             dbConnection.commit();
1267           }
1268           else {
1269             dbConnection.rollback();
1270           }
1271         }
1272         catch(Exception e) {
1273           debug.println("Exception resolving transaction:  " + e.toString());
1274           StringWriter sw = new StringWriter();
1275           PrintWriter pw = new PrintWriter(sw);
1276           e.printStackTrace(pw);
1277           problem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_CHANGES_IMAGES
1278              + e.getMessage()
1279              + "|" + sw.toString();
1280         }
1281         DAOUtil.closePreparedStatement(ps2);
1282         DAOUtil.closePreparedStatement(ps3);
1283         DAOUtil.closeConnection(dbConnection);
1284       }
1285     }
1286 
1287     // get current images list:
1288     try {
1289       imagesList = this.loadImagesNamesRepository();
1290       answer = new ArrayList(2);
1291       answer.add(problem);
1292       answer.add(imagesList);
1293     }
1294     catch(Exception ae) {
1295       throw new DAOException
1296         (LetterTemplateExceptionMessage.PROBLEM_LOAD_IMAGES_NAMES + ae.getMessage());
1297     }
1298     return answer;
1299   }
1300 
1301 
1302   // JDBC METHODS WHICH SUPPORT EJB SERVICES CORRESPONDING TO
1303   // MANAGEMENT OF LETTERS TEMPLATES
1304 
1305   /**
1306    *  Stores a letters template for the current company, in tables
1307    *  DatabaseNames.LETT_TEMPLATE, LETT_COMPONENT, LETT_IMAGE, LETT_VARIABLE
1308    *  Generates code for the template if it is new, and generates code for
1309    *  each component if it is new. If the template exists before, its version
1310    *  is validated and the old template is replaced. The associations between
1311    *  the template and its components are established in
1312    *  DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK table, replacing possible old
1313    *  associations
1314    *
1315    * @param template to store
1316    * @return CodeDescription[] with 4
1317    *      [code, stamp] in the following order:
1318    *      template, HEADER, BODY, CLOSING
1319    * @exception DAOException
1320    */
1321   public CodeDescription[] storeTemplate(Template template)
1322      throws DAOException {
1323     debug.println("storing letters template in DB");
1324     PreparedStatement ps = null;
1325     ResultSet rs = null;
1326 
1327     boolean successTransaction = false;
1328     CodeDescription[] answer = null;
1329     long templateCode = template.getCode();
1330     String templateStamp = template.getStamp();
1331     boolean templateIsNew;
1332 
1333     String queryStrVersion =
1334       " SELECT last_changed_date "
1335        + " FROM " + DatabaseNames.LETT_TEMPLATE
1336        + " WHERE code_template = ? "
1337        + " FOR UPDATE";
1338     // exclusive lock
1339 
1340     String insertStrTemplate =
1341       " INSERT INTO " + DatabaseNames.LETT_TEMPLATE
1342        + "  (code_template, code_category, code_print_type,"
1343        + "   description, last_changed_by, last_changed_date,"
1344        + "   left_margin, right_margin, top_margin, bottom_margin)"
1345        + " VALUES("
1346        + DatabaseNames.SEQ_LETT_TEMPLATE + ".nextval,"
1347        + "   ?, ?, ?, ?, SYSDATE, ?, ?, ?, ?)";
1348 
1349     String updateStrTemplate =
1350       " UPDATE " + DatabaseNames.LETT_TEMPLATE + " SET"
1351        + "   code_category = ?,"
1352        + "   code_print_type = ?,"
1353        + "   description = ?,"
1354        + "   last_changed_by = ?,"
1355        + "   last_changed_date = SYSDATE,"
1356        + "   left_margin = ?, "
1357        + "   right_margin = ?, "
1358        + "   top_margin = ?, "
1359        + "   bottom_margin = ? "
1360        + " WHERE code_template = ?";
1361 
1362     String queryStrCodeStamp =
1363       " SELECT code_template, last_changed_date "
1364        + " FROM " + DatabaseNames.LETT_TEMPLATE
1365        + " WHERE code_category = ?  AND code_print_type = ?"
1366        + "    AND description = ?";
1367 
1368     String deleteStrLinks =
1369       " DELETE " + DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK
1370        + " WHERE code_template = ?";
1371 
1372     try {
1373       dbConnection = DAOUtil.getDBConnection(datasource);
1374       dbConnection.setAutoCommit(false);
1375       templateIsNew = (templateCode == LetterTemplateGlobals.UNDEF) ? true : false;
1376 
1377       // verify valid version of existing template:
1378       if(!templateIsNew) {
1379         ps = dbConnection.prepareStatement(queryStrVersion);
1380         ps.setLong(1, templateCode);
1381         ps.executeQuery();
1382         rs = ps.getResultSet();
1383         rs.next();
1384         String version = rs.getString(1);
1385         if(!version.equals(template.getStamp())) {
1386           throw new DAOException
1387             (LetterTemplateExceptionMessage.PROBLEM_STORE_TEMPLATE_INVALID);
1388         }
1389         DAOUtil.closePreparedStatement(ps);
1390       }
1391 
1392       // update o insert template tuple (master) depending of templateIsNew:
1393       if(templateIsNew) {
1394         ps = dbConnection.prepareStatement(insertStrTemplate);
1395         ps.setLong(1, template.getCategory());
1396         ps.setInt(2, template.getPrintType());
1397         ps.setString(3, template.getName());
1398         ps.setLong(4, this.userId.longValue());
1399         ps.setInt(5, template.getLeftMargin());
1400         ps.setInt(6, template.getRightMargin());
1401         ps.setInt(7, template.getTopMargin());
1402         ps.setInt(8, template.getBottomMargin());
1403         ps.executeUpdate();
1404       }
1405       else {
1406         ps = dbConnection.prepareStatement(updateStrTemplate);
1407         ps.setLong(1, template.getCategory());
1408         ps.setInt(2, template.getPrintType());
1409         ps.setString(3, template.getName());
1410         ps.setLong(4, this.userId.longValue());
1411         ps.setInt(5, template.getLeftMargin());
1412         ps.setInt(6, template.getRightMargin());
1413         ps.setInt(7, template.getTopMargin());
1414         ps.setInt(8, template.getBottomMargin());
1415         ps.setLong(9, templateCode);
1416         ps.executeUpdate();
1417       }
1418       DAOUtil.closePreparedStatement(ps);
1419 
1420       // get templateCode and templateStamp from DB :
1421       ps = dbConnection.prepareStatement(queryStrCodeStamp);
1422       ps.setLong(1, template.getCategory());
1423       ps.setInt(2, template.getPrintType());
1424       ps.setString(3, template.getName());
1425       ps.executeQuery();
1426       rs = ps.getResultSet();
1427       rs.next();
1428       templateCode = rs.getLong(1);
1429       templateStamp = rs.getString(2);
1430       DAOUtil.closePreparedStatement(ps);
1431 
1432       // remove old links between template and components :
1433       ps = dbConnection.prepareStatement(deleteStrLinks);
1434       ps.setLong(1, templateCode);
1435       ps.executeUpdate();
1436 
1437       // store each component and link to template in DB:
1438       CodeDescription headerCodeStamp
1439          = auxStoreComponent(template.getHeader(), ps, rs);
1440       linkTemplateComponent(templateCode, headerCodeStamp.getCode(), ps, rs);
1441 
1442       CodeDescription bodyCodeStamp
1443          = auxStoreComponent(template.getBody(), ps, rs);
1444       linkTemplateComponent(templateCode, bodyCodeStamp.getCode(), ps, rs);
1445 
1446       CodeDescription closingCodeStamp
1447          = auxStoreComponent(template.getClosing(), ps, rs);
1448       linkTemplateComponent(templateCode, closingCodeStamp.getCode(), ps, rs);
1449 
1450       // build the answer with the codes:
1451       answer = new CodeDescription[4];
1452       answer[LetterTemplateGlobals.TEMPLATE_INDEX]
1453          = new CodeDescription(templateCode, templateStamp);
1454       answer[LetterTemplateGlobals.HEADER_INDEX] = headerCodeStamp;
1455       answer[LetterTemplateGlobals.BODY_INDEX] = bodyCodeStamp;
1456       answer[LetterTemplateGlobals.CLOSING_INDEX] = closingCodeStamp;
1457 
1458       successTransaction = true;
1459     }
1460     catch(Exception ae) {
1461       debug.println("Exception:  " + ae.toString());
1462       throw new DAOException
1463         (LetterTemplateExceptionMessage.PROBLEM_STORE_TEMPLATE
1464          + ae.getMessage());
1465     }
1466     finally {
1467       try {
1468         if(successTransaction) {
1469           dbConnection.commit();
1470         }
1471         else {
1472           dbConnection.rollback();
1473         }
1474       }
1475       catch(Exception e) {
1476         debug.println("Exception resolving transaction:  " + e.toString());
1477         throw new DAOException
1478           (LetterTemplateExceptionMessage.PROBLEM_STORE_TEMPLATE + e.getMessage());
1479       }
1480       DAOUtil.closeResultSet(rs);
1481       DAOUtil.closePreparedStatement(ps);
1482       DAOUtil.closeConnection(dbConnection);
1483     }
1484     return answer;
1485   }
1486 
1487 
1488   /**
1489    *  Loads code and description of all templates, for the current company and
1490    *  for the specified category; from DatabaseNames.LETT_TEMPLATE table;
1491    *  ordered by name.
1492    *
1493    * @param category specified letter category
1494    * @param printType specified print type
1495    * @return CodeDescription[] object
1496    *      with [code, description] of templates
1497    * @exception DAOException
1498    */
1499   public CodeDescription[] loadTemplatesDescription
1500     (long category, int printType)
1501      throws DAOException {
1502     debug.println("loading templates description");
1503 
1504     PreparedStatement ps = null;
1505     ResultSet rs = null;
1506     String queryStr =
1507       " SELECT code_template, description "
1508        + " FROM " + DatabaseNames.LETT_TEMPLATE
1509        + " WHERE code_category = ? AND code_print_type = ? "
1510        + " ORDER BY description ";
1511     CodeDescription[] answer = null;
1512 
1513     try {
1514       dbConnection = DAOUtil.getDBConnection(datasource);
1515       ps = dbConnection.prepareStatement(queryStr);
1516       ps.setLong(1, category);
1517       ps.setInt(2, printType);
1518       answer = DAOUtil.loadCodeDescription(ps, rs);
1519     }
1520     catch(Exception ae) {
1521       debug.println("Exception:  " + ae.toString());
1522       throw new DAOException
1523         (LetterTemplateExceptionMessage.PROBLEM_LOAD_COMPONENTS_DESCRIPTION
1524          + ae.getMessage());
1525     }
1526     finally {
1527       DAOUtil.closeResultSet(rs);
1528       DAOUtil.closePreparedStatement(ps);
1529       DAOUtil.closeConnection(dbConnection);
1530     }
1531     return answer;
1532   }
1533 
1534 
1535   /**
1536    *  Loads code and description of one template and its components for the
1537    *  specified template code from DatabaseNames.LETT_TEMPLATE,
1538    *  DatabaseNames.LETT_COMPONENT tables
1539    *
1540    * @param templateCode code of template
1541    * @return CodeDescription[] object
1542    *      with [code, description] of template and components in the order:
1543    *      template, HEADER, BODY, CLOSING
1544    * @exception DAOException
1545    */
1546   public CodeDescription[] loadTemplateCodes(long templateCode)
1547      throws DAOException {
1548     debug.println
1549       ("loading code and description for a template and its components");
1550 
1551     PreparedStatement ps = null;
1552     PreparedStatement ps2 = null;
1553     ResultSet rs = null;
1554     ResultSet rs2 = null;
1555     String queryStrTemplate =
1556       " SELECT description "
1557        + " FROM " + DatabaseNames.LETT_TEMPLATE
1558        + " WHERE code_template = ? ";
1559 
1560     String queryStrLink =
1561       " SELECT code_component "
1562        + " FROM " + DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK
1563        + " WHERE  code_template = ? ";
1564 
1565     String queryStrComponent =
1566       " SELECT code_component_type, description "
1567        + " FROM " + DatabaseNames.LETT_COMPONENT
1568        + " WHERE code_component = ? ";
1569 
1570     CodeDescription[] answer = new CodeDescription[4];
1571 
1572     try {
1573       dbConnection = DAOUtil.getDBConnection(datasource);
1574 
1575       // get description of template:
1576       ps = dbConnection.prepareStatement(queryStrTemplate);
1577       ps.setLong(1, templateCode);
1578       ps.executeQuery();
1579       rs = ps.getResultSet();
1580       rs.next();
1581       String templateDescription = rs.getString(1);
1582       answer[LetterTemplateGlobals.TEMPLATE_INDEX]
1583          = new CodeDescription(templateCode, templateDescription);
1584       DAOUtil.closePreparedStatement(ps);
1585 
1586       // get code and description of components
1587       int type;
1588       String componentDescription;
1589       ps = dbConnection.prepareStatement(queryStrLink);
1590       ps.setLong(1, templateCode);
1591       ps.executeQuery();
1592       rs = ps.getResultSet();
1593       while(rs.next()) {
1594         long componentCode = rs.getLong(1);
1595         ps2 = dbConnection.prepareStatement(queryStrComponent);
1596         ps2.setLong(1, componentCode);
1597         ps2.executeQuery();
1598         rs2 = ps2.getResultSet();
1599         rs2.next();
1600         type = rs2.getInt(1);
1601         componentDescription = rs2.getString(2);
1602 
1603         if(type == LetterComponent.HEADER) {
1604           answer[LetterTemplateGlobals.HEADER_INDEX]
1605              = new CodeDescription(componentCode, componentDescription);
1606         }
1607         else if(type == LetterComponent.BODY) {
1608           answer[LetterTemplateGlobals.BODY_INDEX]
1609              = new CodeDescription(componentCode, componentDescription);
1610         }
1611         else {
1612           //type == LetterComponent.CLOSING
1613           answer[LetterTemplateGlobals.CLOSING_INDEX]
1614              = new CodeDescription(componentCode, componentDescription);
1615         }
1616       }
1617     }
1618     catch(Exception ae) {
1619       debug.println("Exception:  " + ae.toString());
1620       throw new DAOException
1621         (LetterTemplateExceptionMessage.PROBLEM_LOAD_CODES_DESCRIPTIONS_TEMPLATE
1622          + ae.getMessage());
1623     }
1624     finally {
1625       DAOUtil.closeResultSet(rs2);
1626       DAOUtil.closePreparedStatement(ps2);
1627       DAOUtil.closeResultSet(rs);
1628       DAOUtil.closePreparedStatement(ps);
1629       DAOUtil.closeConnection(dbConnection);
1630     }
1631     return answer;
1632   }
1633 
1634 
1635   /**
1636    *  Loads code and stamp of one template and its components for the
1637    *  specified template code from DatabaseNames.LETT_TEMPLATE,
1638    *  DatabaseNames.LETT_COMPONENT tables
1639    *
1640    * @param category category of template
1641    * @param printType type of print
1642    * @param name name of template
1643    * @return CodeDescription[] composed
1644    *      by [code, stamp] of template and its components
1645    *      ordered by template, HEADER, BODY, CLOSING
1646    * @exception DAOException
1647    */
1648   public CodeDescription[] loadTemplateCodes
1649     (long category, int printType, String name)
1650      throws DAOException {
1651     debug.println
1652       ("loading code and stamp for a template and its components");
1653 
1654     PreparedStatement ps = null;
1655     PreparedStatement ps2 = null;
1656     ResultSet rs = null;
1657     ResultSet rs2 = null;
1658     String queryStrTemplate =
1659       " SELECT code_template, last_changed_date "
1660        + " FROM " + DatabaseNames.LETT_TEMPLATE
1661        + " WHERE code_category = ? "
1662        + "    AND code_print_type = ? "
1663        + "    AND description = ? ";
1664 
1665     String queryStrLink =
1666       " SELECT code_component "
1667        + " FROM " + DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK
1668        + " WHERE  code_template = ? ";
1669 
1670     String queryStrComponent =
1671       " SELECT code_component_type, last_changed_date "
1672        + " FROM " + DatabaseNames.LETT_COMPONENT
1673        + " WHERE code_component = ? ";
1674 
1675     CodeDescription[] answer = new CodeDescription[4];
1676 
1677     try {
1678       dbConnection = DAOUtil.getDBConnection(datasource);
1679 
1680       // get code and stamp of template:
1681       ps = dbConnection.prepareStatement(queryStrTemplate);
1682       ps.setLong(1, category);
1683       ps.setInt(2, printType);
1684       ps.setString(3, name);
1685       ps.executeQuery();
1686       rs = ps.getResultSet();
1687       rs.next();
1688       long templateCode = rs.getLong(1);
1689       String templateStamp = rs.getString(2);
1690       answer[LetterTemplateGlobals.TEMPLATE_INDEX]
1691          = new CodeDescription(templateCode, templateStamp);
1692       DAOUtil.closePreparedStatement(ps);
1693 
1694       // get code and stamp of components
1695       int type;
1696       String componentStamp;
1697       ps = dbConnection.prepareStatement(queryStrLink);
1698       ps.setLong(1, templateCode);
1699       ps.executeQuery();
1700       rs = ps.getResultSet();
1701       while(rs.next()) {
1702         long componentCode = rs.getLong(1);
1703         ps2 = dbConnection.prepareStatement(queryStrComponent);
1704         ps2.setLong(1, componentCode);
1705         ps2.executeQuery();
1706         rs2 = ps2.getResultSet();
1707         rs2.next();
1708         type = rs2.getInt(1);
1709         componentStamp = rs2.getString(2);
1710         if(type == LetterComponent.HEADER) {
1711           answer[LetterTemplateGlobals.HEADER_INDEX]
1712              = new CodeDescription(componentCode, componentStamp);
1713         }
1714         else if(type == LetterComponent.BODY) {
1715           answer[LetterTemplateGlobals.BODY_INDEX]
1716              = new CodeDescription(componentCode, componentStamp);
1717         }
1718         else {
1719           //type == LetterComponent.CLOSING
1720           answer[LetterTemplateGlobals.CLOSING_INDEX]
1721              = new CodeDescription(componentCode, componentStamp);
1722         }
1723       }
1724     }
1725     catch(Exception ae) {
1726       debug.println("Exception:  " + ae.toString());
1727       throw new DAOException
1728         (LetterTemplateExceptionMessage.PROBLEM_LOAD_CODES_STAMPS_TEMPLATE
1729          + ae.getMessage());
1730     }
1731     finally {
1732       DAOUtil.closeResultSet(rs2);
1733       DAOUtil.closePreparedStatement(ps2);
1734       DAOUtil.closeResultSet(rs);
1735       DAOUtil.closePreparedStatement(ps);
1736       DAOUtil.closeConnection(dbConnection);
1737     }
1738     return answer;
1739   }
1740 
1741 
1742   /**
1743    *  Loads code and description of one template and its components for the
1744    *  specified template code from DatabaseNames.LETT_TEMPLATE,
1745    *  DatabaseNames.LETT_COMPONENT tables
1746    *
1747    * @param category category of template
1748    * @param printType type of print
1749    * @param name name of template
1750    * @return CodeDescription[] composed
1751    *      by [code, description] of template and its components ordered by
1752    *      template, HEADER, BODY, CLOSING
1753    * @exception DAOException
1754    */
1755   public CodeDescription[] loadTemplateCodeDescription
1756     (long category, int printType, String name)
1757      throws DAOException {
1758     debug.println
1759       ("loading code and description for a template and its components");
1760 
1761     PreparedStatement ps = null;
1762     ResultSet rs = null;
1763     CodeDescription[] answer = null;
1764     String queryStrTemplate =
1765       " SELECT code_template "
1766        + " FROM " + DatabaseNames.LETT_TEMPLATE
1767        + " WHERE code_category = ? "
1768        + "    AND code_print_type = ? "
1769        + "    AND description = ? ";
1770 
1771     try {
1772       dbConnection = DAOUtil.getDBConnection(datasource);
1773       // get code and stamp of template:
1774       ps = dbConnection.prepareStatement(queryStrTemplate);
1775       ps.setLong(1, category);
1776       ps.setInt(2, printType);
1777       ps.setString(3, name);
1778       ps.executeQuery();
1779       rs = ps.getResultSet();
1780       rs.next();
1781       long templateCode = rs.getLong(1);
1782       answer = this.loadTemplateCodes(templateCode);
1783     }
1784     catch(Exception ae) {
1785       debug.println("Exception:  " + ae.toString());
1786       throw new DAOException
1787         (LetterTemplateExceptionMessage.PROBLEM_LOAD_CODES_DESCRIPTIONS_TEMPLATE
1788          + ae.getMessage());
1789     }
1790     finally {
1791       DAOUtil.closeResultSet(rs);
1792       DAOUtil.closePreparedStatement(ps);
1793       DAOUtil.closeConnection(dbConnection);
1794     }
1795     return answer;
1796   }
1797 
1798 
1799   /**
1800    *  Loads code and stamp of template and components from
1801    *  DatabaseNames.LETT_TEMPLATE and LETT_COMPONENT tables
1802    *
1803    * @param category category of template
1804    * @param printType type of print
1805    * @param name name of template
1806    * @param header name of component header
1807    * @param body name of component body
1808    * @param closing name of component closing
1809    * @return CodeDescription[i] for i = 1(HEADER),2(BODY),3(CLOSING) is:
1810    *          [code, stamp] of component, if it exists,
1811    *          [LetterTemplateGlobals.UNDEF,LetterTemplateGlobals.STR_UNDEF] if component doesn't exist
1812    * @exception DAOException
1813    */
1814   public CodeDescription[] loadCodesStamps
1815     (long category, int printType, String name,
1816      String header, String body, String closing)
1817      throws DAOException {
1818 
1819     debug.println
1820       ("loading code and stamp for a template and its components");
1821 
1822     long code = LetterTemplateGlobals.UNDEF;
1823     String stamp = LetterTemplateGlobals.STR_UNDEF;
1824     PreparedStatement ps = null;
1825     ResultSet rs = null;
1826     String queryStrTemplate =
1827       " SELECT code_template, last_changed_date "
1828        + " FROM " + DatabaseNames.LETT_TEMPLATE
1829        + " WHERE code_category = ? "
1830        + "   AND code_print_type = ? "
1831        + "   AND description = ? ";
1832 
1833     CodeDescription temp_answer = null;
1834     CodeDescription[] answer = new CodeDescription[4];
1835 
1836     try {
1837       dbConnection = DAOUtil.getDBConnection(datasource);
1838 
1839       // get code and stamp of template:
1840       ps = dbConnection.prepareStatement(queryStrTemplate);
1841       ps.setLong(1, category);
1842       ps.setInt(2, printType);
1843       ps.setString(3, name);
1844       ps.executeQuery();
1845       rs = ps.getResultSet();
1846       if(rs.next()) {
1847         code = rs.getLong(1);
1848         stamp = rs.getString(2);
1849       }
1850       answer[LetterTemplateGlobals.TEMPLATE_INDEX]
1851          = new CodeDescription(code, stamp);
1852 
1853       // get code and stamp of components
1854       temp_answer =
1855         this.loadComponentCode(LetterComponent.HEADER, printType, header);
1856       answer[LetterTemplateGlobals.HEADER_INDEX]
1857          = new CodeDescription(temp_answer.getCode(),
1858         temp_answer.getDescription());
1859 
1860       temp_answer =
1861         this.loadComponentCode(LetterComponent.BODY, printType, body);
1862       answer[LetterTemplateGlobals.BODY_INDEX]
1863          = new CodeDescription(temp_answer.getCode(),
1864         temp_answer.getDescription());
1865 
1866       temp_answer =
1867         this.loadComponentCode(LetterComponent.CLOSING, printType, closing);
1868       answer[LetterTemplateGlobals.CLOSING_INDEX]
1869          = new CodeDescription(temp_answer.getCode(),
1870         temp_answer.getDescription());
1871     }
1872     catch(Exception ae) {
1873       debug.println("Exception: (DAO) loadCodesStamps " +
1874         ps.toString() + "\n" + ae.toString());
1875       throw new DAOException
1876         (LetterTemplateExceptionMessage.PROBLEM_LOAD_CODES_STAMPS_TEMPLATE
1877          + ae.getMessage());
1878     }
1879     finally {
1880       DAOUtil.closeResultSet(rs);
1881       DAOUtil.closePreparedStatement(ps);
1882       DAOUtil.closeConnection(dbConnection);
1883     }
1884     return answer;
1885   }
1886 
1887 
1888   /**
1889    *  Loads a letters template of the current company, corresponding to a
1890    *  code, from tables DatabaseNames.LETT_TEMPLATE,
1891    *  LETT_TEMPLATE_COMPONENT_LINK, LETT_COMPONENT, LETT_IMAGE, LETT_VARIABLE
1892    *
1893    * @param templateCode code of template
1894    * @return Template selected
1895    * @exception DAOException
1896    */
1897   public Template loadTemplate(long templateCode)
1898      throws DAOException {
1899     debug.println("loading letters template from DB");
1900     PreparedStatement ps = null;
1901     ResultSet rs = null;
1902     Template answer = null;
1903     boolean successTransaction = false;
1904 
1905     // elements of template:
1906     long category;
1907     int printType;
1908     int leftMargin;
1909     int rightMargin;
1910     int topMargin;
1911     int bottomMargin;
1912     String name;
1913     String stamp;
1914     LetterComponent header = null;
1915     LetterComponent body = null;
1916     LetterComponent closing = null;
1917 
1918     String queryStrTemplate =
1919       " SELECT code_category, code_print_type, description,"
1920        + "        last_changed_date, left_margin, right_margin,"
1921        + "        top_margin, bottom_margin "
1922        + " FROM " + DatabaseNames.LETT_TEMPLATE
1923        + " WHERE code_template = ? "
1924        + " FOR UPDATE";
1925     // exclusive lock
1926 
1927     String queryStrLink =
1928       " SELECT code_component "
1929        + " FROM " + DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK
1930        + " WHERE  code_template = ? ";
1931 
1932     try {
1933       dbConnection = DAOUtil.getDBConnection(datasource);
1934       dbConnection.setAutoCommit(false);
1935 
1936       // select template tuple (master) :
1937       ps = dbConnection.prepareStatement(queryStrTemplate);
1938       ps.setLong(1, templateCode);
1939       ps.executeQuery();
1940       rs = ps.getResultSet();
1941       rs.next();
1942       category = rs.getLong(1);
1943       printType = rs.getInt(2);
1944       name = rs.getString(3);
1945       stamp = rs.getString(4);
1946       leftMargin = rs.getInt(5);
1947       rightMargin = rs.getInt(6);
1948       topMargin = rs.getInt(7);
1949       bottomMargin = rs.getInt(8);
1950       DAOUtil.closePreparedStatement(ps);
1951 
1952       // get components of template
1953       ps = dbConnection.prepareStatement(queryStrLink);
1954       ps.setLong(1, templateCode);
1955       ps.executeQuery();
1956       rs = ps.getResultSet();
1957       while(rs.next()) {
1958         long componentCode = rs.getLong(1);
1959         LetterComponent component
1960            = auxLoadComponent(componentCode, ps, rs);
1961         if(component.getType() == LetterComponent.HEADER) {
1962           header = component;
1963         }
1964         else if(component.getType() == LetterComponent.BODY) {
1965           body = component;
1966         }
1967         else {
1968           //component.getType() == LetterComponent.CLOSING
1969           closing = component;
1970         }
1971       }
1972 
1973       answer = new Template(templateCode, name, category, printType,
1974         header, body, closing, stamp, leftMargin, rightMargin,
1975         topMargin, bottomMargin);
1976       successTransaction = true;
1977     }
1978     catch(Exception ae) {
1979       debug.println("Exception:  " + ae.toString());
1980       throw new DAOException
1981         (LetterTemplateExceptionMessage.PROBLEM_LOAD_TEMPLATE + " of code "
1982          + String.valueOf(templateCode) + " : " + ae.getMessage());
1983     }
1984     finally {
1985       try {
1986         if(successTransaction) {
1987           dbConnection.commit();
1988         }
1989         else {
1990           dbConnection.rollback();
1991         }
1992       }
1993       catch(Exception e) {
1994         debug.println("Exception resolving transaction:  " + e.toString());
1995         throw new DAOException
1996           (LetterTemplateExceptionMessage.PROBLEM_LOAD_TEMPLATE + e.getMessage());
1997       }
1998       DAOUtil.closeResultSet(rs);
1999       DAOUtil.closePreparedStatement(ps);
2000       DAOUtil.closeConnection(dbConnection);
2001     }
2002     return answer;
2003   }
2004 
2005 
2006   /**
2007    *  Removes a letters template (not its components) of the current company,
2008    *  corresponding to a code, from tables DatabaseNames.LETT_TEMPLATE and
2009    *  LETT_TEMPLATE_COMPONENT_LINK
2010    *
2011    * @param templateCode code of template
2012    * @exception DAOException
2013    */
2014   public void removeTemplate(long templateCode)
2015      throws DAOException {
2016     debug.println("removing letters template from DB");
2017     PreparedStatement ps = null;
2018     ResultSet rs = null;
2019     boolean successTransaction = false;
2020 
2021     String deleteStrLinks =
2022       " DELETE " + DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK
2023        + " WHERE code_template = ?";
2024 
2025     String deleteStrTemplate =
2026       " DELETE " + DatabaseNames.LETT_TEMPLATE
2027        + " WHERE code_template = ?";
2028 
2029     try {
2030       dbConnection = DAOUtil.getDBConnection(datasource);
2031       dbConnection.setAutoCommit(false);
2032 
2033       // remove links between template and components :
2034       ps = dbConnection.prepareStatement(deleteStrLinks);
2035       ps.setLong(1, templateCode);
2036       ps.executeUpdate();
2037       DAOUtil.closePreparedStatement(ps);
2038 
2039       // remove template:
2040       ps = dbConnection.prepareStatement(deleteStrTemplate);
2041       ps.setLong(1, templateCode);
2042       ps.executeUpdate();
2043 
2044       successTransaction = true;
2045     }
2046     catch(Exception ae) {
2047       debug.println("Exception:  " + ae.toString());
2048       throw new DAOException
2049         (LetterTemplateExceptionMessage.PROBLEM_DELETE_TEMPLATE + " of code "
2050          + String.valueOf(templateCode) + " : " + ae.getMessage());
2051     }
2052     finally {
2053       try {
2054         if(successTransaction) {
2055           dbConnection.commit();
2056         }
2057         else {
2058           dbConnection.rollback();
2059         }
2060       }
2061       catch(Exception e) {
2062         debug.println("Exception resolving transaction:  " + e.toString());
2063         throw new DAOException
2064           (LetterTemplateExceptionMessage.PROBLEM_DELETE_TEMPLATE + e.getMessage());
2065       }
2066       DAOUtil.closeResultSet(rs);
2067       DAOUtil.closePreparedStatement(ps);
2068       DAOUtil.closeConnection(dbConnection);
2069     }
2070   }
2071 
2072 
2073   /**
2074    *  Loads code, print type, category and name of templates
2075    *  and their categories names.
2076    *  from DatabaseNames.LETT_TEMPLATE, LETT_CATEGORY, LETT_PRINT_TYPE.
2077    *
2078    * @return ArrayList of variables where each element is an
2079    *            inner ArrayList with the following elements of a variable:
2080    *                code(Long): code of template,
2081    *                nameCategory(String): name of category,
2082    *                type(String): print type,
2083    *                nameTemplate (String): name of template.
2084    * @exception DAOException
2085    */
2086   public ArrayList loadAllTemplatesDescription()
2087      throws DAOException {
2088 
2089     debug.println("loading all templates description");
2090 
2091     PreparedStatement ps = null;
2092     ResultSet rs = null;
2093     String queryStrFields =
2094       " SELECT t.code_template, c.description, p.description, t.description "
2095        + " FROM " + DatabaseNames.LETT_TEMPLATE + " t ,"
2096        + DatabaseNames.LETT_CATEGORY + " c ,"
2097        + DatabaseNames.LETT_PRINT_TYPE + " p "
2098        + " WHERE  c.code_company = ?  "
2099        + "   AND  c.code_category = t.code_category "
2100        + "   AND  t.code_print_type = p.code_print_type "
2101        + " ORDER BY  c.description, t.description, p.description ";
2102 
2103     ArrayList answer = new ArrayList();
2104 
2105     try {
2106       dbConnection = DAOUtil.getDBConnection(datasource);
2107       ps = dbConnection.prepareStatement(queryStrFields);
2108       ps.setLong(1, Long.parseLong(companyId));
2109       ps.executeQuery();
2110       rs = ps.getResultSet();
2111       while(rs.next()) {
2112         Long code = new Long(rs.getLong(1));
2113         String nameCategory = (rs.getString(2)).trim();
2114         String type = rs.getString(3).trim();
2115         String nameTemplate = rs.getString(4).trim();
2116         ArrayList tuple = new ArrayList(4);
2117         tuple.add(code);
2118         tuple.add(nameCategory);
2119         tuple.add(type);
2120         tuple.add(nameTemplate);
2121         answer.add(tuple);
2122       }
2123     }
2124     catch(Exception ae) {
2125       debug.println("Exception:  " + ae.toString());
2126       throw new DAOException
2127         (LetterTemplateExceptionMessage.PROBLEM_LOAD_TEMPLATES_DESCRIPTION
2128          + ae.getMessage());
2129     }
2130     finally {
2131       DAOUtil.closeResultSet(rs);
2132       DAOUtil.closePreparedStatement(ps);
2133       DAOUtil.closeConnection(dbConnection);
2134     }
2135     return answer;
2136   }
2137 
2138 
2139   /**
2140    *  Applies a set of changes in the templates of the current company from
2141    *  DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK and LETT_TEMPLATE.
2142    *
2143    * @param items ArrayList with 4 elements of
2144    *      type String[] representing the attributes of items to apply:
2145    *      code of template, code of category, name of template and status;
2146    *      status indicates if the item is for deleting or updating
2147    *      (LetterTemplateGlobals.DELETE, LetterTemplateGlobals.UPDATE).
2148    * @return ArrayList with 2 elements:
2149    *      (0) possible problem (String),
2150    *      (1) current Template description list (ArrayList)
2151    * @exception DAOException
2152    */
2153   public ArrayList applyItemsTemplate(ArrayList items) throws DAOException {
2154 
2155     debug.println("applying a set of changes to template of current company");
2156     PreparedStatement ps1;
2157     PreparedStatement ps2;
2158     PreparedStatement ps3;
2159     ps1 = ps2 = ps3 = null;
2160     boolean listsBuilted = false;
2161     boolean successTransaction = false;
2162     ArrayList item = new ArrayList();
2163     ArrayList deleteList = new ArrayList();
2164     ArrayList updateList = new ArrayList();
2165     int listSize;
2166 
2167     String deleteStrLink =
2168       " DELETE " + DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK
2169        + " WHERE code_template = ?";
2170 
2171     String deleteStrTempl =
2172       " DELETE " + DatabaseNames.LETT_TEMPLATE
2173        + " WHERE code_template = ?";
2174 
2175     String updateStrTempl =
2176       " UPDATE " + DatabaseNames.LETT_TEMPLATE + " SET"
2177        + " code_category = ?,"
2178        + " description = ?,"
2179        + " last_changed_by = ?,"
2180        + " last_changed_date = SYSDATE"
2181        + " WHERE code_template = ?";
2182 
2183     String problem = LetterTemplateGlobals.STR_UNDEF;
2184     ArrayList templatesList = new ArrayList();
2185     ArrayList answer = null;
2186 
2187     // from items parameter, build 2 sets of items:
2188     // items for deleting and updating
2189     try {
2190       String[] codeTemplate = (String[])items.get(0);
2191       String[] codeCategory = (String[])items.get(1);
2192       String[] name = (String[])items.get(2);
2193       String[] status = (String[])items.get(3);
2194       int numItems = codeTemplate.length;
2195 
2196       for(int i = 0; i < numItems; i++) {
2197         ArrayList slot = new ArrayList(3);
2198         slot.add(codeTemplate[i]);
2199         slot.add(codeCategory[i]);
2200         slot.add(name[i]);
2201         if(status[i].equals(LetterTemplateGlobals.DELETE)) {
2202           deleteList.add(slot);
2203         }
2204         else if(status[i].equals(LetterTemplateGlobals.UPDATE)) {
2205           updateList.add(slot);
2206         }
2207         else {
2208           throw new DAOException
2209             (LetterTemplateExceptionMessage.ITEM_STATUS_INVALID);
2210         }
2211       }
2212       listsBuilted = true;
2213     }
2214     catch(Exception e) {
2215       debug.println("Exception building lists:  " + e.toString());
2216       StringWriter sw = new StringWriter();
2217       PrintWriter pw = new PrintWriter(sw);
2218       e.printStackTrace(pw);
2219       problem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_CHANGES_TEMPLATES
2220          + e.getMessage()
2221          + "|" + sw.toString();
2222     }
2223 
2224     // apply sets of changes:
2225     if(listsBuilted) {
2226       String phase = "";
2227       try {
2228         dbConnection = DAOUtil.getDBConnection(datasource);
2229         dbConnection.setAutoCommit(false);
2230 
2231         // apply set of deletes:
2232         phase = "delete";
2233         ps1 = dbConnection.prepareStatement(deleteStrLink);
2234         ps2 = dbConnection.prepareStatement(deleteStrTempl);
2235         listSize = deleteList.size();
2236         for(int i = 0; i < listSize; i++) {
2237           item = ((ArrayList)(deleteList.get(i)));
2238           ps1.setLong(1, Long.parseLong(((String)item.get(0))));
2239           ps2.setLong(1, Long.parseLong(((String)item.get(0))));
2240           try {
2241             ps1.executeUpdate();
2242             int num = ps2.executeUpdate();
2243             if(num == 0) {
2244               throw new DAOException
2245                 (LetterTemplateExceptionMessage.PROBLEM_APPLYING_DELETES1_TEMPLATES);
2246             }
2247           }
2248           catch(DAOException da) {
2249             throw new DAOException(da.getMessage());
2250           }
2251           catch(Exception ee) {
2252             throw new DAOException(LetterTemplateExceptionMessage.PROBLEM_APPLYING_DELETES11_TEMPLATES
2253                + ee.getMessage());
2254           }
2255         }
2256 
2257         // apply set of updates:
2258         phase = "update";
2259         ps3 = dbConnection.prepareStatement(updateStrTempl);
2260         listSize = updateList.size();
2261         for(int i = 0; i < listSize; i++) {
2262           item = ((ArrayList)(updateList.get(i)));
2263           ps3.setLong(1, Long.parseLong(((String)item.get(1))));
2264           ps3.setString(2, ((String)(item.get(2))));
2265           ps3.setLong(3, this.userId.longValue());
2266           ps3.setLong(4, Long.parseLong(((String)item.get(0))));
2267           int num = ps3.executeUpdate();
2268           if(num == 0) {
2269             throw new DAOException
2270               (LetterTemplateExceptionMessage.PROBLEM_APPLYING_UPDATES1_TEMPLATES);
2271           }
2272         }
2273         successTransaction = true;
2274       }
2275       catch(Exception ae) {
2276         debug.println("Exception applying item to DB in phase " + phase
2277            + " : " + ae.toString());
2278         StringWriter sw = new StringWriter();
2279         PrintWriter pw = new PrintWriter(sw);
2280         ae.printStackTrace(pw);
2281         String subproblem = null;
2282         if(phase.equals("delete")) {
2283           subproblem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_DELETES2_TEMPLATES;
2284         }
2285         else {
2286           // phase.equals("update")
2287           subproblem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_UPDATES2_TEMPLATES;
2288         }
2289         String templateName = (item != null) ? ((String)(item.get(2))) : "";
2290         problem = subproblem
2291            + "current template name: " + templateName
2292            + " :" + ae.getMessage() + "|" + sw.toString();
2293       }
2294       finally {
2295         try {
2296           if(successTransaction) {
2297             dbConnection.commit();
2298           }
2299           else {
2300             dbConnection.rollback();
2301           }
2302         }
2303         catch(Exception e) {
2304           debug.println("Exception resolving transaction:  " + e.toString());
2305           StringWriter sw = new StringWriter();
2306           PrintWriter pw = new PrintWriter(sw);
2307           e.printStackTrace(pw);
2308           problem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_CHANGES_TEMPLATES
2309              + e.getMessage()
2310              + "|" + sw.toString();
2311         }
2312         DAOUtil.closePreparedStatement(ps1);
2313         DAOUtil.closePreparedStatement(ps2);
2314         DAOUtil.closePreparedStatement(ps3);
2315         DAOUtil.closeConnection(dbConnection);
2316       }
2317     }
2318 
2319     // get current images list:
2320     try {
2321       templatesList = this.loadAllTemplatesDescription();
2322       answer = new ArrayList(2);
2323       answer.add(problem);
2324       answer.add(templatesList);
2325     }
2326     catch(Exception ae) {
2327       throw new DAOException
2328         (LetterTemplateExceptionMessage.PROBLEM_LOAD_TEMPLATE + ae.getMessage());
2329     }
2330     return answer;
2331   }
2332 
2333 
2334   /**
2335    *  Load the date of template from DatabaseNames.LETT_TEMPLATE table.
2336    *
2337    * @param templateCode Code of template.
2338    * @return date date of template.
2339    * @exception DAOException
2340    */
2341   public Date loadTemplateDate(long templateCode) throws DAOException {
2342 
2343     debug.println("loading date template from DB");
2344     PreparedStatement ps = null;
2345     ResultSet rs = null;
2346     Date answer = null;
2347     String queryStrTemplate =
2348       " SELECT last_changed_date"
2349        + " FROM " + DatabaseNames.LETT_TEMPLATE
2350        + " WHERE code_template = ? ";
2351 
2352     try {
2353       dbConnection = DAOUtil.getDBConnection(datasource);
2354       ps = dbConnection.prepareStatement(queryStrTemplate);
2355       ps.setLong(1, templateCode);
2356       ps.executeQuery();
2357       rs = ps.getResultSet();
2358       rs.next();
2359       answer = rs.getDate(1);
2360     }
2361     catch(Exception ae) {
2362       debug.println(CommonUtil.stackTraceToString(ae));
2363       throw new DAOException
2364         (LetterTemplateExceptionMessage.PROBLEM_LOAD_STAMP_TEMPLATE
2365          + ae.getMessage());
2366     }
2367     finally {
2368       DAOUtil.closeResultSet(rs);
2369       DAOUtil.closePreparedStatement(ps);
2370       DAOUtil.closeConnection(dbConnection);
2371     }
2372     return answer;
2373   }
2374 
2375 
2376   // JDBC METHODS WHICH SUPPORT EJB SERVICES CORRESPONDING TO
2377   // MANAGEMENT OF LETTERS COMPONENTS
2378 
2379   /**
2380    *  Stores a letters component for the current company, in tables
2381    *  DatabaseNames.LETT_COMPONENT, LETT_IMAGE, LETT_VARIABLE Generates code
2382    *  for the component if it is new. If the component exists before, its
2383    *  version is validated and the old component is replaced.
2384    *
2385    * @param component is the letter component to store
2386    * @return CodeDescription: [code, stamp] of component
2387    * @exception DAOException
2388    */
2389   public CodeDescription storeComponent(LetterComponent component)
2390      throws DAOException {
2391     debug.println("storing letters component in DB");
2392     PreparedStatement ps = null;
2393     ResultSet rs = null;
2394 
2395     boolean successTransaction = false;
2396     CodeDescription answer = null;
2397     // [code, stamp] of component
2398 
2399     try {
2400       dbConnection = DAOUtil.getDBConnection(datasource);
2401       dbConnection.setAutoCommit(false);
2402       answer = auxStoreComponent(component, ps, rs);
2403       successTransaction = true;
2404     }
2405     catch(Exception ae) {
2406       debug.println("Exception:  " + ae.toString());
2407       throw new DAOException
2408         (LetterTemplateExceptionMessage.PROBLEM_STORE_COMPONENT + ae.getMessage());
2409     }
2410     finally {
2411       try {
2412         if(successTransaction) {
2413           dbConnection.commit();
2414         }
2415         else {
2416           dbConnection.rollback();
2417         }
2418       }
2419       catch(Exception e) {
2420         debug.println("Exception resolving transaction:  " + e.toString());
2421         throw new DAOException
2422           (LetterTemplateExceptionMessage.PROBLEM_STORE_COMPONENT + e.getMessage());
2423       }
2424       DAOUtil.closeResultSet(rs);
2425       DAOUtil.closePreparedStatement(ps);
2426       DAOUtil.closeConnection(dbConnection);
2427     }
2428     return answer;
2429   }
2430 
2431 
2432   /**
2433    *  Store as a letters component for the current company in tables
2434    *  DatabaseNames.LETT_COMPONENT, LETT_IMAGE, LETT_VARIABLE generating code
2435    *  for the component if it is new. If the component exists before, its
2436    *  version is validated and the old component is replaced. The association
2437    *  between the template and the component is established in
2438    *  DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK table
2439    *
2440    * @param templateCode code of template
2441    * @param component is the letter component to store
2442    * @return CodeDescription: [code,  stamp] of component
2443    * @exception DAOException
2444    */
2445 
2446   public CodeDescription storeComponentAs(long templateCode,
2447                                           LetterComponent component)
2448      throws DAOException {
2449 
2450     debug.println("storing as letters component in DB");
2451     PreparedStatement ps = null;
2452     ResultSet rs = null;
2453 
2454     String deleteStrLinks =
2455       " DELETE " + DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK
2456        + " WHERE code_template = ?"
2457        + "   AND code_component = ? ";
2458 
2459     String queryStrLink =
2460       " SELECT l.code_component "
2461        + " FROM " + DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK + " l ,"
2462        + DatabaseNames.LETT_COMPONENT + " c "
2463        + " WHERE l.code_component = c.code_component  "
2464        + "    AND l.code_template = ? "
2465        + "    AND c.code_component_type = ? ";
2466 
2467     boolean successTransaction = false;
2468 
2469     CodeDescription answer = null;
2470     // [code, stamp] of component
2471 
2472     try {
2473       dbConnection = DAOUtil.getDBConnection(datasource);
2474       dbConnection.setAutoCommit(false);
2475       answer = auxStoreComponent(component, ps, rs);
2476 
2477       // get code of old component corresponding to type of new component
2478       ps = dbConnection.prepareStatement(queryStrLink);
2479       ps.setLong(1, templateCode);
2480       ps.setInt(2, component.getType());
2481       ps.executeQuery();
2482       rs = ps.getResultSet();
2483       rs.next();
2484       long oldComponentCode = rs.getLong(1);
2485       DAOUtil.closePreparedStatement(ps);
2486 
2487       // remove link between template and old component :
2488       ps = dbConnection.prepareStatement(deleteStrLinks);
2489       ps.setLong(1, templateCode);
2490       ps.setLong(2, oldComponentCode);
2491       ps.executeUpdate();
2492 
2493       // link new component to template in DB:
2494       linkTemplateComponent(templateCode, answer.getCode(), ps, rs);
2495       successTransaction = true;
2496     }
2497     catch(Exception ae) {
2498       debug.println("Exception:  " + ae.toString());
2499       throw new DAOException
2500         (LetterTemplateExceptionMessage.PROBLEM_STORE_AS_COMPONENT + ae.getMessage());
2501     }
2502     finally {
2503       try {
2504         if(successTransaction) {
2505           dbConnection.commit();
2506         }
2507         else {
2508           dbConnection.rollback();
2509         }
2510       }
2511       catch(Exception e) {
2512         debug.println("Exception resolving transaction:  " + e.toString());
2513         throw new DAOException
2514           (LetterTemplateExceptionMessage.PROBLEM_STORE_COMPONENT + e.getMessage());
2515       }
2516       DAOUtil.closeResultSet(rs);
2517       DAOUtil.closePreparedStatement(ps);
2518       DAOUtil.closeConnection(dbConnection);
2519     }
2520     return answer;
2521   }
2522 
2523 
2524   /**
2525    *  Loads code and description of all components, for the current company,
2526    *  for the specified component type and print type; from
2527    *  DatabaseNames.LETT_COMPONENT table; ordered by name
2528    *
2529    * @param componentType type of components to load
2530    * @param printType print type of components to load
2531    * @return CodeDescription[] object with [code, description] of components
2532    * @exception DAOException
2533    */
2534   public CodeDescription[] loadComponentsDescription
2535     (int componentType, int printType)
2536      throws DAOException {
2537     debug.println("loading components description");
2538 
2539     PreparedStatement ps = null;
2540     ResultSet rs = null;
2541     String queryStr =
2542       " SELECT code_component, description "
2543        + " FROM " + DatabaseNames.LETT_COMPONENT
2544        + " WHERE code_company = ? AND code_component_type = ? "
2545        + "   AND code_print_type = ?"
2546        + " ORDER BY description ";
2547     CodeDescription[] answer = null;
2548 
2549     try {
2550       dbConnection = DAOUtil.getDBConnection(datasource);
2551       ps = dbConnection.prepareStatement(queryStr);
2552       ps.setLong(1, Long.parseLong(companyId));
2553       ps.setInt(2, componentType);
2554       ps.setInt(3, printType);
2555       answer = DAOUtil.loadCodeDescription(ps, rs);
2556     }
2557     catch(Exception ae) {
2558       debug.println("Exception:  " + ae.toString());
2559       throw new DAOException
2560         (LetterTemplateExceptionMessage.PROBLEM_LOAD_COMPONENTS_DESCRIPTION
2561          + ae.getMessage());
2562     }
2563     finally {
2564       DAOUtil.closeResultSet(rs);
2565       DAOUtil.closePreparedStatement(ps);
2566       DAOUtil.closeConnection(dbConnection);
2567     }
2568     return answer;
2569   }
2570 
2571 
2572   /**
2573    *  Loads a letters component of the current company, corresponding to a
2574    *  code, from tables DatabaseNames.LETT_COMPONENT, LETT_IMAGE,
2575    *  LETT_VARIABLE
2576    *
2577    * @param componentCode code of component to load
2578    * @return LetterComponent is the loaded component
2579    * @exception DAOException
2580    */
2581   public LetterComponent loadComponent(long componentCode)
2582      throws DAOException {
2583     debug.println("loading letters component from DB");
2584     PreparedStatement ps = null;
2585     ResultSet rs = null;
2586     boolean successTransaction = false;
2587     LetterComponent answer = null;
2588 
2589     try {
2590       dbConnection = DAOUtil.getDBConnection(datasource);
2591       dbConnection.setAutoCommit(false);
2592       answer = auxLoadComponent(componentCode, ps, rs);
2593       successTransaction = true;
2594     }
2595     catch(Exception ae) {
2596       debug.println("Exception:  " + ae.toString());
2597       throw new DAOException
2598         (LetterTemplateExceptionMessage.PROBLEM_LOAD_COMPONENT + " of code "
2599          + String.valueOf(componentCode) + " : " + ae.getMessage());
2600     }
2601     finally {
2602       try {
2603         if(successTransaction) {
2604           dbConnection.commit();
2605         }
2606         else {
2607           dbConnection.rollback();
2608         }
2609       }
2610       catch(Exception e) {
2611         debug.println("Exception resolving transaction:  " + e.toString());
2612         throw new DAOException
2613           (LetterTemplateExceptionMessage.PROBLEM_LOAD_COMPONENT + e.getMessage());
2614       }
2615       DAOUtil.closeResultSet(rs);
2616       DAOUtil.closePreparedStatement(ps);
2617       DAOUtil.closeConnection(dbConnection);
2618     }
2619     return answer;
2620   }
2621 
2622 
2623   /**
2624    *  Removes a letters component of the current company, corresponding to a
2625    *  code, from tables DatabaseNames.LETT_COMPONENT, LETT_IMAGE,
2626    *  LETT_VARIABLE Fails if the component has links with one or several
2627    *  templates
2628    *
2629    * @param componentCode is the component code to remove
2630    * @exception DAOException
2631    */
2632   public void removeComponent(long componentCode)
2633      throws DAOException {
2634     debug.println("removing letters component from DB");
2635     PreparedStatement ps = null;
2636     ResultSet rs = null;
2637     boolean successTransaction = false;
2638 
2639     String queryStrLink =
2640       " SELECT code_component "
2641        + " FROM " + DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK
2642        + " WHERE  code_component = ? ";
2643 
2644     String deleteStrVariables =
2645       " DELETE " + DatabaseNames.LETT_VARIABLE
2646        + " WHERE code_component = ? ";
2647 
2648     String deleteStrImages =
2649       " DELETE " + DatabaseNames.LETT_IMAGE
2650        + " WHERE code_component = ? ";
2651 
2652     String deleteStrComponent =
2653       " DELETE " + DatabaseNames.LETT_COMPONENT
2654        + " WHERE code_component = ?";
2655 
2656     try {
2657       dbConnection = DAOUtil.getDBConnection(datasource);
2658       dbConnection.setAutoCommit(false);
2659 
2660       // verify that the component doesn't have links with templates:
2661       ps = dbConnection.prepareStatement(queryStrLink);
2662       ps.setLong(1, componentCode);
2663       ps.executeQuery();
2664       rs = ps.getResultSet();
2665       if(rs.next()) {
2666         throw new DAOException
2667           (LetterTemplateExceptionMessage.PROBLEM_DELETE_COMPONENT_LINKS);
2668       }
2669       DAOUtil.closePreparedStatement(ps);
2670 
2671       // remove variables and images of component :
2672       ps = dbConnection.prepareStatement(deleteStrVariables);
2673       ps.setLong(1, componentCode);
2674       ps.executeUpdate();
2675       DAOUtil.closePreparedStatement(ps);
2676 
2677       ps = dbConnection.prepareStatement(deleteStrImages);
2678       ps.setLong(1, componentCode);
2679       ps.executeUpdate();
2680       DAOUtil.closePreparedStatement(ps);
2681 
2682       // remove component:
2683       ps = dbConnection.prepareStatement(deleteStrComponent);
2684       ps.setLong(1, componentCode);
2685       ps.executeUpdate();
2686 
2687       successTransaction = true;
2688     }
2689     catch(Exception ae) {
2690       debug.println("Exception:  " + ae.toString());
2691       throw new DAOException
2692         (LetterTemplateExceptionMessage.PROBLEM_LOAD_COMPONENT + " of code "
2693          + String.valueOf(componentCode) + " : " + ae.getMessage());
2694     }
2695     finally {
2696       try {
2697         if(successTransaction) {
2698           dbConnection.commit();
2699         }
2700         else {
2701           dbConnection.rollback();
2702         }
2703       }
2704       catch(Exception e) {
2705         debug.println("Exception resolving transaction:  " + e.toString());
2706         throw new DAOException
2707           (LetterTemplateExceptionMessage.PROBLEM_DELETE_COMPONENT + e.getMessage());
2708       }
2709       DAOUtil.closeResultSet(rs);
2710       DAOUtil.closePreparedStatement(ps);
2711       DAOUtil.closeConnection(dbConnection);
2712     }
2713   }
2714 
2715 
2716   /**
2717    *  Load [code, stamp] for specified component from
2718    *  DatabaseNames.LETT_COMPONENT table
2719    *
2720    * @param componentType type of component (HEADER, BODY or CLOSING)
2721    * @param printType type of print
2722    * @param name name of component
2723    * @return CodeDescription:
2724    *           [code, stamp] if the component exists,
2725    *           [LetterTemplateGlobals.UNDEF,LetterTemplateGlobals.STR_UNDEF] if the component doesn't exist
2726    * @exception DAOException
2727    */
2728 
2729   public CodeDescription loadComponentCode
2730     (int componentType, int printType, String name)
2731      throws DAOException {
2732 
2733     debug.println("loading component code and stamp");
2734 
2735     long code = LetterTemplateGlobals.UNDEF;
2736     String stamp = LetterTemplateGlobals.STR_UNDEF;
2737     PreparedStatement ps = null;
2738     ResultSet rs = null;
2739     String queryStr =
2740       " SELECT code_component, last_changed_date "
2741        + " FROM " + DatabaseNames.LETT_COMPONENT
2742        + " WHERE code_company = ? "
2743        + "   AND code_component_type = ? "
2744        + "   AND code_print_type = ? "
2745        + "   AND description = ? ";
2746 
2747     CodeDescription answer = null;
2748 
2749     try {
2750       dbConnection = DAOUtil.getDBConnection(datasource);
2751       ps = dbConnection.prepareStatement(queryStr);
2752       ps.setLong(1, Long.parseLong(companyId));
2753       ps.setInt(2, componentType);
2754       ps.setInt(3, printType);
2755       ps.setString(4, name);
2756       ps.executeQuery();
2757       rs = ps.getResultSet();
2758       if(rs.next()) {
2759         code = rs.getLong(1);
2760         stamp = rs.getString(2);
2761       }
2762       answer = new CodeDescription(code, stamp);
2763     }
2764     catch(Exception ae) {
2765       debug.println("Exception in (DAO) loadComponentCode:  " +
2766         ps.toString() + "\n" + ae.toString());
2767       throw new DAOException
2768         (LetterTemplateExceptionMessage.PROBLEM_LOAD_COMPONENT_CODE
2769          + ae.getMessage());
2770     }
2771     finally {
2772       DAOUtil.closeResultSet(rs);
2773       DAOUtil.closePreparedStatement(ps);
2774       DAOUtil.closeConnection(dbConnection);
2775     }
2776     return answer;
2777   }
2778 
2779 
2780   /**
2781    *  If the relationship between Template and Component doesn't exist loads
2782    *  code, name and print type of components and name of component type from
2783    *  DatabaseNames.LETT_COMPONENT, LETT_COMPONENT_TYPE, LETT_PRINT_TYPE and
2784    *  LETT_TEMPLATE_COMPONENT_LINK.
2785    *
2786    * @return ArrayList of variables where each element is an
2787    *          inner ArrayList with the following elements of a variable:
2788    *            code(Long): code of component,
2789    *            nameComponentType(String): name of component type,
2790    *            type(String): print type,
2791    *            nameComponent (String): name of component.
2792    * @exception DAOException
2793    */
2794   public ArrayList loadUnlikedComponents()
2795      throws DAOException {
2796 
2797     debug.println("loading unlike components description");
2798 
2799     PreparedStatement ps = null;
2800     ResultSet rs = null;
2801     String queryStrUnlComp =
2802       " SELECT c.code_component, ct.description, p.description, c.description "
2803        + " FROM " + DatabaseNames.LETT_COMPONENT + " c,"
2804        + DatabaseNames.LETT_COMPONENT_TYPE + " ct, "
2805        + DatabaseNames.LETT_PRINT_TYPE + " p "
2806        + " WHERE c.code_component  NOT IN( "
2807        + "   SELECT code_component "
2808        + "   FROM " + DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK
2809        + "   ) "
2810        + " AND c.code_component_type = ct.code_component_type "
2811        + " AND c.code_print_type = p.code_print_type "
2812        + " AND c.code_company = ? "
2813        + " ORDER BY ct.description, p.description, c.description ";
2814 
2815     ArrayList answer = new ArrayList();
2816 
2817     try {
2818       dbConnection = DAOUtil.getDBConnection(datasource);
2819       ps = dbConnection.prepareStatement(queryStrUnlComp);
2820       ps.setLong(1, Long.parseLong(companyId));
2821       ps.executeQuery();
2822       rs = ps.getResultSet();
2823       while(rs.next()) {
2824         Long code = new Long(rs.getLong(1));
2825         String nameComponentType = rs.getString(2);
2826         String type = rs.getString(3);
2827         String nameComponent = rs.getString(4);
2828         ArrayList tuple = new ArrayList(4);
2829         tuple.add(code);
2830         tuple.add(nameComponentType);
2831         tuple.add(type);
2832         tuple.add(nameComponent);
2833         answer.add(tuple);
2834       }
2835     }
2836     catch(Exception ae) {
2837       debug.println("Exception:  " + ae.toString());
2838       throw new DAOException
2839         (LetterTemplateExceptionMessage.PROBLEM_LOAD_COMPONENTS_DESCRIPTION
2840          + ae.getMessage());
2841     }
2842     finally {
2843       DAOUtil.closeResultSet(rs);
2844       DAOUtil.closePreparedStatement(ps);
2845       DAOUtil.closeConnection(dbConnection);
2846     }
2847     return answer;
2848   }
2849 
2850 
2851   /**
2852    *  Applies a set of changes in the components of the current company where
2853    *  the relationship between Template and Component doesn't exist from
2854    *  DatabaseNames.LETT_VARIABLE, LETT_IMAGE, LETT_COMPONENT.
2855    *
2856    * @param items ArrayList with 3 elements of
2857    *      type String[] representing the attributes of items to apply:
2858    *      code, name of component and status; status indicates if the item is for
2859    *      deleting or updating
2860    * @return ArrayList with 2 elements:
2861    *      (0) possible problem (String),
2862    *      (1) current Template description list (ArrayList)
2863    * @exception DAOException
2864    */
2865   public ArrayList applyItemsComponent(ArrayList items)
2866      throws DAOException {
2867     debug.println("applying a set of changes to components of current company");
2868 
2869     PreparedStatement ps1;
2870 
2871     PreparedStatement ps2;
2872 
2873     PreparedStatement ps3;
2874 
2875     PreparedStatement ps4;
2876     ps1 = ps2 = ps3 = ps4 = null;
2877     boolean listsBuilted = false;
2878     boolean successTransaction = false;
2879     ArrayList deleteList = new ArrayList();
2880     ArrayList updateList = new ArrayList();
2881     ArrayList item = new ArrayList();
2882     int listSize;
2883 
2884     String deleteStrVariables =
2885       " DELETE " + DatabaseNames.LETT_VARIABLE
2886        + " WHERE code_component = ? ";
2887 
2888     String deleteStrImages =
2889       " DELETE " + DatabaseNames.LETT_IMAGE
2890        + " WHERE code_component = ? ";
2891 
2892     String deleteStrComponent =
2893       " DELETE " + DatabaseNames.LETT_COMPONENT
2894        + " WHERE code_component = ?";
2895 
2896     String updateStrComponent =
2897       " UPDATE " + DatabaseNames.LETT_COMPONENT + " SET"
2898        + " description = ?,"
2899        + " last_changed_by = ?,"
2900        + " last_changed_date = SYSDATE"
2901        + " WHERE code_component = ?"
2902        + " AND code_company = ?";
2903 
2904     String problem = LetterTemplateGlobals.STR_UNDEF;
2905     ArrayList componetsList = new ArrayList();
2906     ArrayList answer = null;
2907 
2908     // from items parameter, build 2 sets of items:
2909     // items for deleting and updating
2910     try {
2911       String[] codeComponent = (String[])items.get(0);
2912       String[] nameComponent = (String[])items.get(1);
2913       String[] status = (String[])items.get(2);
2914       int numItems = codeComponent.length;
2915 
2916       for(int i = 0; i < numItems; i++) {
2917         ArrayList slot = new ArrayList(2);
2918         slot.add(codeComponent[i]);
2919         slot.add(nameComponent[i]);
2920         if(status[i].equals(LetterTemplateGlobals.DELETE)) {
2921           deleteList.add(slot);
2922         }
2923         else if(status[i].equals(LetterTemplateGlobals.UPDATE)) {
2924           updateList.add(slot);
2925         }
2926         else {
2927           throw new DAOException
2928             (LetterTemplateExceptionMessage.ITEM_STATUS_INVALID);
2929         }
2930       }
2931       listsBuilted = true;
2932     }
2933     catch(Exception e) {
2934       debug.println("Exception building lists:  " + e.toString());
2935       StringWriter sw = new StringWriter();
2936       PrintWriter pw = new PrintWriter(sw);
2937       e.printStackTrace(pw);
2938       problem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_CHANGES_COMPONENTS
2939          + e.getMessage()
2940          + "|" + sw.toString();
2941     }
2942 
2943     // apply sets of changes:
2944     if(listsBuilted) {
2945       String phase = "";
2946       try {
2947         dbConnection = DAOUtil.getDBConnection(datasource);
2948         dbConnection.setAutoCommit(false);
2949 
2950         // apply set of deletes:
2951         phase = "delete";
2952         ps1 = dbConnection.prepareStatement(deleteStrVariables);
2953         ps2 = dbConnection.prepareStatement(deleteStrImages);
2954         ps3 = dbConnection.prepareStatement(deleteStrComponent);
2955         listSize = deleteList.size();
2956 
2957         for(int i = 0; i < listSize; i++) {
2958           item = ((ArrayList)(deleteList.get(i)));
2959           ps1.setLong(1, Long.parseLong(((String)item.get(0))));
2960           ps2.setLong(1, Long.parseLong(((String)item.get(0))));
2961           ps3.setLong(1, Long.parseLong(((String)item.get(0))));
2962           ps1.executeUpdate();
2963           ps2.executeUpdate();
2964           int num = ps3.executeUpdate();
2965           if(num == 0) {
2966             throw new DAOException
2967               (LetterTemplateExceptionMessage.PROBLEM_APPLYING_DELETES1_COMPONENTS);
2968           }
2969         }
2970 
2971         // apply set of updates:
2972         phase = "update";
2973         ps4 = dbConnection.prepareStatement(updateStrComponent);
2974         listSize = updateList.size();
2975         for(int i = 0; i < listSize; i++) {
2976           item = ((ArrayList)(updateList.get(i)));
2977           ps4.setString(1, (String)(item.get(1)));
2978           ps4.setLong(2, this.userId.longValue());
2979           ps4.setLong(3, Long.parseLong(((String)item.get(0))));
2980           ps4.setLong(4, Long.parseLong(this.companyId));
2981           int num = ps4.executeUpdate();
2982           if(num == 0) {
2983             throw new DAOException
2984               (LetterTemplateExceptionMessage.PROBLEM_APPLYING_UPDATES1_COMPONENTS);
2985           }
2986         }
2987         successTransaction = true;
2988       }
2989       catch(Exception ae) {
2990         debug.println("Exception applying item to DB in phase " + phase
2991            + " : " + ae.toString());
2992         StringWriter sw = new StringWriter();
2993         PrintWriter pw = new PrintWriter(sw);
2994         ae.printStackTrace(pw);
2995         String subproblem = null;
2996         if(phase.equals("delete")) {
2997           subproblem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_DELETES2_COMPONENTS;
2998         }
2999         else {
3000           // phase.equals("update")
3001           subproblem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_UPDATES2_COMPONENTS;
3002         }
3003         String ComponentName = (item != null) ?
3004           ((String)(item.get(1))) : "";
3005         problem = subproblem
3006            + "current component name: " + ComponentName
3007            + " :" + ae.getMessage() + "|" + sw.toString();
3008       }
3009       finally {
3010         try {
3011           if(successTransaction) {
3012             dbConnection.commit();
3013           }
3014           else {
3015             dbConnection.rollback();
3016           }
3017         }
3018         catch(Exception e) {
3019           debug.println("Exception resolving transaction:  " + e.toString());
3020           StringWriter sw = new StringWriter();
3021           PrintWriter pw = new PrintWriter(sw);
3022           e.printStackTrace(pw);
3023           problem = LetterTemplateExceptionMessage.PROBLEM_APPLYING_CHANGES_COMPONENTS
3024              + e.getMessage()
3025              + "|" + sw.toString();
3026         }
3027         DAOUtil.closePreparedStatement(ps1);
3028         DAOUtil.closePreparedStatement(ps2);
3029         DAOUtil.closePreparedStatement(ps3);
3030         DAOUtil.closePreparedStatement(ps4);
3031         DAOUtil.closeConnection(dbConnection);
3032       }
3033     }
3034 
3035     // get current component list:
3036     try {
3037       componetsList = this.loadUnlikedComponents();
3038       answer = new ArrayList(2);
3039       answer.add(problem);
3040       answer.add(componetsList);
3041     }
3042     catch(Exception ae) {
3043       throw new DAOException
3044         (LetterTemplateExceptionMessage.PROBLEM_LOAD_COMPONENT
3045          + ae.getMessage());
3046     }
3047     return answer;
3048   }
3049 
3050 
3051   // BUSINESS METHODS FOR LETTERS JOBS
3052 
3053   /**
3054    *  Gets template variables values for one loan of the current company,
3055    *  which will be used in a preview of the template.
3056    *
3057    *  It creates an entity EJB Job instance associated to the template preview
3058    *  and generates the associated SQL sentence. This sentence is executed on
3059    *  any tables and gets the template variables values.
3060    *
3061    * @param templateCode is the code of template to preview
3062    * @param loanCode is the code of the loan (i.e. agreement)
3063    * @param templateVarsCodes template variables codes
3064    * @param systemAlias Hashtable of system Alias
3065    *                           key:   String = tableAlias|rootType
3066    *                           value: Alias object
3067    * @param systemFields Hashtable of system Fields for current company
3068    *                           key: fieldId (in Long), value: Field object
3069    * @return ArrayList of one tuple that
3070    *      is an Object[] of Strings; each String is the value of a template
3071    *      variable for the chosen loan
3072    * @exception DAOException
3073    */
3074   public ArrayList generatePreviewTemplate
3075     (long templateCode, long loanCode, Long[] templateVarsCodes,
3076      Hashtable systemAlias, Hashtable systemFields)
3077      throws DAOException {
3078     debug.println("generatePreviewTemplate: generating template variables values for a preview");
3079     PreparedStatement ps = null;
3080     ResultSet rs = null;
3081 
3082     JobHome jobhome = null;
3083     Job jobejb = null;
3084     ArrayList jobSELECT;
3085     ArrayList jobWHERE;
3086     ArrayList jobORDER;
3087     JobORDERelement jobORDERelement;
3088     ArrayList answer = null;
3089 
3090     String queryAgrmCode =
3091       " SELECT field_id "
3092        + " FROM " + DatabaseNames.LETT_FIELD
3093        + " WHERE table_alias = ?  AND root_type = ?"
3094        + "      AND field_column = ? ";
3095 
3096     try {
3097 
3098       // remove a Job instance  corresponding to template preview,
3099       // if exists:
3100       InitialContext ctx = new InitialContext();
3101       jobhome = (JobHome)ctx.lookup(JNDINames.JOB_EJBHOME);
3102       try {
3103         jobejb = jobhome.findByName(companyId,
3104           LetterTemplateGlobals.DOWN_PREVIEW_NAME);
3105         jobejb.remove();
3106       }
3107       catch(FinderException e) {
3108         debug.println("job not found: " + e.getMessage());
3109       }
3110       catch(Exception aa) {
3111         debug.println("Exception unexpected: " + aa);
3112         throw new DAOException
3113           ("Exception unexpected: " + aa.getMessage());
3114       }
3115 
3116       // get ftp ids associated to the current company:
3117       CodeDescription[] ftps = this.loadFTPCodes();
3118       long firstFtpId;
3119       if(ftps.length == 0) {
3120         firstFtpId = LetterTemplateGlobals.UNDEF;
3121       }
3122       else {
3123         firstFtpId = ftps[0].getCode();
3124       }
3125 
3126       // create a new entity EJB Job instance for template preview,
3127       // in memory and in database:
3128       debug.println("job will be created");
3129       jobejb = jobhome.create(companyId, userId,
3130         LetterTemplateGlobals.DOWN_PREVIEW_NAME,
3131         firstFtpId, firstFtpId);
3132       debug.println("invoking jobejb.setTemplate()");
3133       jobejb.setTemplate(templateCode);
3134       jobejb.setDescription(LetterTemplateGlobals.DOWN_PREVIEW_NAME);
3135 
3136       // set the SELECT part of Job state with template variables:
3137       jobSELECT = new ArrayList();
3138       for(int i = 0; i < templateVarsCodes.length; i++) {
3139         jobSELECT.add(new JobSELECTelement
3140           (i + 1, templateVarsCodes[i].longValue()));
3141       }
3142       debug.println("invoking jobejb.setJobSELECT()");
3143       jobejb.setJobSELECT(jobSELECT);
3144 
3145       // get field Id. corresponding to AGREEMENT_CODE_VARIABLE :
3146       dbConnection = DAOUtil.getDBConnection(datasource);
3147       ps = dbConnection.prepareStatement(queryAgrmCode);
3148       ps.setString(1, LetterTemplateGlobals.AGREEMENTS_ALIAS);
3149       ps.setString(2, LetterTemplateGlobals.ROOT_AGREEMENTS);
3150       ps.setString(3, LetterTemplateGlobals.AGREEMENT_CODE_VARIABLE);
3151       ps.executeQuery();
3152       rs = ps.getResultSet();
3153       rs.next();
3154       long agrmCodeFieldId = rs.getLong(1);
3155 
3156       // set the WHERE part of Job state with the chosen loan:
3157       jobWHERE = new ArrayList();
3158       jobWHERE.add(new JobWHEREelement
3159         (1, 1, agrmCodeFieldId, "=", String.valueOf(loanCode),
3160         LetterTemplateGlobals.EMPTY_CONNECTOR));
3161       debug.println("invoking jobejb.setJobWHERE()");
3162       jobejb.setJobWHERE(jobWHERE);
3163 
3164       // set the ORDER part of Job state with template variables:
3165       jobORDER = new ArrayList();
3166       for(int i = 0; i < templateVarsCodes.length; i++) {
3167         jobORDERelement = new JobORDERelement
3168           (i + 1, templateVarsCodes[i].longValue(),
3169           LetterTemplateGlobals.ASCENDING_DIRECTION,
3170           LetterTemplateGlobals.DEFAULT_UNICITY);
3171         jobORDER.add(jobORDERelement);
3172       }
3173       debug.println("invoking jobejb.setJobORDER()");
3174       jobejb.setJobORDER(jobORDER);
3175 
3176       // get the SQL sentence for obtaining variable values:
3177       debug.println("invoking jobejb.generateSQLtext()");
3178       String sentenceSQL
3179          = jobejb.generateSQLtext(systemFields, systemAlias,
3180         LetterTemplateGlobals.ROOT_AGREEMENTS);
3181 
3182       // obtain the preview variable values, executing the SQL sentence,
3183       // the first column is aggregated for job control:
3184       JobModel jobModel = jobejb.getState();
3185       Hashtable jobORDERhashtable = jobModel.getJobORDERtable();
3186       ArrayList[] theResultSet
3187          = executeSQL(sentenceSQL, templateVarsCodes,
3188         jobORDERhashtable, systemFields);
3189       ArrayList firstColumn = theResultSet[0];
3190       ArrayList otherColumns = theResultSet[1];
3191       if(firstColumn.size() == 0) {
3192         throw new DAOException
3193           (LetterTemplateExceptionMessage.NO_DATA_FOR_LOAN);
3194       }
3195 
3196       // build the answer:
3197       answer = otherColumns;
3198 
3199       // remove the EJB job instance, from memory and from database:
3200       jobejb.remove();
3201 
3202     }
3203     catch(Exception ae) {
3204       debug.println("Exception:  " + ae.toString());
3205       throw new DAOException
3206         (LetterTemplateExceptionMessage.PROBLEM_GENERATING_VARIABLES_VALUES
3207          + ae.getMessage());
3208     }
3209     finally {
3210       DAOUtil.closeResultSet(rs);
3211       DAOUtil.closePreparedStatement(ps);
3212       DAOUtil.closeConnection(dbConnection);
3213     }
3214     return answer;
3215   }
3216 
3217 
3218   /**
3219    *  Gets a result set executing a SQL sentence,
3220    *  associated with a letter job.
3221    *
3222    * @param sentenceSQL SQL sentence for executing;
3223    *          in addition to SQL sintax, it can contain ++ or -- operators
3224    *          that must be transformed in workable days offset
3225    * @param selectFields output fields ids (in job SELECT order)
3226    *          or a Long[] of length 0 if there are no output fields.
3227    * @param jobORDERhashtable Hashtable of job ORDER elements:
3228    *                             key: fieldId (in Long), value: JobORDERelement
3229    * @param systemFields Hashtable of system Fields for current company
3230    *                           key: fieldId (in Long), value: Field object
3231    * @return ArrayList[] as following:
3232    *          ArrayList[0]: first (aggregated) column of the result set
3233    *                        (i.e. agreement code)
3234    *                        it is an ArrayList of String elements.
3235    *          ArrayList[1]: the others columns of the result set
3236    *                        it is an ArrayList of String[] elements.
3237    * @exception DAOException
3238    */
3239   public ArrayList[] executeSQL(String sentenceSQL, Long[] selectFields,
3240                                 Hashtable jobORDERhashtable,
3241                                 Hashtable systemFields) throws DAOException {
3242     debug.println("executeSQL");
3243 
3244     PreparedStatement ps = null;
3245     ResultSet rs = null;
3246     ArrayList firstColumn = new ArrayList();
3247     ArrayList otherColumns = new ArrayList();
3248     String unicityValueOld = "--Inexistent Value";
3249     String unicityValueNew = null;
3250     ArrayList[] answer = new ArrayList[2];
3251 
3252     String queryCOMPANY_DATE =
3253       " SELECT company_date "
3254        + " FROM " + DatabaseNames.COMPANIES
3255        + " WHERE cmp_id = ? ";
3256 
3257     try {
3258       // gets SYSDATE value:
3259       java.sql.Date sysDate = loadSysDate();
3260 
3261       // gets COMPANY_DATE value:
3262       dbConnection = DAOUtil.getDBConnection(datasource);
3263       ps = dbConnection.prepareStatement(queryCOMPANY_DATE);
3264       ps.setLong(1, Long.parseLong(companyId));
3265       ps.executeQuery();
3266       rs = ps.getResultSet();
3267       rs.next();
3268       java.sql.Date companyDate = rs.getDate(1);
3269       DAOUtil.closeResultSet(rs);
3270       DAOUtil.closePreparedStatement(ps);
3271       DAOUtil.closeConnection(dbConnection);
3272       rs = null;
3273       ps = null;
3274       dbConnection = null;
3275 
3276       // transforms in sentenceSQL ++ and -- operators
3277       // in workable days offset:
3278       sentenceSQL = auxTransformWorkableOffset
3279         (sentenceSQL, sysDate, companyDate);
3280 
3281       // executes sentenceSQL
3282       dbConnection = DAOUtil.getDBConnection(datasource);
3283       ps = dbConnection.prepareStatement(sentenceSQL);
3284       ps.executeQuery();
3285       rs = ps.getResultSet();
3286 
3287       int numRecords = 0;
3288       while(rs.next()) {
3289         numRecords++;
3290         // getting value of first column (added for job control):
3291         String valueFirstColumn = rs.getString(1);
3292 
3293         // getting tuple with other columns:
3294         String[] tuple = new String[selectFields.length];
3295         for(int i = 0; i < selectFields.length; i++) {
3296           tuple[i] = "";  // for SQL null value
3297           Field field = (Field)systemFields.get(selectFields[i]);
3298           if((field.getDataType())
3299             .equals(LetterTemplateGlobals.FIELD_DATE)) {
3300             java.sql.Date date = rs.getDate(i + 2);
3301             if(date != null) {
3302               tuple[i] = date.toString();
3303             }
3304           }
3305           else {
3306             String value = rs.getString(i + 2);
3307             if(value != null) {
3308               tuple[i] = value;
3309             }
3310           }
3311         }
3312 
3313         // appliying unicity criteria to discard or not the tuple:
3314         unicityValueNew = "";
3315         for(int i = 0; i < selectFields.length; i++) {
3316           JobORDERelement jobORDERelement
3317              = (JobORDERelement)jobORDERhashtable.get(selectFields[i]);
3318           if(jobORDERelement.getUnicityMember().equals("yes")) {
3319             unicityValueNew += tuple[i];
3320           }
3321         }
3322         if((selectFields.length == 0)
3323            || (!unicityValueNew.equals(unicityValueOld))) {
3324           firstColumn.add(valueFirstColumn);
3325           otherColumns.add(tuple);
3326           unicityValueOld = unicityValueNew;
3327         }
3328       }
3329       debug.println("resultset: size before discarding=" + numRecords);
3330       debug.println("resultset: size after discarding=" + firstColumn.size());
3331       answer[0] = firstColumn;
3332       answer[1] = otherColumns;
3333 
3334     }
3335     catch(Exception ae) {
3336       debug.println("Exception:  " + ae.toString());
3337       //debug.println(CommonUtil.stackTraceToString(ae));
3338       throw new DAOException
3339         (LetterTemplateExceptionMessage.PROBLEM_GETTING_RESULTSET
3340          + ae.getMessage());
3341     }
3342     finally {
3343       DAOUtil.closeResultSet(rs);
3344       DAOUtil.closePreparedStatement(ps);
3345       DAOUtil.closeConnection(dbConnection);
3346     }
3347     return answer;
3348   }
3349 
3350 
3351   /**
3352    *  Loads all [code, name] of the ftp's of the current company,
3353    *  from DatabaseNames.COMPANY_ADDRESSES and COMPANY_LOCATIONS tables;
3354    *  ordered by name
3355    *
3356    * @return CodeDescription[] object
3357    *           with [code, name] of the ftp's
3358    * @exception DAOException
3359    */
3360   public CodeDescription[] loadFTPCodes() throws DAOException {
3361     debug.println("loading code and name of ftps of current company");
3362 
3363     PreparedStatement ps = null;
3364     ResultSet rs = null;
3365 
3366     String queryStr =
3367       " SELECT l.cmpl_id, l.cmpl_name "
3368        + " FROM "
3369        + DatabaseNames.COMPANY_ADDRESSES + " a ,"
3370        + DatabaseNames.COMPANY_LOCATIONS + " l "
3371        + " WHERE a.cad_id = l.cmpl_cad_id  "
3372        + "   AND a.cad_cmp_id = ? "
3373        + " ORDER BY l.cmpl_name ";
3374     CodeDescription[] answer = null;
3375 
3376     try {
3377       dbConnection = DAOUtil.getDBConnection(datasource);
3378       ps = dbConnection.prepareStatement(queryStr);
3379       ps.setLong(1, Long.parseLong(companyId));
3380       answer = DAOUtil.loadCodeDescription(ps, rs);
3381     }
3382     catch(Exception ae) {
3383       debug.println("Exception:  " + ae.toString());
3384       throw new DAOException
3385         (LetterTemplateExceptionMessage.PROBLEM_LOAD_FTPS + ae.getMessage());
3386     }
3387     finally {
3388       DAOUtil.closeResultSet(rs);
3389       DAOUtil.closePreparedStatement(ps);
3390       DAOUtil.closeConnection(dbConnection);
3391     }
3392     return answer;
3393   }
3394 
3395 
3396   /**
3397    *  Loads all [code, name] of the jobs of the current company;
3398    *  from DatabaseNames.LETT_JOB; ordered by name
3399    *
3400    * @return CodeDescription[] object
3401    *      with [code, description] of the categories
3402    * @exception DAOException
3403    */
3404   public CodeDescription[] loadJobsCodes() throws DAOException {
3405     debug.println("loading names of jobs of current company");
3406 
3407     PreparedStatement ps = null;
3408     ResultSet rs = null;
3409     String queryStr =
3410       " SELECT job_id, name "
3411        + " FROM " + DatabaseNames.LETT_JOB
3412        + " WHERE code_company = ?"
3413        + " ORDER BY name ";
3414     CodeDescription[] answer = null;
3415 
3416     try {
3417       dbConnection = DAOUtil.getDBConnection(datasource);
3418       ps = dbConnection.prepareStatement(queryStr);
3419       ps.setLong(1, Long.parseLong(companyId));
3420       answer = DAOUtil.loadCodeDescription(ps, rs);
3421     }
3422     catch(Exception ae) {
3423       debug.println("Exception:  " + ae.toString());
3424       throw new DAOException
3425         (LetterTemplateExceptionMessage.PROBLEM_LOAD_JOBS + ae.getMessage());
3426     }
3427     finally {
3428       DAOUtil.closeResultSet(rs);
3429       DAOUtil.closePreparedStatement(ps);
3430       DAOUtil.closeConnection(dbConnection);
3431     }
3432     return answer;
3433   }
3434 
3435 
3436   /**
3437    *  Loads all the calendars of the current company;
3438    *  from DatabaseNames.CALENDARS;
3439    *
3440    * @return Hashtable of company calendars:
3441    *           key:   year (Integer),
3442    *           value: String of 365/366 characters representing the year calendar
3443    *                  (each day of year is a character :
3444    *                  'P'  if it is workable(Processing) day, 'N' otherwise)
3445    * @exception DAOException
3446    */
3447   public Hashtable loadCalendars() throws DAOException {
3448     debug.println("loadCalendars");
3449     PreparedStatement ps = null;
3450     ResultSet rs = null;
3451     String queryStr =
3452       " SELECT clnd_year year, clnd_days days "
3453        + " FROM " + DatabaseNames.CALENDARS
3454        + " WHERE clnd_cmp_id = ? ";
3455     Hashtable answer = new Hashtable();
3456 
3457     try {
3458       dbConnection = DAOUtil.getDBConnection(datasource);
3459       ps = dbConnection.prepareStatement(queryStr);
3460       ps.setLong(1, Long.parseLong(companyId));
3461       ps.executeQuery();
3462       rs = ps.getResultSet();
3463       while(rs.next()) {
3464         int year = rs.getInt(1);
3465         String calendar = rs.getString(2);
3466         answer.put(new Integer(year), calendar);
3467       }
3468 
3469     }
3470     catch(Exception ae) {
3471       debug.println("Exception: " + ae.getMessage());
3472       throw new DAOException
3473         (LetterTemplateExceptionMessage.PROBLEM_LOAD_COMPANY_CALENDARS
3474          + ae.getMessage());
3475     }
3476     finally {
3477       DAOUtil.closeResultSet(rs);
3478       DAOUtil.closePreparedStatement(ps);
3479       DAOUtil.closeConnection(dbConnection);
3480     }
3481     return answer;
3482   }
3483 
3484 
3485   // BUSINESS METHODS TO LAUNCH AND REVIEW BATCH LETTER JOBS
3486 
3487   /**
3488    *  Loads all letters Job information.
3489    *  this method service imvoke the verifyDate() methos.
3490    *
3491    * @return answer The LetterBatchStartModel object with all letters Job
3492    *         when each atribute represents: Jobs to run, Jobs out of frequency
3493    *         and other Jobs(inactive,no yet active and on request)
3494    * @exception DAOException
3495    */
3496   public LetterBatchStartModel loadLetterJob() throws DAOException {
3497 
3498     debug.println("LoadLetterJob");
3499 
3500     PreparedStatement ps = null;
3501     ResultSet rs = null;
3502     ArrayList toRun = new ArrayList();
3503     ArrayList outOfFrequency = new ArrayList();
3504     ArrayList other = new ArrayList();
3505     LetterBatchStartModel answer = null;
3506     String activation_date = null;
3507     String last_execution_date = null;
3508     String type = null;
3509     String empty = null;
3510     String queryStr =
3511       " SELECT job_id, name, description, frequency, status, "
3512        + " activation_date, last_execution_date "
3513        + " FROM " + DatabaseNames.LETT_JOB
3514        + " WHERE code_company = ?  "
3515        + " ORDER BY name ";
3516     int i;
3517     try {
3518       dbConnection = DAOUtil.getDBConnection(datasource);
3519       ps = dbConnection.prepareStatement(queryStr);
3520       ps.setLong(1, Long.parseLong(companyId));
3521       ps.executeQuery();
3522       rs = ps.getResultSet();
3523       for(i = 0; rs.next(); i++) {
3524         last_execution_date = "";
3525         empty = LetterTemplateGlobals.STR_UNDEF;
3526         String id = rs.getString(1);
3527         String name = rs.getString(2);
3528         String description = rs.getString(3);
3529         String frequency = rs.getString(4);
3530         String status = rs.getString(5);
3531         Date activationDate = rs.getDate(6);
3532         Date lastDate = rs.getDate(7);
3533         activation_date = new SimpleDateFormat
3534           ("MMM dd, yyyy ").format(activationDate);
3535         if(!rs.wasNull()) {
3536           last_execution_date = new SimpleDateFormat
3537             ("MMM dd, yyyy ").format(lastDate);
3538           empty = "";
3539         }
3540         JobData jobData = new JobData(id, name, description, frequency, status,
3541           activation_date, last_execution_date);
3542         type = verifyDate(frequency, status, activationDate, lastDate, empty);
3543         if(type.equals(LetterTemplateGlobals.RUN)) {
3544           toRun.add(jobData);
3545         }
3546         else if(type.equals(LetterTemplateGlobals.OUT)) {
3547           outOfFrequency.add(jobData);
3548         }
3549         else if(type.equals(LetterTemplateGlobals.OTHER)) {
3550           other.add(jobData);
3551         }
3552       }
3553       answer = new LetterBatchStartModel(toRun, outOfFrequency, other);
3554     }
3555     catch(Exception ae) {
3556       debug.println(CommonUtil.stackTraceToString(ae));
3557       throw new DAOException
3558         (LetterTemplateExceptionMessage.PROBLEM_LOAD_LETTER_JOB
3559          + ae.getMessage());
3560     }
3561     finally {
3562       DAOUtil.closeResultSet(rs);
3563       DAOUtil.closePreparedStatement(ps);
3564       DAOUtil.closeConnection(dbConnection);
3565     }
3566     return answer;
3567   }
3568 
3569 
3570   /**
3571    *  Loads the date (Oracle SYSDATE() function).
3572    *
3573    * @return date The date of Oracle SYSDATE() function.
3574    * @exception DAOException
3575    */
3576   public Date loadSysDate() throws DAOException {
3577 
3578     debug.println("loadSysDate");
3579     PreparedStatement ps = null;
3580     ResultSet rs = null;
3581     String queryStr = " SELECT SYSDATE FROM DUAL ";
3582     Date answer = null;
3583 
3584     try {
3585       dbConnection = DAOUtil.getDBConnection(datasource);
3586       ps = dbConnection.prepareStatement(queryStr);
3587       ps.executeQuery();
3588       rs = ps.getResultSet();
3589       rs.next();
3590       answer = rs.getDate(1);
3591     }
3592     catch(Exception ae) {
3593       debug.println(CommonUtil.stackTraceToString(ae));
3594     }
3595     finally {
3596       DAOUtil.closeResultSet(rs);
3597       DAOUtil.closePreparedStatement(ps);
3598       DAOUtil.closeConnection(dbConnection);
3599     }
3600     return answer;
3601   }
3602 
3603 
3604   /**
3605    *  Loads the temporal directory path of the current company.
3606    *  from DatabasesNames.COLLECTIONS_CONFIG table.
3607    *
3608    * @return path  Path for the Downloads generated by the system.
3609    * @exception DAOException
3610    */
3611   public String loadCompanyWorkDir() throws DAOException {
3612 
3613     debug.println("loadCompanyWorkDir");
3614     PreparedStatement ps = null;
3615     ResultSet rs = null;
3616     String queryStr =
3617       " SELECT ccfg_download_path "
3618        + " FROM " + DatabaseNames.COLLECTIONS_CONFIG
3619        + " WHERE ccfg_cmp_id = ? ";
3620     String answer = null;
3621 
3622     try {
3623       dbConnection = DAOUtil.getDBConnection(datasource);
3624       ps = dbConnection.prepareStatement(queryStr);
3625       ps.setLong(1, Long.parseLong(companyId));
3626       ps.executeQuery();
3627       rs = ps.getResultSet();
3628       rs.next();
3629       answer = rs.getString(1);
3630     }
3631     catch(Exception ae) {
3632       debug.println(CommonUtil.stackTraceToString(ae));
3633       throw new DAOException
3634         (LetterTemplateExceptionMessage.PROBLEM_LOAD_COMPANY_WORK_DIR
3635          + ae.getMessage());
3636     }
3637     finally {
3638       DAOUtil.closeResultSet(rs);
3639       DAOUtil.closePreparedStatement(ps);
3640       DAOUtil.closeConnection(dbConnection);
3641     }
3642     return answer;
3643   }
3644 
3645 
3646   /**
3647    *  Store the log of executed letter jobs of the current company.
3648    *
3649    * @param resultSetLength Number of records retrieved by the job execution.
3650    * @param loggeableResultSet Result set with the records retrieved by
3651    *       the job execution.
3652    * @param foTemplate Transformed text of template used by the job execution.
3653    * @param jobId Description of the Parameter
3654    * @param executionDate Description of the Parameter
3655    * @param success Description of the Parameter
3656    * @return answer  The LettersJobLogBean object with
3657    *        the log code, job id and execution date of executed letter jobs.
3658    * @exception DAOException
3659    * @parm jobId The code of letter job.
3660    * @parm executionDate The date of execution letter job.
3661    */
3662   public LettersJobLogBean storeLetterJobLog(long jobId, Date executionDate,
3663                                              String success, long resultSetLength,
3664                                              String loggeableResultSet,
3665                                              String foTemplate) throws DAOException {
3666 
3667     debug.println("storeLetterJobLog");
3668     PreparedStatement ps = null;
3669     ResultSet rs = null;
3670     String queryStr =
3671       " SELECT job_log_id, job_id, execution_date "
3672        + " FROM " + DatabaseNames.LETT_JOB_LOG
3673        + " WHERE job_id = ? "
3674        + " AND execution_date = TO_DATE( ? , \'dd-Mon-yyyy HH:MI:SS AM\') ";
3675 
3676     String insertStr =
3677       " INSERT INTO " + DatabaseNames.LETT_JOB_LOG
3678        + "  (job_log_id, job_id, execution_date, execution_success,"
3679        + "   number_of_records, result_set, fo_template)"
3680        + " VALUES("
3681        + DatabaseNames.SEQ_LETT_JOB_LOG + ".nextval,"
3682        + " ?, TO_DATE( ? , \'dd-Mon-yyyy HH:MI:SS AM\'),"
3683        + " ?, ?, EMPTY_BLOB(), EMPTY_BLOB())";
3684 
3685     String queryResultSet =
3686       " SELECT result_set "
3687        + " FROM " + DatabaseNames.LETT_JOB_LOG
3688        + " WHERE job_id = ? "
3689        + " AND execution_date = TO_DATE( ? , \'dd-Mon-yyyy HH:MI:SS AM\') ";
3690 
3691     String queryFo =
3692       " SELECT fo_template "
3693        + " FROM " + DatabaseNames.LETT_JOB_LOG
3694        + " WHERE job_id = ? "
3695        + " AND execution_date = TO_DATE( ? , \'dd-Mon-yyyy HH:MI:SS AM\') ";
3696 
3697     LettersJobLogBean answer = new LettersJobLogBean();
3698     boolean successTransaction = false;
3699     String execDateString =
3700       new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss a").format(executionDate);
3701 
3702     try {
3703       dbConnection = DAOUtil.getDBConnection(datasource);
3704       dbConnection.setAutoCommit(false);
3705       // insert
3706       ps = dbConnection.prepareStatement(insertStr);
3707       ps.setLong(1, jobId);
3708       ps.setString(2, execDateString);
3709       ps.setString(3, success);
3710       ps.setLong(4, resultSetLength);
3711       ps.executeUpdate();
3712       DAOUtil.closePreparedStatement(ps);
3713       // insert blob ResultSet
3714 
3715       ps = dbConnection.prepareStatement(queryResultSet);
3716       ps.setLong(1, jobId);
3717       ps.setString(2, execDateString);
3718       java.sql.Blob textFieldRef = DAOUtil.getBlobReference(ps, rs);
3719       InputStream is
3720          = new ByteArrayInputStream(loggeableResultSet.getBytes());
3721       DAOUtil.writeBlobData(textFieldRef, is);
3722       DAOUtil.closePreparedStatement(ps);
3723       // insert blob FoTemplate
3724       ps = dbConnection.prepareStatement(queryFo);
3725       ps.setLong(1, jobId);
3726       ps.setString(2, execDateString);
3727       java.sql.Blob textFieldRef1 = DAOUtil.getBlobReference(ps, rs);
3728       InputStream is1
3729          = new ByteArrayInputStream(foTemplate.getBytes());
3730       DAOUtil.writeBlobData(textFieldRef1, is1);
3731       DAOUtil.closePreparedStatement(ps);
3732 
3733       //select
3734       ps = dbConnection.prepareStatement(queryStr);
3735       ps.setLong(1, jobId);
3736       ps.setString(2, execDateString);
3737       ps.executeQuery();
3738       rs = ps.getResultSet();
3739       rs.next();
3740       answer.setLogId(rs.getLong(1));
3741       answer.setJobId(rs.getLong(2));
3742       answer.setExecutionDate(rs.getDate(3));
3743       successTransaction = true;
3744     }
3745     catch(Exception ae) {
3746       debug.println(CommonUtil.stackTraceToString(ae));
3747       throw new DAOException
3748         (LetterTemplateExceptionMessage.PROBLEM_INSERT_LETTER_JOB_LOG
3749          + ae.getMessage());
3750     }
3751     finally {
3752       try {
3753         if(successTransaction) {
3754           dbConnection.commit();
3755         }
3756         else {
3757           dbConnection.rollback();
3758         }
3759       }
3760       catch(Exception e) {
3761         debug.println("Exception resolving transaction:  " + e.toString());
3762         throw new DAOException
3763           (LetterTemplateExceptionMessage.PROBLEM_STORE_LETTER_JOB_LOG
3764            + e.getMessage());
3765       }
3766       DAOUtil.closeResultSet(rs);
3767       DAOUtil.closePreparedStatement(ps);
3768       DAOUtil.closeConnection(dbConnection);
3769     }
3770     return answer;
3771   }
3772 
3773 
3774   /**
3775    *  Store the Log of ftps made for executed letter jobs
3776    *  of the current company in DatabaseNames.LETT_JOB_FTP_LOG table.
3777    *
3778    * @param succes Indicates if the JOB_FILE was sucessfully sent by ftp (yes)
3779    *        or not (no).
3780    * @param attempts Number of failed attempts in sending by ftp the JOB_FILE.
3781    * @param ip IP address used in last attempt in sending by ftp the JOB_FILE
3782    *          (null when the job is not distributed by ftp).
3783    * @param path complementary PATH of LAST_FTP_IP_ADDRESS.
3784    *          (null when the job is not distributed by ftp).
3785    * @param failureDescription explanation in failure case
3786    *          (null when the job is not distributed by ftp).
3787    * @param jobLogId Description of the Parameter
3788    * @param fullFilePath Description of the Parameter
3789    * @exception DAOException
3790    * @parm jobLogId The code of letter job.
3791    */
3792   public void storeLetterFtpJobLog(long jobLogId, String fullFilePath,
3793                                    boolean succes, int attempts,
3794                                    String ip, String path,
3795                                    String failureDescription)
3796      throws DAOException {
3797 
3798     debug.println("storeLetterFtpJobLog");
3799     PreparedStatement ps = null;
3800     ResultSet rs = null;
3801     String ftpDate = (ip != null) ? " SYSDATE," : " NULL,";
3802 
3803     String insertStr =
3804       " INSERT INTO " + DatabaseNames.LETT_JOB_FTP_LOG
3805        + "  (job_log_id, job_file, ftp_success, failed_attempts,"
3806        + "   last_ftp_date, last_ftp_ip_address, last_ftp_path, failure_description)"
3807        + " VALUES(?, ?, ?, ?,"
3808        + ftpDate
3809        + "        ?, ?, ?)";
3810 
3811     String execSuccess = "no";
3812     if(succes) {
3813       execSuccess = "yes";
3814     }
3815     if(ip == null) {
3816       execSuccess = "not requested";
3817     }
3818     boolean successTransaction = false;
3819     try {
3820 
3821       dbConnection = DAOUtil.getDBConnection(datasource);
3822       dbConnection.setAutoCommit(false);
3823       ps = dbConnection.prepareStatement(insertStr);
3824       ps.setLong(1, jobLogId);
3825       ps.setString(2, fullFilePath);
3826       ps.setString(3, execSuccess);
3827       debug.println("jobLogId=" + jobLogId
3828          + "--fullFilePath=" + fullFilePath
3829          + "--execSuccess =" + execSuccess);
3830       if(ip != null) {
3831         ps.setLong(4, attempts);
3832         ps.setString(5, ip);
3833         ps.setString(6, path);
3834         ps.setString(7, failureDescription);
3835         debug.println("attempts=" + attempts
3836            + "--ip=" + ip
3837            + "--path =" + path
3838            + "--failureDescription=" + failureDescription);
3839       }
3840       else {
3841         ps.setNull(4, Types.BIGINT);
3842         ps.setNull(5, Types.VARCHAR);
3843         ps.setNull(6, Types.VARCHAR);
3844         ps.setNull(7, Types.VARCHAR);
3845       }
3846       ps.executeUpdate();
3847       successTransaction = true;
3848     }
3849     catch(Exception ae) {
3850       debug.println(CommonUtil.stackTraceToString(ae));
3851       throw new DAOException
3852         (LetterTemplateExceptionMessage.PROBLEM_INSERT_LETTER_FTP_JOB_LOG
3853          + ae.getMessage());
3854     }
3855     finally {
3856       try {
3857         if(successTransaction) {
3858           dbConnection.commit();
3859         }
3860         else {
3861           dbConnection.rollback();
3862         }
3863       }
3864       catch(Exception e) {
3865         debug.println("Exception resolving transaction:  " + e.toString());
3866         throw new DAOException
3867           (LetterTemplateExceptionMessage.PROBLEM_STORE_LETTER_FTP_JOB_LOG
3868            + e.getMessage());
3869       }
3870       DAOUtil.closeResultSet(rs);
3871       DAOUtil.closePreparedStatement(ps);
3872       DAOUtil.closeConnection(dbConnection);
3873     }
3874   }
3875 
3876 
3877   /**
3878    *  Update the Log of ftps made for executed letter jobs
3879    *  of the current company in DatabaseNames.LETT_JOB_FTP_LOG table.
3880    *
3881    * @param succes Indicates if the JOB_FILE was sucessfully sent by ftp (yes)
3882    *        or not (no).
3883    * @param attempts Number of failed attempts in sending by ftp the JOB_FILE.
3884    * @param ip IP address used in last attempt in sending by ftp the JOB_FILE.
3885    * @param path complementary PATH of LAST_FTP_IP_ADDRESS.
3886    * @param failureDescription explanation in failure case.
3887    * @param jobLogId Description of the Parameter
3888    * @param fullFilePath Description of the Parameter
3889    * @exception DAOException
3890    * @parm jobLogId The code of letter job.
3891    */
3892   public void updateLetterFtpJobLog(long jobLogId, String fullFilePath,
3893                                     boolean succes, int attempts,
3894                                     String ip, String path,
3895                                     String failureDescription)
3896      throws DAOException {
3897 
3898     debug.println("updateLetterFtpJobLog");
3899     PreparedStatement ps = null;
3900     ResultSet rs = null;
3901     String updateStr =
3902       " UPDATE " + DatabaseNames.LETT_JOB_FTP_LOG + " SET "
3903        + " ftp_success = ?,"
3904        + " failed_attempts = ?,"
3905        + " last_ftp_date = SYSDATE,"
3906        + " last_ftp_ip_address = ?,"
3907        + " last_ftp_path = ?,"
3908        + " failure_description = ?"
3909        + " WHERE job_log_id = ?"
3910        + " AND job_file = ?";
3911 
3912     String execSuccess = "no";
3913     if(succes) {
3914       execSuccess = "yes";
3915     }
3916 
3917     boolean successTransaction = false;
3918     try {
3919       dbConnection = DAOUtil.getDBConnection(datasource);
3920       dbConnection.setAutoCommit(false);
3921       ps = dbConnection.prepareStatement(updateStr);
3922       ps.setString(1, execSuccess);
3923       ps.setLong(2, attempts);
3924       ps.setString(3, ip);
3925       ps.setString(4, path);
3926       ps.setString(5, failureDescription);
3927       ps.setLong(6, jobLogId);
3928       ps.setString(7, fullFilePath);
3929       ps.executeUpdate();
3930       successTransaction = true;
3931     }
3932     catch(Exception ae) {
3933       debug.println(CommonUtil.stackTraceToString(ae));
3934       throw new DAOException
3935         (LetterTemplateExceptionMessage.PROBLEM_UPDATE_LETTER_FTP_JOB_LOG
3936          + ae.getMessage());
3937     }
3938     finally {
3939       try {
3940         if(successTransaction) {
3941           dbConnection.commit();
3942         }
3943         else {
3944           dbConnection.rollback();
3945         }
3946       }
3947       catch(Exception e) {
3948         debug.println("Exception resolving transaction:  " + e.toString());
3949         throw new DAOException
3950           (LetterTemplateExceptionMessage.PROBLEM_STORE_LETTER_FTP_JOB_LOG
3951            + e.getMessage());
3952       }
3953       DAOUtil.closeResultSet(rs);
3954       DAOUtil.closePreparedStatement(ps);
3955       DAOUtil.closeConnection(dbConnection);
3956     }
3957   }
3958 
3959 
3960   /**
3961    *  Update the  date of execution of the letter job
3962    *  of the current company.
3963    *
3964    * @param date The  date of execution of the letter job.
3965    * @param jobId Description of the Parameter
3966    * @exception DAOException
3967    * @parm jobLogId The code of letter job.
3968    */
3969   public void updateJobExecDate(long jobId, Date date) throws DAOException {
3970 
3971     debug.println("updateJobExecDate");
3972     PreparedStatement ps = null;
3973     ResultSet rs = null;
3974     String updateStr =
3975       " UPDATE " + DatabaseNames.LETT_JOB + " SET"
3976        + " last_execution_date = TO_DATE( ? , \'dd-Mon-yyyy HH:MI:SS AM\')"
3977        + " WHERE job_id = ?";
3978     boolean successTransaction = false;
3979 
3980     String execDateString =
3981       new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss a").format(date);
3982 
3983     try {
3984       dbConnection = DAOUtil.getDBConnection(datasource);
3985       dbConnection.setAutoCommit(false);
3986       ps = dbConnection.prepareStatement(updateStr);
3987       ps.setString(1, execDateString);
3988       ps.setLong(2, jobId);
3989       ps.executeUpdate();
3990       successTransaction = true;
3991     }
3992     catch(Exception ae) {
3993       debug.println(CommonUtil.stackTraceToString(ae));
3994       throw new DAOException
3995         (LetterTemplateExceptionMessage.PROBLEM_UPDATE_LETTER_JOB_DATE
3996          + ae.getMessage());
3997     }
3998     finally {
3999       try {
4000         if(successTransaction) {
4001           dbConnection.commit();
4002         }
4003         else {
4004           dbConnection.rollback();
4005         }
4006       }
4007       catch(Exception e) {
4008         debug.println("Exception resolving transaction:  " + e.toString());
4009         throw new DAOException
4010           (LetterTemplateExceptionMessage.PROBLEM_STORE_LETTER_JOB_DATE
4011            + e.getMessage());
4012       }
4013 
4014       DAOUtil.closeResultSet(rs);
4015       DAOUtil.closePreparedStatement(ps);
4016       DAOUtil.closeConnection(dbConnection);
4017     }
4018   }
4019 
4020 
4021   /**
4022    *  Load the data of company locations from DatabaseNames.COMPANY_LOCATIONS
4023    *  table.
4024    *
4025    * @param ftpId The code of ftp.
4026    * @return answer The CompanyLocation object with location id, path
4027    *        ip address, ftp login name and ftp password.
4028    * @exception DAOException
4029    */
4030   public CompanyLocation loadCompanyLocation(long ftpId) throws DAOException {
4031 
4032     debug.println("loadCompanyLocation");
4033     PreparedStatement ps = null;
4034     ResultSet rs = null;
4035     String queryStr =
4036       " SELECT cmpl_id, cmpl_cad_id, cmpl_path, cmpl_name, "
4037        + " cmpl_ip_address, cmpl_user, cmpl_password "
4038        + " FROM " + DatabaseNames.COMPANY_LOCATIONS
4039        + " WHERE cmpl_id = ? ";
4040     CompanyLocation answer = new CompanyLocation();
4041 
4042     try {
4043       dbConnection = DAOUtil.getDBConnection(datasource);
4044       ps = dbConnection.prepareStatement(queryStr);
4045       ps.setLong(1, ftpId);
4046       ps.executeQuery();
4047       rs = ps.getResultSet();
4048       rs.next();
4049       answer.setLocationId(rs.getLong(1));
4050       answer.setCadId(rs.getLong(2));
4051       answer.setPath(rs.getString(3));
4052       answer.setName(rs.getString(4));
4053       answer.setIpAddress(rs.getString(5));
4054       answer.setUser(rs.getString(6));
4055       answer.setPassword(rs.getString(7));
4056     }
4057     catch(Exception ae) {
4058       debug.println(CommonUtil.stackTraceToString(ae));
4059       throw new DAOException
4060         (LetterTemplateExceptionMessage.PROBLEM_LOAD_COMPANY_LOCATIONS
4061          + ae.getMessage());
4062     }
4063     finally {
4064       DAOUtil.closeResultSet(rs);
4065       DAOUtil.closePreparedStatement(ps);
4066       DAOUtil.closeConnection(dbConnection);
4067     }
4068     return answer;
4069   }
4070 
4071 
4072   /**
4073    *  Review the batch of letters jobs from tables
4074    *
4075    * @param dayMonthYear The date to ask for letter Job Log information
4076    * @return answer The LetterBatchReviewModel object with Job Log information.
4077    * @exception DAOException
4078    */
4079   public LetterBatchReviewModel loadLetterBatchReview(String dayMonthYear)
4080      throws DAOException {
4081 
4082     debug.println("loadLetterBatchReview");
4083 
4084     PreparedStatement ps = null;
4085     ResultSet rs = null;
4086     LetterBatchReviewModel answer = null;
4087     JobLogInfo jobLogInfo = null;
4088     FileLogInfo fileLogInfo = null;
4089     VariablesFormat variablesFormat = new VariablesFormat();
4090     String queryStr =
4091       "SELECT j.name, j.description, "
4092        + " l.execution_date, l.execution_success, l.number_of_records,"
4093        + " f.job_file, f.ftp_success, f.failed_attempts,"
4094        + " f.last_ftp_date, f.last_ftp_ip_address, f.failure_description"
4095        + " FROM " + DatabaseNames.LETT_JOB + " j, "
4096        + DatabaseNames.LETT_JOB_LOG + " l, "
4097        + DatabaseNames.LETT_JOB_FTP_LOG + " f, "
4098        + DatabaseNames.COMPANIES + " c "
4099        + " WHERE c.cmp_id = ?"
4100        + " AND   c.cmp_id = j.code_company"
4101        + " AND   j.job_id = l.job_id"
4102        + " AND   l.job_log_id = f.job_log_id (+)"
4103        + " AND   TRUNC(l.execution_date) = TO_DATE( ?, \'dd-Mon-yyyy\')"
4104        + " ORDER BY j.name, l.execution_date, f.job_file ";
4105     String oldname = "";
4106     String lastFtpDate = "";
4107     int i;
4108     int index = 0;
4109     int num = -1;
4110 
4111     try {
4112       // initialize LetterBatchReviewModel
4113       answer = new LetterBatchReviewModel(dayMonthYear);
4114       dbConnection = DAOUtil.getDBConnection(datasource);
4115       ps = dbConnection.prepareStatement(queryStr);
4116       ps.setLong(1, Long.parseLong(companyId));
4117       ps.setString(2, dayMonthYear);
4118       ps.executeQuery();
4119       rs = ps.getResultSet();
4120       for(i = 0; rs.next(); i++) {
4121         lastFtpDate = null;
4122         String name = rs.getString(1);
4123         String description = rs.getString(2);
4124         Date executionDate1 = rs.getDate(3);
4125         String executionDate = new SimpleDateFormat
4126           ("MMM dd,yyyy hh:mm:ss a").format(executionDate1);
4127         String jobOK = rs.getString(4);
4128         String numberRecords = rs.getString(5);
4129         String jobFile = rs.getString(6);
4130         debug.println("jobFile=" + jobFile);
4131         if(!rs.wasNull()) {
4132           index = jobFile.lastIndexOf("\\");
4133           jobFile = jobFile.substring(index + 1, jobFile.length());
4134         }
4135         String ftpSucces = rs.getString(7);
4136         String failedAttempts = rs.getString(8);
4137         Date lastFtpDate1 = rs.getDate(9);
4138         if(!rs.wasNull()) {
4139           lastFtpDate = new SimpleDateFormat
4140             ("MMM dd,yyyy hh:mm:ss a").format(lastFtpDate1);
4141         }
4142         String lastFtpIpAddress = rs.getString(10);
4143         String failureDescription = rs.getString(11);
4144         if(!oldname.equals(executionDate)) {
4145           // initialize JobLogInfo
4146           num++;
4147           jobLogInfo = new JobLogInfo(name, description, executionDate,
4148             jobOK, numberRecords);
4149           if(jobOK.equals(LetterTemplateGlobals.LETTER_JOB_OK)) {
4150             fileLogInfo = new FileLogInfo(jobFile, ftpSucces, failedAttempts,
4151               lastFtpDate, lastFtpIpAddress, failureDescription);
4152             jobLogInfo.getFileLogInfo().add(fileLogInfo);
4153           }
4154           answer.getJobLogInfo().add(jobLogInfo);
4155         }
4156         else {  // oldname.equals(executionDate)
4157           if(jobOK.equals(LetterTemplateGlobals.LETTER_JOB_OK)) {
4158             fileLogInfo = new FileLogInfo(jobFile, ftpSucces, failedAttempts,
4159               lastFtpDate, lastFtpIpAddress, failureDescription);
4160             ((JobLogInfo)answer.getJobLogInfo().get(num)).
4161               getFileLogInfo().add(fileLogInfo);
4162           }
4163         }
4164         oldname = executionDate;
4165       }
4166     }
4167     catch(Exception ae) {
4168       debug.println(CommonUtil.stackTraceToString(ae));
4169       throw new DAOException
4170         (LetterTemplateExceptionMessage.PROBLEM_LOAD_JOB_FTP_LOGS
4171          + ae.getMessage());
4172     }
4173     finally {
4174       DAOUtil.closeResultSet(rs);
4175       DAOUtil.closePreparedStatement(ps);
4176       DAOUtil.closeConnection(dbConnection);
4177     }
4178     return answer;
4179   }
4180 
4181 
4182   // AUXILIARY METHODS FOR STORING AND LOADING LETTERS COMPONENTS
4183 
4184   /**
4185    *  Auxiliary for storeComponent: stores a letter component
4186    *  in tables DatabaseNames.LETT_COMPONENT, LETT_VARIABLE, LETT_IMAGE
4187    *
4188    * @param component to store (LetterComponent)
4189    * @param ps auxiliary PreparedStatement
4190    * @param rs auxiliary ResultSet
4191    * @return CodeDescription: [code, stamp] of component
4192    * @exception Exception
4193    */
4194   private CodeDescription auxStoreComponent(LetterComponent component,
4195                                             PreparedStatement ps, ResultSet rs)
4196      throws Exception {
4197     long componentCode = component.getCode();
4198     String componentStamp = component.getStamp();
4199     boolean componentIsNew;
4200     PreparedStatement ps1;
4201     PreparedStatement ps2;
4202     ps1 = ps2 = null;
4203 
4204     String queryStrVersion =
4205       " SELECT last_changed_date "
4206        + " FROM " + DatabaseNames.LETT_COMPONENT
4207        + " WHERE code_component = ? "
4208        + " FOR UPDATE";
4209     // exclusive lock
4210 
4211     String deleteStrVariables =
4212       " DELETE " + DatabaseNames.LETT_VARIABLE
4213        + " WHERE code_component = ? ";
4214 
4215     String deleteStrImages =
4216       " DELETE " + DatabaseNames.LETT_IMAGE
4217        + " WHERE code_component = ? ";
4218 
4219     String insertStrComponent =
4220       " INSERT INTO " + DatabaseNames.LETT_COMPONENT
4221        + "   (code_component, code_company, code_component_type,"
4222        + "    code_print_type, description, text,"
4223        + "    last_changed_by, last_changed_date)"
4224        + " VALUES("
4225        + DatabaseNames.SEQ_LETT_COMPONENT + ".nextval,"
4226        + "   ?, ?, ?, ?, EMPTY_BLOB(), ?, SYSDATE)";
4227 
4228     String updateStrComponent =
4229       " UPDATE " + DatabaseNames.LETT_COMPONENT + " SET"
4230        + "   code_component_type = ?,"
4231        + "   code_print_type = ?,"
4232        + "   description = ?,"
4233        + "   text = EMPTY_BLOB(),"
4234        + "   last_changed_by = ?,"
4235        + "   last_changed_date = SYSDATE"
4236        + " WHERE code_component = ?";
4237 
4238     String queryStrCodeStamp =
4239       " SELECT code_component, last_changed_date "
4240        + " FROM " + DatabaseNames.LETT_COMPONENT
4241        + " WHERE code_company = ?  AND code_component_type = ?"
4242        + "    AND code_print_type = ? AND description = ?";
4243 
4244     String queryStrText =
4245       " SELECT text "
4246        + " FROM " + DatabaseNames.LETT_COMPONENT
4247        + " WHERE code_component = ?";
4248 
4249     String insertStrVariable =
4250       " INSERT INTO " + DatabaseNames.LETT_VARIABLE
4251        + "  (code_component, position, field_id, code_format, offset)"
4252        + " VALUES"
4253        + "  (?, ?, ?, ?, ?)";
4254 
4255     String insertStrImage =
4256       " INSERT INTO " + DatabaseNames.LETT_IMAGE
4257        + "  (code_component, position, image)"
4258        + " VALUES"
4259        + "  (?, ?, EMPTY_BLOB())";
4260 
4261     String queryStrImage =
4262       " SELECT image "
4263        + " FROM " + DatabaseNames.LETT_IMAGE
4264        + " WHERE code_component = ? AND position = ?";
4265 
4266     componentIsNew = (componentCode == LetterTemplateGlobals.UNDEF) ? true : false;
4267 
4268     // verify valid version of existing component:
4269     if(!componentIsNew) {
4270       ps = dbConnection.prepareStatement(queryStrVersion);
4271       ps.setLong(1, componentCode);
4272       ps.executeQuery();
4273       rs = ps.getResultSet();
4274       rs.next();
4275       String version = rs.getString(1);
4276       if(!version.equals(component.getStamp())) {
4277         throw new DAOException
4278           (LetterTemplateExceptionMessage.PROBLEM_STORE_COMPONENT_INVALID);
4279       }
4280       DAOUtil.closePreparedStatement(ps);
4281     }
4282 
4283     // delete component variables and images from DB if component is not new
4284     // (necessary for replacing):
4285     if(!componentIsNew) {
4286       ps = dbConnection.prepareStatement(deleteStrVariables);
4287       ps.setLong(1, componentCode);
4288       ps.executeUpdate();
4289       DAOUtil.closePreparedStatement(ps);
4290 
4291       ps = dbConnection.prepareStatement(deleteStrImages);
4292       ps.setLong(1, componentCode);
4293       ps.executeUpdate();
4294       DAOUtil.closePreparedStatement(ps);
4295     }
4296 
4297     // update o insert component tuple (master) depending of componentIsNew
4298     if(componentIsNew) {
4299       ps = dbConnection.prepareStatement(insertStrComponent);
4300       ps.setLong(1, Long.parseLong(companyId));
4301       ps.setInt(2, component.getType());
4302       ps.setInt(3, component.getPrintType());
4303       ps.setString(4, component.getName());
4304       ps.setLong(5, this.userId.longValue());
4305       ps.executeUpdate();
4306     }
4307     else {
4308       ps = dbConnection.prepareStatement(updateStrComponent);
4309       ps.setInt(1, component.getType());
4310       ps.setInt(2, component.getPrintType());
4311       ps.setString(3, component.getName());
4312       ps.setLong(4, this.userId.longValue());
4313       ps.setLong(5, componentCode);
4314       ps.executeUpdate();
4315     }
4316     DAOUtil.closePreparedStatement(ps);
4317 
4318     // get componentCode and componentStamp from DB:
4319     ps = dbConnection.prepareStatement(queryStrCodeStamp);
4320     ps.setLong(1, Long.parseLong(companyId));
4321     ps.setInt(2, component.getType());
4322     ps.setInt(3, component.getPrintType());
4323     ps.setString(4, component.getName());
4324     ps.executeQuery();
4325     rs = ps.getResultSet();
4326     rs.next();
4327     componentCode = rs.getLong(1);
4328     componentStamp = rs.getString(2);
4329     DAOUtil.closePreparedStatement(ps);
4330 
4331     // obtain reference to BLOB text field and write BLOB data on DB:
4332     ps = dbConnection.prepareStatement(queryStrText);
4333     ps.setLong(1, componentCode);
4334     java.sql.Blob textFieldRef = DAOUtil.getBlobReference(ps, rs);
4335     InputStream is
4336        = new ByteArrayInputStream(component.getRtfText().getBytes());
4337     DAOUtil.writeBlobData(textFieldRef, is);
4338     DAOUtil.closePreparedStatement(ps);
4339 
4340     // insert variables of the component
4341     ArrayList traceVariables = component.getTraceVariables();
4342     ps = dbConnection.prepareStatement(insertStrVariable);
4343     for(int i = 0; i < traceVariables.size(); i++) {
4344       ArrayList slot = (ArrayList)traceVariables.get(i);
4345       Integer position = (Integer)slot.get(0);
4346       Long fieldId = (Long)slot.get(1);
4347       Long codeFormat = (Long)slot.get(2);
4348       Long offset = (Long)slot.get(3);
4349       ps.setLong(1, componentCode);
4350       ps.setInt(2, position.intValue());
4351       ps.setLong(3, fieldId.longValue());
4352       ps.setLong(4, codeFormat.longValue());
4353       ps.setLong(5, offset.longValue());
4354       ps.executeUpdate();
4355     }
4356     DAOUtil.closePreparedStatement(ps);
4357 
4358     // insert images of the component
4359     ArrayList traceImages = component.getTraceImages();
4360     ps1 = dbConnection.prepareStatement(insertStrImage);
4361     ps2 = dbConnection.prepareStatement(queryStrImage);
4362     for(int i = 0; i < traceImages.size(); i++) {
4363       ArrayList slot = (ArrayList)traceImages.get(i);
4364       Integer position = (Integer)slot.get(0);
4365       byte[] image = (byte[])slot.get(1);
4366       ps1.setLong(1, componentCode);
4367       ps1.setInt(2, position.intValue());
4368       ps1.executeUpdate();
4369 
4370       // obtain reference to BLOB image field and write BLOB data on DB
4371       ps2.setLong(1, componentCode);
4372       ps2.setInt(2, position.intValue());
4373       java.sql.Blob imageFieldRef = DAOUtil.getBlobReference(ps2, rs);
4374       InputStream is2 = new ByteArrayInputStream(image);
4375       DAOUtil.writeBlobData(imageFieldRef, is2);
4376     }
4377     DAOUtil.closePreparedStatement(ps1);
4378     DAOUtil.closePreparedStatement(ps2);
4379     return new CodeDescription(componentCode, componentStamp);
4380   }
4381 
4382 
4383   /**
4384    *  Auxiliary for loadComponent: loads a letter component
4385    *  from tables DatabaseNames.LETT_COMPONENT, LETT_VARIABLE, LETT_IMAGE
4386    *
4387    * @param componentCode code of component to load
4388    * @param ps auxiliary PreparedStatement
4389    * @param rs auxiliary ResultSet
4390    * @return LetterComponent: letter component
4391    * @exception Exception
4392    */
4393   private LetterComponent auxLoadComponent(long componentCode,
4394                                            PreparedStatement ps, ResultSet rs)
4395      throws Exception {
4396     LetterComponent answer = null;
4397 
4398     // elements of component:
4399     int type;
4400 
4401     // elements of component:
4402     int printType;
4403     String name;
4404     String rtfText;
4405     ArrayList traceImages;
4406     ArrayList traceVariables;
4407     String stamp;
4408 
4409     byte[] textArray = new byte[LetterTemplateGlobals.MAX_TEXT_SIZE];
4410     byte[] imageArray = new byte[LetterTemplateGlobals.MAX_IMAGE_SIZE];
4411 
4412     String queryStrComponent =
4413       " SELECT code_component_type, code_print_type, description,"
4414        + "        text, last_changed_date"
4415        + " FROM " + DatabaseNames.LETT_COMPONENT
4416        + " WHERE code_component = ? AND code_company = ? "
4417        + " FOR UPDATE";
4418     // exclusive lock
4419 
4420     String queryStrVariables =
4421       " SELECT position, field_id, code_format, offset "
4422        + " FROM " + DatabaseNames.LETT_VARIABLE
4423        + " WHERE code_component = ? "
4424        + " ORDER BY position DESC ";
4425 
4426     String queryStrImages =
4427       " SELECT position, image"
4428        + " FROM " + DatabaseNames.LETT_IMAGE
4429        + " WHERE code_component = ? "
4430        + " ORDER BY position DESC ";
4431 
4432     // select component tuple (master) and reference to BLOB text:
4433     ps = dbConnection.prepareStatement(queryStrComponent);
4434     ps.setLong(1, componentCode);
4435     ps.setLong(2, Long.parseLong(companyId));
4436     ps.executeQuery();
4437     rs = ps.getResultSet();
4438     rs.next();
4439     type = rs.getInt(1);
4440     printType = rs.getInt(2);
4441     name = rs.getString(3);
4442     java.sql.Blob refText = rs.getBlob(4);
4443     stamp = rs.getString(5);
4444     DAOUtil.closePreparedStatement(ps);
4445 
4446     // get BLOB text from DB:
4447     rtfText = DAOUtil.getBlobText(refText, textArray);
4448 
4449     // get variables of the component:
4450     ps = dbConnection.prepareStatement(queryStrVariables);
4451     ps.setLong(1, componentCode);
4452     ps.executeQuery();
4453     rs = ps.getResultSet();
4454     traceVariables = new ArrayList();
4455     while(rs.next()) {
4456       int pos = rs.getInt(1);
4457       long fId = rs.getLong(2);
4458       long codFmt = rs.getLong(3);
4459       long offset = rs.getLong(4);
4460       ArrayList slot = new ArrayList(4);
4461       slot.add(new Integer(pos));
4462       slot.add(new Long(fId));
4463       slot.add(new Long(codFmt));
4464       slot.add(new Long(offset));
4465       traceVariables.add(slot);
4466     }
4467     DAOUtil.closePreparedStatement(ps);
4468 
4469     // get images of the component:
4470     ps = dbConnection.prepareStatement(queryStrImages);
4471     ps.setLong(1, componentCode);
4472     ps.executeQuery();
4473     rs = ps.getResultSet();
4474     traceImages = new ArrayList();
4475     while(rs.next()) {
4476       int position = rs.getInt(1);
4477       java.sql.Blob refImage = rs.getBlob(2);
4478       byte[] image = DAOUtil.getBlobImage(refImage, imageArray);
4479 
4480       ArrayList slot = new ArrayList(2);
4481       slot.add(new Integer(position));
4482       slot.add(image);
4483       traceImages.add(slot);
4484     }
4485 
4486     answer = new LetterComponent(componentCode, type, printType, name,
4487       rtfText, traceVariables, traceImages, stamp);
4488     return answer;
4489   }
4490 
4491 
4492   /**
4493    *  Auxiliary for linking a template and a component precondition there
4494    *  isn't any link before between template and component
4495    *
4496    * @param templateCode code of template
4497    * @param componentCode code of component
4498    * @param ps auxiliary PreparedStatement
4499    * @param rs auxiliary ResultSet
4500    * @exception Exception
4501    */
4502   private void linkTemplateComponent(long templateCode, long componentCode,
4503                                      PreparedStatement ps, ResultSet rs)
4504      throws Exception {
4505 
4506     String insertStr =
4507       " INSERT INTO " + DatabaseNames.LETT_TEMPLATE_COMPONENT_LINK
4508        + "  (code_template, code_component)"
4509        + " VALUES"
4510        + "  (?, ?)";
4511 
4512     ps = dbConnection.prepareStatement(insertStr);
4513     ps.setLong(1, templateCode);
4514     ps.setLong(2, componentCode);
4515     ps.executeUpdate();
4516 
4517     return;
4518   }
4519 
4520   // AUXILIARY METHOD FOR loadLetterJob SERVICE
4521 
4522   /**
4523    *  Auxiliary for loadLetterJob service.
4524    *  Check the type of letter job.
4525    *
4526    * @param frequency The frequency of letter job generation.
4527    * @param status The state of letter job.
4528    * @param activationDate Date in which the letter job can be executed the first time.
4529    * @param lastDate The date of last execution of the letter job.
4530    * @param empty If lastDate is null its value is LetterTemplateGlobals.STR_UNDEF
4531    * @return type The type of letter Job.
4532    */
4533   private String verifyDate(String frequency, String status, Date activationDate,
4534                             Date lastDate, String empty) {
4535 
4536     String type = LetterTemplateGlobals.RUN;
4537     String date = this.form.format(this.toDay);
4538 
4539     if(this.toDay.before(activationDate) ||
4540       frequency.equals(LetterTemplateGlobals.ON_REQUEST) ||
4541       status.equals(LetterTemplateGlobals.INACTIVE) ||
4542       empty.equals(LetterTemplateGlobals.STR_UNDEF)) {
4543       type = LetterTemplateGlobals.OTHER;
4544     }
4545     // verify year
4546     else if(status.equals(LetterTemplateGlobals.ACTIVE)
4547        && frequency.equals(LetterTemplateGlobals.YEARLY)) {
4548       this.calendar.setTime(lastDate);
4549       this.calendar.add(Calendar.YEAR, 1);
4550       java.util.Date toYear = this.calendar.getTime();
4551       String caldate = this.form.format(toYear);
4552       if(!caldate.equals(date)) {
4553         type = LetterTemplateGlobals.OUT;
4554       }
4555     }
4556     // verify month
4557     else if(status.equals(LetterTemplateGlobals.ACTIVE)
4558        && frequency.equals(LetterTemplateGlobals.MONTHLY)) {
4559       this.calendar.setTime(lastDate);
4560       this.calendar.add(Calendar.MONTH, 1);
4561       java.util.Date toMonth = this.calendar.getTime();
4562       String caldate = this.form.format(toMonth);
4563       if(!caldate.equals(date)) {
4564         type = LetterTemplateGlobals.OUT;
4565       }
4566     }
4567     // verify week
4568     else if(status.equals(LetterTemplateGlobals.ACTIVE)
4569        && frequency.equals(LetterTemplateGlobals.WEEKLY)) {
4570       this.calendar.setTime(lastDate);
4571       this.calendar.add(Calendar.WEEK_OF_MONTH, 1);
4572       java.util.Date toWeek = this.calendar.getTime();
4573       String caldate = this.form.format(toWeek);
4574       if(!caldate.equals(date)) {
4575         type = LetterTemplateGlobals.OUT;
4576       }
4577     }
4578     // verify day
4579     else if(status.equals(LetterTemplateGlobals.ACTIVE)
4580        && frequency.equals(LetterTemplateGlobals.DAILY)) {
4581       this.calendar.setTime(lastDate);
4582       this.calendar.add(Calendar.DATE, 1);
4583       java.util.Date toDate = this.calendar.getTime();
4584       String caldate = this.form.format(toDate);
4585       if(!caldate.equals(date)) {
4586         type = LetterTemplateGlobals.OUT;
4587       }
4588     }
4589     return type;
4590   }
4591 
4592 
4593   // AUXILIARY METHODS FOR executeSQL SERVICE:
4594 
4595   /**
4596    *  Auxiliary for executeSQL service.
4597    *  Transform a sentenceSQL replacing all expressions:
4598    *       "SYSDATE",           "COMPANY_DATE",
4599    *       "SYSDATE ++ n",      "SYSDATE -- n",
4600    *       "COMPANY_DATE ++ n", "COMPANY_DATE -- n"
4601    *  by equivalent SQL date literals to the workable days offset.
4602    *
4603    * @param sentenceSQL The SQL sentence to transform.
4604    * @param sysDate Date of today.
4605    * @param companyDate batch Date of current company.
4606    * @return String resulting of transformation.
4607    * @throws DAOException Description of the Exception
4608    */
4609   private String auxTransformWorkableOffset(String sentenceSQL,
4610                                             java.sql.Date sysDate, java.sql.Date companyDate)
4611      throws DAOException {
4612     debug.println("auxTransformWorkableOffset");
4613 
4614     String answer = "";
4615     String sentencePhase1;
4616     String sentencePhase2;
4617     int indexCOMPANY_DATE;
4618     String beforeCOMPANY_DATE;
4619     SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy");
4620     String companyDateString = "TO_DATE('" + sdf.format(companyDate)
4621        + "','MM-DD-YYYY')";
4622 
4623     sentencePhase1
4624        = auxReplaceWorkableOperator(sentenceSQL, "++", sysDate, companyDate);
4625     sentencePhase2
4626        = auxReplaceWorkableOperator(sentencePhase1, "--", sysDate, companyDate);
4627 
4628     int lastIndex = sentencePhase2.length() - 1;
4629     int currentIndex = 0;
4630     while((indexCOMPANY_DATE
4631        = sentencePhase2.indexOf("COMPANY_DATE", currentIndex)) > 0) {
4632       beforeCOMPANY_DATE
4633          = sentencePhase2.substring(currentIndex, indexCOMPANY_DATE);
4634 
4635       if(!(sentencePhase2.charAt(indexCOMPANY_DATE - 1) == '.')) {
4636         answer += beforeCOMPANY_DATE + companyDateString;
4637       }
4638       else {
4639         answer += beforeCOMPANY_DATE + "COMPANY_DATE";
4640       }
4641       currentIndex = indexCOMPANY_DATE + 12;
4642     }  // end of while
4643 
4644     answer += sentencePhase2.substring(currentIndex, lastIndex + 1);
4645     //debug.println("answer="+ answer);
4646     return answer;
4647   }
4648 
4649 
4650   /**
4651    *  Auxiliary for executeSQL service.
4652    *  Transform a SQL sentence replacing each substring of type
4653    *  <special field>  <workable operator>  <value> (example: COMPANY_DATE ++ 67)
4654    *  by equivalent SQL date literals to the workable days offset.
4655    *  The transformation is made only for one of the workable operator (++, --)
4656    *
4657    * @param sentence The SQL sentence to transform.
4658    * @param workableOperator The workable operator (++  or -- )
4659    * @param sysDate Date of today.
4660    * @param companyDate batch Date of current company.
4661    * @return String resulting of transformation.
4662    * @throws DAOException Description of the Exception
4663    */
4664   private String auxReplaceWorkableOperator(String sentence, String workableOperator,
4665                                             java.sql.Date sysDate, java.sql.Date companyDate)
4666      throws DAOException {
4667 
4668     debug.println("auxReplaceWorkableOperator for workableOperator:" + workableOperator);
4669 
4670     String beforeWorkableOperator;
4671 
4672     String afterWorkableOperator;
4673 
4674     String copieAfterWorkableOperator;
4675     String specialField;
4676     String beforeSpecialField;
4677     String value;
4678     String workableDate;
4679     StringTokenizer tokens;
4680     int indexSpecialField;
4681     int indexWorkableOperator;
4682     int indexValue;
4683     java.sql.Date specialDate;
4684     java.sql.Date resultingDate;
4685     String answer = "";
4686 
4687     if(companyCalendars == null) {
4688       companyCalendars = this.loadCalendars();
4689     }
4690     SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yyyy");
4691 
4692     int lastIndex = sentence.length() - 1;
4693     int currentIndex = 0;
4694 
4695     while((indexWorkableOperator
4696        = sentence.indexOf(workableOperator, currentIndex)) > 0) {
4697       beforeWorkableOperator
4698          = sentence.substring(currentIndex, indexWorkableOperator);
4699       afterWorkableOperator
4700          = sentence.substring(indexWorkableOperator + 2, lastIndex + 1);
4701 
4702       specialField = (beforeWorkableOperator.trim().endsWith("SYSDATE")) ?
4703         "SYSDATE" : "COMPANY_DATE";
4704 
4705       indexSpecialField = beforeWorkableOperator.lastIndexOf(specialField);
4706       beforeSpecialField = beforeWorkableOperator.substring(0, indexSpecialField);
4707       answer += beforeSpecialField;
4708 
4709       copieAfterWorkableOperator = new String(afterWorkableOperator);
4710       tokens = new StringTokenizer(copieAfterWorkableOperator, " ),");
4711       value = tokens.nextToken();
4712 
4713       specialDate = (specialField.equals("SYSDATE")) ? sysDate : companyDate;
4714       int offset = (workableOperator.equals("++"))
4715          ? Integer.parseInt(value)
4716          : -Integer.parseInt(value);
4717       java.util.Date resultingDateU = CommonUtil.workableOffset
4718         (specialDate, offset, companyCalendars);
4719       if(resultingDateU == null) {
4720         throw new DAOException
4721           (LetterTemplateExceptionMessage.INSUFFICIENT_CALENDARS
4722            + specialField + " " + workableOperator + " " + value);
4723       }
4724       resultingDate = new java.sql.Date(resultingDateU.getTime());
4725       workableDate = "TO_DATE('" + sdf.format(resultingDate) + "','MM-DD-YYYY')";
4726       answer += workableDate;
4727 
4728       indexValue = afterWorkableOperator.indexOf(value, 0);
4729       currentIndex = indexWorkableOperator + 2 + indexValue + value.length();
4730     }  // end of while
4731 
4732     answer += sentence.substring(currentIndex, lastIndex + 1);
4733     return answer;
4734   }
4735 
4736 
4737   public void insertLetterARHistory(Connection dbConnection, long lCompID, long lAgrmID, Date procDate, long lLettID, long lLettCode, long lActionCode, long lResultCode)
4738      throws RemoteException, DAOException {
4739 
4740     PreparedStatement ps = null;
4741     ResultSet rs = null;
4742     String insertStr =
4743       " INSERT INTO " + DatabaseNames.COLL_ACTION_RESULTS_HISTORY
4744        + "  (acrh_id, acrh_agrm_id, acrh_act_id, acrh_res_id,"
4745        + "   acrh_let_id, acrh_user_id, acrh_qplan_id, acrh_date,"
4746        + "   acrh_comments, acrh_customer_contact, acrh_time_loop,"
4747        + "   acrh_day_loop, acrh_next_review_date, acrh_flag_show)"
4748        + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
4749 
4750     String insertLetterProduced =
4751       " INSERT INTO " + DatabaseNames.LETT_PRODUCE
4752        + "  (letprd_id, letprd_company, letprd_template, "
4753        + "   letprd_agrm_id, letprd_date, letprd_status)"
4754        + " VALUES (?, ?, ?, ?, ?, ?)";
4755 
4756     String sDesc = "*** Batch Letter Sent ***";
4757 
4758     boolean successTransaction = false;
4759     try {
4760       dbConnection.setAutoCommit(false);
4761       ps = dbConnection.prepareStatement(insertStr);
4762 
4763       long lSeq = SqlUtils.nextOracleSequence(dbConnection, false, "SEQ_ID_GENERATOR");
4764 
4765       ps.setLong(1, lSeq);  // Sequence
4766       ps.setLong(2, lAgrmID);  // Agrm ID
4767       ps.setLong(3, lActionCode);  // Action Code: SY
4768       ps.setLong(4, lResultCode);  // Result Code: SL
4769       ps.setLong(5, lLettID);  // Letter ID
4770       ps.setLong(6, 4);  // SYSGEN User ID
4771       ps.setNull(7, Types.NUMERIC);  // Queue Plan ID
4772       ps.setDate(8, procDate);  // Date
4773       ps.setString(9, sDesc);  // Comments
4774       ps.setLong(10, 0);  // Customer Contact
4775       ps.setLong(11, 0);  // Time Loop
4776       ps.setLong(12, 0);  // Day Loop
4777       ps.setDate(13, procDate);  // Next Review Date
4778       ps.setString(14, "Y");  // Show Flag
4779 
4780       ps.executeUpdate();
4781 
4782       DAOUtil.closePreparedStatement(ps);
4783 
4784       ps = dbConnection.prepareStatement(insertLetterProduced);
4785 
4786       lSeq = SqlUtils.nextOracleSequence(dbConnection, false, "SEQ_LETT_PRODUCE");
4787 
4788       ps.setLong(1, lSeq);
4789       ps.setLong(2, lCompID);
4790       ps.setLong(3, lLettCode);
4791       ps.setLong(4, lAgrmID);
4792       ps.setDate(5, procDate);
4793       ps.setString(6, "A");
4794 
4795       ps.executeUpdate();
4796 
4797       DAOUtil.closePreparedStatement(ps);
4798 
4799       successTransaction = true;
4800     }
4801     catch(Exception ae) {
4802       debug.println(CommonUtil.stackTraceToString(ae));
4803       throw new DAOException
4804         (LetterTemplateExceptionMessage.PROBLEM_BATCH_ACTION_RESULT_HISTORY
4805          + ae.getMessage());
4806     }
4807     finally {
4808       try {
4809         if(successTransaction) {
4810           dbConnection.commit();
4811         }
4812         else {
4813           dbConnection.rollback();
4814         }
4815       }
4816       catch(Exception e) {
4817         debug.println("Exception resolving transaction:  " + e.toString());
4818         throw new DAOException
4819           (LetterTemplateExceptionMessage.PROBLEM_BATCH_ACTION_RESULT_HISTORY
4820            + e.getMessage());
4821       }
4822       DAOUtil.closeResultSet(rs);
4823       DAOUtil.closePreparedStatement(ps);
4824       //DAOUtil.closeConnection( dbConnection);
4825     }
4826   }
4827 
4828 }
4829 
4830 
4831 
4832