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.creation.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.creation.CreationRepository;
24  import com.sri.emo.wizard.creation.model.CreationBeans;
25  import com.sri.emo.wizard.creation.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 ExpressoTemplateRepository implements CreationRepository {
36  
37      /***
38       * The bean to dbobject converter bridge.
39       */
40      private final CreationDBObjConverter completionConverter;
41  
42      private Logger mLog = Logger.getLogger(ExpressoTemplateRepository.class);
43  
44      /***
45       * Completion Repository constructor that takes a converter.
46       *
47       * @param converter CompletionDBObjConverter
48       */
49      public ExpressoTemplateRepository(final CreationDBObjConverter 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 CreationBeans 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) {
120                 if (associatedObject.find()) {
121                     associatedObject.delete();
122                 }
123             }
124 
125             //Secondary cleaning, in case data was corrupted, remove
126             //all completion definitions that had this wizard id
127             //as a value.
128             CreationDefinition completionDef = new CreationDefinition();
129             completionDef.setField(CreationDefinition.FLD_ID, wizardId);
130             completionDef.setConnection(dbConnection);
131             completionDef.deleteAll();
132 
133             CreationDetails completionDetails = new CreationDetails();
134             completionDetails.setConnection(dbConnection);
135             completionDetails.setField(CreationDetails.FLD_WIZARD_ID, wizardId);
136             completionDetails.deleteAll();
137 
138             dbConnection.commit();
139 
140         } catch (DBRecordNotFoundException ex) {
141             try {
142                 dbConnection.rollback();
143             } catch (DBException e) {
144                 mLog.debug("problem rolling back: " + ex.getMessage());
145             }
146             throw new ObjectNotFoundException(
147                     "Cannot find wizard by id of: " + wizardId + " it may have already been deleted.", ex);
148         } catch (DBException ex) {
149             try {
150                 dbConnection.rollback();
151             } catch (DBException e) {
152                 mLog.debug("problem rolling back: " + ex.getMessage());
153             }
154             throw new RepositoryException("Error deleting wizard definition", ex);
155         } finally {
156             dbConnection.release();
157         }
158 
159     }
160 
161     public CreationBeans findById(final int wizardId) throws RepositoryException, ObjectNotFoundException,
162             RepositoryConversionException {
163         try {
164             WizDefinition wizDef = new WizDefinition();
165             wizDef.setField(WizDefinition.FLD_ID, wizardId);
166             wizDef.retrieve();
167             CreationBeans returnValue = completionConverter.convertToBean(wizDef);
168             assert returnValue != null;
169             return returnValue;
170         } catch (DBRecordNotFoundException ex) {
171             throw new ObjectNotFoundException("Cannot find wizard by id of: " + wizardId, ex);
172         } catch (DBException ex) {
173             throw new RepositoryException("Error loading wizard definition", ex);
174         }
175     }
176 
177     public CreationBeans findById(final Object previouslyGeneratedKey) throws RepositoryException,
178             ObjectNotFoundException,
179             RepositoryConversionException {
180 
181         if (previouslyGeneratedKey == null) {
182             throw new IllegalArgumentException("Previously Generated Key cannot be null");
183         }
184 
185         if (previouslyGeneratedKey instanceof Integer) {
186             return findById(((Integer) previouslyGeneratedKey).intValue());
187         } else {
188             int keyToUse = Integer.parseInt(previouslyGeneratedKey.toString());
189             return findById(keyToUse);
190         }
191     }
192 
193 
194     /***
195      * Updates the completion bean.
196      *
197      * @param newValue CompletionBean
198      * @throws RepositoryException     upon update erorr.
199      * @throws ObjectNotFoundException if the wizard id specified in newValue
200      *                                 doesn't exist in the underlying database object store.
201      */
202     public void update(final CreationBeans newValue) throws RepositoryException, ObjectNotFoundException {
203         assert newValue != null;
204 
205         DBConnection updateTransaction = null;
206         try {
207             updateTransaction = DBConnectionPool.getInstance(RequestRegistry.getDataContext()).getConnection(
208                     "Creation Wizard Update");
209             updateTransaction.setAutoCommit(false);
210 
211             boolean success = false;
212             //Check for object existance first.
213             WizDefinition oldDefinition = new WizDefinition();
214             oldDefinition.setConnection(updateTransaction);
215             oldDefinition.set(WizDefinition.FLD_ID, newValue.getWizardId());
216             oldDefinition.retrieve();
217 
218             while (!success) {
219                 try {
220                     WizDefinition wizDef = completionConverter.convertToDBObject(newValue);
221                     wizDef.setConnection(updateTransaction);
222                     assert wizDef != null;
223                     wizDef.update();
224                     success = true;
225                 } catch (IncompleteDetailsException incomplete) {
226 
227                     //Try to repair the system.
228                     CreationDetails details = incomplete.getMissingDetail();
229 
230                     details.setField(CreationDetails.FLD_COMPLETION, FieldCompletion.NOT_INCLUDED.toString());
231 
232                     CreationDetails maxOrderQuery = new CreationDetails();
233                     maxOrderQuery.setField(CreationDetails.FLD_WIZARD_ID, newValue.getWizardId().intValue());
234                     int maxOrderNumber = (int) maxOrderQuery.max(CreationDetails.FLD_PART_ORDER);
235 
236                     details.setField(CreationDetails.FLD_PART_ORDER, maxOrderNumber + 1);
237 
238                     details.add();
239 
240                     /***
241                      * @todo Turn into an event of some sort.
242                      */
243                     mLog.warn("Found incomplete details: "
244                             + details.toString() + " have added it as 'fixed' part");
245 
246                     //Now loop and try again.
247                 }
248             }
249 
250 
251             updateTransaction.commit();
252         } catch (DBRecordNotFoundException ex) {
253             try {
254                 updateTransaction.rollback();
255             } catch (DBException e) {
256                 mLog.debug("problem rolling back: " + ex.getMessage());
257             }
258             throw new ObjectNotFoundException("Cannot find wizard by id of: " + newValue.getWizardId(), ex);
259         } catch (DBException ex) {
260             try {
261                 updateTransaction.rollback();
262             } catch (DBException e) {
263                 mLog.debug("problem rolling back: " + ex.getMessage());
264             }
265             throw new RepositoryException("Error adding wizard definition: " + newValue.toString(), ex);
266         } finally {
267             if (updateTransaction != null) {
268                 updateTransaction.release();
269             }
270         }
271 
272     }
273 }