KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > modeler > dialog > db > DbLoaderHelper


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56 package org.objectstyle.cayenne.modeler.dialog.db;
57
58 import java.sql.Connection JavaDoc;
59 import java.sql.SQLException JavaDoc;
60 import java.util.Arrays JavaDoc;
61 import java.util.Collection JavaDoc;
62 import java.util.List JavaDoc;
63
64 import javax.swing.JFrame JavaDoc;
65 import javax.swing.JOptionPane JavaDoc;
66 import javax.swing.SwingUtilities JavaDoc;
67
68 import org.apache.log4j.Logger;
69 import org.objectstyle.cayenne.CayenneException;
70 import org.objectstyle.cayenne.CayenneRuntimeException;
71 import org.objectstyle.cayenne.access.DbLoader;
72 import org.objectstyle.cayenne.access.DbLoaderDelegate;
73 import org.objectstyle.cayenne.dba.DbAdapter;
74 import org.objectstyle.cayenne.map.DataMap;
75 import org.objectstyle.cayenne.map.DbEntity;
76 import org.objectstyle.cayenne.map.ObjEntity;
77 import org.objectstyle.cayenne.map.event.DataMapEvent;
78 import org.objectstyle.cayenne.map.event.EntityEvent;
79 import org.objectstyle.cayenne.map.event.MapEvent;
80 import org.objectstyle.cayenne.modeler.Application;
81 import org.objectstyle.cayenne.modeler.ProjectController;
82 import org.objectstyle.cayenne.modeler.event.DataMapDisplayEvent;
83 import org.objectstyle.cayenne.modeler.util.LongRunningTask;
84 import org.objectstyle.cayenne.project.NamedObjectFactory;
85 import org.objectstyle.cayenne.util.Util;
86
87 /**
88  * Stateful helper class that encapsulates access to DbLoader.
89  *
90  * @author Andrei Adamchik
91  */

