View Javadoc

1   /* ===================================================================
2    * Copyright 2002-05 SRI International.
3    * Released under the MOZILLA PUBLIC LICENSE Version 1.1
4    * which can be obtained at http://www.mozilla.org/MPL/MPL-1.1.html
5    * This software is distributed on an "AS IS"
6    * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
7    * See the License for the specific language governing rights and
8    * limitations under the License.
9    * =================================================================== */
10  
11  package com.sri.emo.wizard.completion.persistence;
12  
13  import com.jcorporate.expresso.core.dataobjects.jdbc.JDBCDataObject;
14  import com.jcorporate.expresso.core.db.DBConnection;
15  import com.jcorporate.expresso.core.db.DBConnectionPool;
16  import com.jcorporate.expresso.core.db.DBException;
17  import com.jcorporate.expresso.core.db.exception.DBRecordNotFoundException;
18  import com.jcorporate.expresso.core.registry.RequestRegistry;
19  import com.sri.common.dbobj.ObjectNotFoundException;
20  import com.sri.common.dbobj.RepositoryConversionException;
21  import com.sri.common.dbobj.RepositoryException;
22  import com.sri.emo.dbobj.WizDefinition;
23  import com.sri.emo.wizard.completion.CompletionRepository;
24  import com.sri.emo.wizard.completion.model.CompletionBean;
25  import com.sri.emo.wizard.completion.model.FieldCompletion;
26  import org.apache.log4j.Logger;
27  
28  
29  /***
30   * Expresso-specific implementation that converts the completion beans to
31   * DBObjects.
32   *
33   * @author Michael Rimov
34   */
35  public class ExpressoCompletionRepository implements CompletionRepository {
36  
37      /***
38       * The bean to dbobject converter bridge.
39       */
40      private final CompletionDBObjConverter completionConverter;
41  
42      private Logger mLog = Logger.getLogger(ExpressoCompletionRepository.class);
43  
44      /***
45       * Completion Repository constructor that takes a converter.
46       *
47       * @param converter CompletionDBObjConverter
48       */
49      public ExpressoCompletionRepository(final CompletionDBObjConverter converter) {
50          assert converter != null;
51          completionConverter = converter;
52      }
53  
54      /***
55       * Adds a CompletionBean to the underlying data store.
56       *
57       * @param newValue CompletionBean the metadata for the wizard to update.
58       * @return the new wizard id.
59       * @throws RepositoryException           upon underlying error.
60       * @throws RepositoryConversionException if there was an error converting
61       *                                       the <tt>CompletionBean</tt> object to the underlying WizDefinition DBObject.
62       */
63      public int add(final CompletionBean newValue) throws RepositoryException, RepositoryConversionException {
64          assert newValue != null;
65  
66          DBConnection connection = null;
67          WizDefinition wizDef = null;
68          try {
69              wizDef = completionConverter.convertToDBObject(newValue);
70  
71              assert wizDef != null;
72              connection = DBConnectionPool.getInstance(RequestRegistry.getDataContext()).getConnection(
73                      "Add Completion Wizard");
74              connection.setAutoCommit(false);
75              wizDef.setConnection(connection);
76              wizDef.add();
77              connection.commit();
78  
79              newValue.setWizardId(new Integer(wizDef.getId()));
80              return Integer.parseInt(wizDef.getId());
81          } catch (DBException ex) {
82              try {
83                  connection.rollback();
84              } catch (DBException e) {
85                  mLog.debug("problem rolling back: " + ex.getMessage());
86              }
87              throw new RepositoryException("Error adding wizard definition: " + newValue.toString(), ex);
88          } finally {
89              if (connection != null) {
90                  connection.release();
91              }
92          }
93  
94      }
95  
96      /***
97       * Deletes the completion bean from the underlying data store.
98       *
99       * @param wizardId int the wizard surrogate key.
100      * @throws RepositoryException     upon deletion error.
101      * @throws ObjectNotFoundException if the given wizard Id doesn't exist.
102      */
103     public void delete(final int wizardId) throws RepositoryException, ObjectNotFoundException {
104         assert wizardId > 0;
105 
106         DBConnection dbConnection = null;
107         try {
108             WizDefinition wizDef = new WizDefinition();
109             dbConnection = DBConnectionPool.getInstance(RequestRegistry.getDataContext()).getConnection(
110                     "Delete Wizard Definition");
111 
112             dbConnection.setAutoCommit(false);
113             wizDef.setConnection(dbConnection);
114             wizDef.setId(wizardId);
115             wizDef.retrieve();
116             JDBCDataObject associatedObject = (JDBCDataObject) wizDef.getAdditionalInfo();
117             associatedObject.setConnection(dbConnection);
118             wizDef.delete();
119             if (associatedObject != null && associatedObject.find()) {
120                 associatedObject.delete();
121             }
122 
123             //Secondary cleaning, in case data was corrupted, remove
124             //all completion definitions that had this wizard id
125             //as a value.
126             CompletionDefinition completionDef = new CompletionDefinition();
127             completionDef.setField(CompletionDefinition.FLD_ID, wizardId);
128             completionDef.setConnection(dbConnection);
129             completionDef.deleteAll();
130 
131             CompletionDetails completionDetails = new CompletionDetails();
132             completionDetails.setConnection(dbConnection);
133             completionDetails.setField(CompletionDetails.FLD_WIZARD_ID, wizardId);
134             completionDetails.deleteAll();
135 
136             dbConnection.commit();
137 
138         } catch (DBRecordNotFoundException ex) {
139             try {
140                 dbConnection.rollback();
141             } catch (DBException e) {
142                 mLog.debug("problem rolling back: " + ex.getMessage());
143             }
144             throw new ObjectNotFoundException(
145                     "Cannot find wizard by id of: " + wizardId + " it may have already been deleted.", ex);
146         } catch (DBException ex) {
147             try {
148                 dbConnection.rollback();
149             } catch (DBException e) {
150                 mLog.debug("problem rolling back: " + ex.getMessage());
151             }
152             throw new RepositoryException("Error deleting wizard definition", ex);
153         } finally {
154             dbConnection.release();
155         }
156 
157     }
158 
159     public CompletionBean findById(final int wizardId) throws RepositoryException, ObjectNotFoundException,
160             RepositoryConversionException {
161         try {
162             WizDefinition wizDef = new WizDefinition();
163             wizDef.setField(WizDefinition.FLD_ID, wizardId);
164             wizDef.retrieve();
165             CompletionBean returnValue = completionConverter.convertToBean(wizDef);
166             assert returnValue != null;
167             return returnValue;
168         } catch (DBRecordNotFoundException ex) {
169             throw new ObjectNotFoundException("Cannot find wizard by id of: " + wizardId, ex);
170         } catch (DBException ex) {
171             throw new RepositoryException("Error loading wizard definition", ex);
172         }
173     }
174 
175     public CompletionBean findById(final Object previouslyGeneratedKey) throws RepositoryException,
176             ObjectNotFoundException,
177             RepositoryConversionException {
178 
179         if (previouslyGeneratedKey == null) {
180             throw new IllegalArgumentException("Previously Generated Key cannot be null");
181         }
182 
183         if (previouslyGeneratedKey instanceof Integer) {
184             return findById(((Integer) previouslyGeneratedKey).intValue());
185         } else {
186             int keyToUse = Integer.parseInt(previouslyGeneratedKey.toString());
187             return findById(keyToUse);
188         }
189     }
190 
191 
192     /***
193      * Updates the completion bean.
194      *
195      * @param newValue CompletionBean
196      * @throws RepositoryException     upon update erorr.
197      * @throws ObjectNotFoundException if the wizard id specified in newValue
198      *                                 doesn't exist in the underlying database object store.
199      */
200     public void update(final CompletionBean newValue) throws RepositoryException, ObjectNotFoundException {
201         assert newValue != null;
202 
203         DBConnection updateTransaction = null;
204         try {
205             updateTransaction = DBConnectionPool.getInstance(RequestRegistry.getDataContext()).getConnection(
206                     "Completion Wizard Update");
207             updateTransaction.setAutoCommit(false);
208 
209             boolean success = false;
210             //Check for object existance first.
211             WizDefinition oldDefinition = new WizDefinition();
212             oldDefinition.setConnection(updateTransaction);
213             oldDefinition.set(WizDefinition.FLD_ID, newValue.getWizardId());
214             oldDefinition.retrieve();
215 
216             while (!success) {
217                 try {
218                     WizDefinition wizDef = completionConverter.convertToDBObject(newValue);
219                     wizDef.setConnection(updateTransaction);
220                     assert wizDef != null;
221                     wizDef.update();
222                     success = true;
223                 } catch (IncompleteDetailsException incomplete) {
224 
225                     //Try to repair the system.
226                     CompletionDetails details = incomplete.getMissingDetail();
227 
228                     details.setField(CompletionDetails.FLD_COMPLETION, FieldCompletion.FIXED.toString());
229 
230                     CompletionDetails maxOrderQuery = new CompletionDetails();
231                     maxOrderQuery.setField(CompletionDetails.FLD_WIZARD_ID, newValue.getWizardId().intValue());
232                     int maxOrderNumber = (int) maxOrderQuery.max(CompletionDetails.FLD_PART_ORDER);
233 
234                     details.setField(CompletionDetails.FLD_PART_ORDER, maxOrderNumber + 1);
235 
236                     details.add();
237 
238                     /***
239                      * @todo Turn into an event of some sort.
240                      */
241                     mLog.warn("Found incomplete details: "
242                             + details.toString() + " have added it as 'fixed' part");
243 
244                     //Now loop and try again.
245                 }
246             }
247 
248 
249             updateTransaction.commit();
250         } catch (DBRecordNotFoundException ex) {
251             try {
252                 updateTransaction.rollback();
253             } catch (DBException e) {
254                 mLog.debug("problem rolling back: " + ex.getMessage());
255             }
256             throw new ObjectNotFoundException("Cannot find wizard by id of: " + newValue.getWizardId(), ex);
257         } catch (DBException ex) {
258             try {
259                 updateTransaction.rollback();
260             } catch (DBException e) {
261                 mLog.debug("problem rolling back: " + ex.getMessage());
262             }
263             throw new RepositoryException("Error adding wizard definition: " + newValue.toString(), ex);
264         } finally {
265             if (updateTransaction != null) {
266                 updateTransaction.release();
267             }
268         }
269 
270     }
271 }