92 public class DbLoaderHelper {
93
94     private static final Logger logObj = Logger.getLogger(DbLoaderHelper.class);
95
96     // TODO: this is a temp hack... need to delegate to DbAdapter, or configurable in
97
// preferences...
98
private static final Collection JavaDoc EXCLUDED_TABLES = Arrays.asList(new Object JavaDoc[] {
99             "AUTO_PK_SUPPORT", "auto_pk_support"
100     });
101
102     static DbLoaderMergeDialog mergeDialog;
103
104     protected boolean overwritePreferenceSet;
105     protected boolean overwritingEntities;
106     protected boolean stoppingReverseEngineering;
107     protected boolean existingMap;
108
109     protected ProjectController mediator;
110     protected String JavaDoc dbUserName;
111     protected DbLoader loader;
112     protected DataMap dataMap;
113     protected String JavaDoc schemaName;
114     protected String JavaDoc tableNamePattern;
115     protected boolean loadProcedures;
116     protected String JavaDoc procedureNamePattern;
117     protected List JavaDoc schemas;
118
119     protected String JavaDoc loadStatusNote;
120
121     static synchronized DbLoaderMergeDialog getMergeDialogInstance() {
122         if (mergeDialog == null) {
123             mergeDialog = new DbLoaderMergeDialog(Application.getFrame());
124         }
125
126         return mergeDialog;
127     }
128
129     public DbLoaderHelper(ProjectController mediator, Connection JavaDoc connection,
130             DbAdapter adapter, String JavaDoc dbUserName) {
131         this.dbUserName = dbUserName;
132         this.mediator = mediator;
133         this.loader = new DbLoader(connection, adapter, new LoaderDelegate());
134     }
135
136     public void setOverwritingEntities(boolean overwritePreference) {
137         this.overwritingEntities = overwritePreference;
138     }
139
140     public void setOverwritePreferenceSet(boolean overwritePreferenceSet) {
141         this.overwritePreferenceSet = overwritePreferenceSet;
142     }
143
144     public void setStoppingReverseEngineering(boolean stopReverseEngineering) {
145         this.stoppingReverseEngineering = stopReverseEngineering;
146     }
147
148     public boolean isOverwritePreferenceSet() {
149         return overwritePreferenceSet;
150     }
151
152     public boolean isOverwritingEntities() {
153         return overwritingEntities;
154     }
155
156     public boolean isStoppingReverseEngineering() {
157         return stoppingReverseEngineering;
158     }
159
160     /**
161      * Performs reverse engineering of the DB using internal DbLoader. This method should
162      * be invoked outside EventDispatchThread, or it will throw an exception.
163      */

164     public void execute() {
165         stoppingReverseEngineering = false;
166
167         // load schemas...
168
LongRunningTask loadSchemasTask = new LoadSchemasTask(Application
169                 .getFrame(), "Loading Schemas");
170
171         loadSchemasTask.startAndWait();
172
173         if (stoppingReverseEngineering) {
174             return;
175         }
176
177         final DbLoaderOptionsDialog dialog = new DbLoaderOptionsDialog(
178                 schemas,
179                 dbUserName,
180                 false);
181
182         try {
183             // since we are not inside EventDisptahcer Thread, must run it via
184
// SwingUtilities
185
SwingUtilities.invokeAndWait(new Runnable JavaDoc() {
186
187                 public void run() {
188                     dialog.setVisible(true);
189                     dialog.dispose();
190                 }
191             });
192         }
193         catch (Throwable JavaDoc th) {
194             processException(th, "Error Reengineering Database");
195             return;
196         }
197
198         if (dialog.getChoice() == DbLoaderOptionsDialog.CANCEL) {
199             return;
200         }
201
202         this.schemaName = dialog.getSelectedSchema();
203         this.tableNamePattern = dialog.getTableNamePattern();
204         this.loadProcedures = dialog.isLoadingProcedures();
205         this.procedureNamePattern = dialog.getProcedureNamePattern();
206
207         // load DataMap...
208
LongRunningTask loadDataMapTask = new LoadDataMapTask(Application
209                 .getFrame(), "Reengineering DB");
210         loadDataMapTask.startAndWait();
211     }
212
213     protected void processException(final Throwable JavaDoc th, final String JavaDoc message) {
214         logObj.info("Exception on reverse engineering", Util.unwindException(th));
215         cleanup();
216         SwingUtilities.invokeLater(new Runnable JavaDoc() {
217
218             public void run() {
219                 JOptionPane.showMessageDialog(Application.getFrame(), th
220                         .getMessage(), message, JOptionPane.ERROR_MESSAGE);
221             }
222         });
223     }
224
225     protected void cleanup() {
226         loadStatusNote = "Closing connection...";
227         try {
228             if (loader.getCon() != null) {
229                 loader.getCon().close();
230             }
231         }
232         catch (SQLException JavaDoc e) {
233             logObj.warn("Error closing connection.", e);
234         }
235     }
236
237     final class LoaderDelegate implements DbLoaderDelegate {
238
239         public boolean overwriteDbEntity(DbEntity ent) throws CayenneException {
240             checkCanceled();
241
242             if (!overwritePreferenceSet) {
243                 DbLoaderMergeDialog dialog = DbLoaderHelper.getMergeDialogInstance();
244                 dialog.initFromModel(DbLoaderHelper.this, ent.getName());
245                 dialog.centerWindow();
246                 dialog.setVisible(true);
247                 dialog.setVisible(false);
248             }
249
250             if (stoppingReverseEngineering) {
251                 throw new CayenneException("Should stop DB import.");
252             }
253
254             return overwritingEntities;
255         }
256
257         public void dbEntityAdded(DbEntity entity) {
258             checkCanceled();
259
260             loadStatusNote = "Importing table '" + entity.getName() + "'...";
261
262             // TODO: hack to prevent PK tables from being visible... this should really be
263
// delegated to DbAdapter to decide...
264
if (EXCLUDED_TABLES.contains(entity.getName()) && entity.getDataMap() != null) {
265                 entity.getDataMap().removeDbEntity(entity.getName());
266             }
267             else if (existingMap) {
268                 mediator
269                         .fireDbEntityEvent(new EntityEvent(this, entity, EntityEvent.ADD));
270             }
271         }
272
273         public void objEntityAdded(ObjEntity entity) {
274             checkCanceled();
275
276             loadStatusNote = "Creating ObjEntity '" + entity.getName() + "'...";
277
278             if (existingMap) {
279                 mediator
280                         .fireObjEntityEvent(new EntityEvent(this, entity, EntityEvent.ADD));
281             }
282         }
283
284         public void dbEntityRemoved(DbEntity entity) {
285             checkCanceled();
286
287             if (existingMap) {
288                 mediator.fireDbEntityEvent(new EntityEvent(
289                         Application.getFrame(),
290                         entity,
291                         EntityEvent.REMOVE));
292             }
293         }
294
295         public void objEntityRemoved(ObjEntity entity) {
296             checkCanceled();
297
298             if (existingMap) {
299                 mediator.fireObjEntityEvent(new EntityEvent(Application
300                         .getFrame(), entity, EntityEvent.REMOVE));
301             }
302         }
303
304         void checkCanceled() {
305             if (isStoppingReverseEngineering()) {
306                 throw new CayenneRuntimeException("Reengineering was canceled.");
307             }
308         }
309     }
310
311     abstract class DbLoaderTask extends LongRunningTask {
312
313         public DbLoaderTask(JFrame JavaDoc frame, String JavaDoc title) {
314             super(frame, title);
315             setMinValue(0);
316             setMaxValue(10);
317         }
318
319         protected String JavaDoc getCurrentNote() {
320             return loadStatusNote;
321         }
322
323         protected int getCurrentValue() {
324             return getMinValue();
325         }
326
327         protected boolean isIndeterminate() {
328             return true;
329         }
330
331         public boolean isCanceled() {
332             return isStoppingReverseEngineering();
333         }
334
335         public void setCanceled(boolean b) {
336             if (b) {
337                 loadStatusNote = "Canceling..";
338             }
339
340             setStoppingReverseEngineering(b);
341         }
342     }
343
344     final class LoadSchemasTask extends DbLoaderTask {
345
346         public LoadSchemasTask(JFrame JavaDoc frame, String JavaDoc title) {
347             super(frame, title);
348         }
349
350         protected void execute() {
351             loadStatusNote = "Loading available schemas...";
352
353             try {
354                 schemas = loader.getSchemas();
355             }
356             catch (Throwable JavaDoc th) {
357                 processException(th, "Error Loading Schemas");
358             }
359         }
360     }
361
362     final class LoadDataMapTask extends DbLoaderTask {
363
364         public LoadDataMapTask(JFrame JavaDoc frame, String JavaDoc title) {
365             super(frame, title);
366         }
367
368         protected void execute() {
369
370             loadStatusNote = "Preparing...";
371
372             DbLoaderHelper.this.dataMap = mediator.getCurrentDataMap();
373             DbLoaderHelper.this.existingMap = dataMap != null;
374
375             if (!existingMap) {
376                 dataMap = (DataMap) NamedObjectFactory.createObject(DataMap.class, null);
377                 dataMap.setName(NamedObjectFactory.createName(DataMap.class, mediator
378                         .getCurrentDataDomain()));
379                 dataMap.setDefaultSchema(schemaName);
380             }
381
382             if (isCanceled()) {
383                 return;
384             }
385
386             loadStatusNote = "Importing tables...";
387
388             try {
389                 loader.loadDataMapFromDB(schemaName, tableNamePattern, dataMap);
390             }
391             catch (Throwable JavaDoc th) {
392                 if (!isCanceled()) {
393                     processException(th, "Error Reengineering Database");
394                 }
395             }
396
397             if (loadProcedures) {
398                 loadStatusNote = "Importing procedures...";
399                 try {
400                     loader
401                             .loadProceduresFromDB(
402                                     schemaName,
403                                     procedureNamePattern,
404                                     dataMap);
405                 }
406                 catch (Throwable JavaDoc th) {
407                     if (!isCanceled()) {
408                         processException(th, "Error Reengineering Database");
409                     }
410                 }
411             }
412
413             cleanup();
414
415             // fire up events
416
loadStatusNote = "Updating view...";
417             if (mediator.getCurrentDataMap() != null) {
418                 mediator.fireDataMapEvent(new DataMapEvent(
419                         Application.getFrame(),
420                         dataMap,
421                         MapEvent.CHANGE));
422                 mediator.fireDataMapDisplayEvent(new DataMapDisplayEvent(
423                         Application.getFrame(),
424                         dataMap,
425                         mediator.getCurrentDataDomain(),
426                         mediator.getCurrentDataNode()));
427             }
428             else {
429                 mediator.addDataMap(Application.getFrame(), dataMap);
430             }
431         }
432     }
433 }
Popular Tags