KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > modeler > dialog > ResolveDbRelationshipDialog


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;
57
58 import java.awt.BorderLayout JavaDoc;
59 import java.awt.Dimension JavaDoc;
60 import java.awt.event.ActionEvent JavaDoc;
61 import java.awt.event.ActionListener JavaDoc;
62 import java.util.ArrayList JavaDoc;
63 import java.util.Collection JavaDoc;
64 import java.util.Collections JavaDoc;
65 import java.util.Iterator JavaDoc;
66 import java.util.List JavaDoc;
67
68 import javax.swing.DefaultCellEditor JavaDoc;
69 import javax.swing.JButton JavaDoc;
70 import javax.swing.JComboBox JavaDoc;
71 import javax.swing.JOptionPane JavaDoc;
72 import javax.swing.JScrollPane JavaDoc;
73 import javax.swing.JTextField JavaDoc;
74 import javax.swing.ListSelectionModel JavaDoc;
75 import javax.swing.table.TableColumn JavaDoc;
76
77 import org.objectstyle.cayenne.CayenneRuntimeException;
78 import org.objectstyle.cayenne.map.DbEntity;
79 import org.objectstyle.cayenne.map.DbJoin;
80 import org.objectstyle.cayenne.map.DbRelationship;
81 import org.objectstyle.cayenne.map.Entity;
82 import org.objectstyle.cayenne.map.Relationship;
83 import org.objectstyle.cayenne.map.event.RelationshipEvent;
84 import org.objectstyle.cayenne.modeler.Application;
85 import org.objectstyle.cayenne.modeler.util.CayenneDialog;
86 import org.objectstyle.cayenne.modeler.util.CayenneTable;
87 import org.objectstyle.cayenne.modeler.util.CayenneWidgetFactory;
88 import org.objectstyle.cayenne.modeler.util.ModelerUtil;
89 import org.objectstyle.cayenne.modeler.util.PanelFactory;
90 import org.objectstyle.cayenne.modeler.util.ProjectUtil;
91 import org.objectstyle.cayenne.project.NamedObjectFactory;
92 import org.objectstyle.cayenne.util.Util;
93
94 import com.jgoodies.forms.builder.PanelBuilder;
95 import com.jgoodies.forms.layout.CellConstraints;
96 import com.jgoodies.forms.layout.FormLayout;
97
98 /**
99  * Editor of DbRelationship joins.
100  */

101 public class ResolveDbRelationshipDialog extends CayenneDialog {
102
103     protected DbRelationship relationship;
104     protected DbRelationship reverseRelationship;
105
106     protected JTextField JavaDoc name;
107     protected JTextField JavaDoc reverseName;
108     protected CayenneTable table;
109     protected JButton JavaDoc addButton;
110     protected JButton JavaDoc removeButton;
111     protected JButton JavaDoc saveButton;
112     protected JButton JavaDoc cancelButton;
113
114     private boolean cancelPressed;
115
116     public ResolveDbRelationshipDialog(DbRelationship relationship) {
117
118         super(Application.getFrame(), "", true);
119
120         initView();
121         initController();
122         initWithModel(relationship);
123
124         this.pack();
125         this.centerWindow();
126     }
127
128     /**
129      * Creates graphical components.
130      */

131     private void initView() {
132
133         // create widgets
134
name = new JTextField JavaDoc(25);
135         reverseName = new JTextField JavaDoc(25);
136         addButton = new JButton JavaDoc("Add");
137         removeButton = new JButton JavaDoc("Remove");
138         saveButton = new JButton JavaDoc("Done");
139         cancelButton = new JButton JavaDoc("Cancel");
140
141         table = new AttributeTable();
142         table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
143
144         // assemble
145
getContentPane().setLayout(new BorderLayout JavaDoc());
146
147         CellConstraints cc = new CellConstraints();
148         PanelBuilder builder = new PanelBuilder(
149                 new FormLayout(
150                         "right:max(50dlu;pref), 3dlu, fill:min(150dlu;pref), 3dlu, fill:min(150dlu;pref)",
151                         "p, 3dlu, p, 3dlu, p, 9dlu, p, 3dlu, top:14dlu, 3dlu, top:p:grow"));
152         builder.setDefaultDialogBorder();
153
154         builder.addSeparator("DbRelationship Information", cc.xywh(1, 1, 5, 1));
155         builder.addLabel("Relationship:", cc.xy(1, 3));
156         builder.add(name, cc.xywh(3, 3, 1, 1));
157         builder.addLabel("Reverse Relationship", cc.xy(1, 5));
158         builder.add(reverseName, cc.xywh(3, 5, 1, 1));
159
160         builder.addSeparator("Joins", cc.xywh(1, 7, 5, 1));
161         builder.add(new JScrollPane JavaDoc(table), cc.xywh(1, 9, 3, 3, "fill, fill"));
162         builder.add(addButton, cc.xywh(5, 9, 1, 1));
163         builder.add(removeButton, cc.xywh(5, 11, 1, 1));
164
165         getContentPane().add(builder.getPanel(), BorderLayout.CENTER);
166         getContentPane().add(PanelFactory.createButtonPanel(new JButton JavaDoc[] {
167                 saveButton, cancelButton
168         }), BorderLayout.SOUTH);
169     }
170
171     private void initWithModel(DbRelationship relationship) {
172
173         // sanity check
174
if (relationship.getSourceEntity() == null) {
175             throw new CayenneRuntimeException("Null source entity: " + relationship);
176         }
177
178         if (relationship.getTargetEntity() == null) {
179             throw new CayenneRuntimeException("Null target entity: " + relationship);
180         }
181
182         if (relationship.getSourceEntity().getDataMap() == null) {
183             throw new CayenneRuntimeException("Null DataMap: "
184                     + relationship.getSourceEntity());
185         }
186
187         this.relationship = relationship;
188         this.reverseRelationship = relationship.getReverseRelationship();
189
190         // init UI components
191
setTitle("DbRelationship Info: "
192                 + relationship.getSourceEntity().getName()
193                 + " to "
194                 + relationship.getTargetEntityName());
195
196         table.setModel(new DbJoinTableModel(relationship, getMediator(), this, true));
197         TableColumn JavaDoc sourceColumn = table.getColumnModel().getColumn(
198                 DbJoinTableModel.SOURCE);
199         sourceColumn.setMinWidth(150);
200         JComboBox JavaDoc comboBox = CayenneWidgetFactory.createComboBox(ModelerUtil
201                 .getDbAttributeNames(getMediator(), (DbEntity) relationship
202                         .getSourceEntity()), true);
203         comboBox.setEditable(false);
204         sourceColumn.setCellEditor(new DefaultCellEditor JavaDoc(comboBox));
205
206         TableColumn JavaDoc targetColumn = table.getColumnModel().getColumn(
207                 DbJoinTableModel.TARGET);
208         targetColumn.setMinWidth(150);
209         comboBox = CayenneWidgetFactory.createComboBox(ModelerUtil.getDbAttributeNames(
210                 getMediator(),
211                 (DbEntity) relationship.getTargetEntity()), true);
212         comboBox.setEditable(false);
213         targetColumn.setCellEditor(new DefaultCellEditor JavaDoc(comboBox));
214
215         if (reverseRelationship != null) {
216             reverseName.setText(reverseRelationship.getName());
217         }
218
219         name.setText(relationship.getName());
220     }
221
222     private void initController() {
223         addButton.addActionListener(new ActionListener JavaDoc() {
224
225             public void actionPerformed(ActionEvent JavaDoc e) {
226                 DbJoinTableModel model = (DbJoinTableModel) table.getModel();
227                 model.addRow(new DbJoin(relationship));
228                 table.select(model.getRowCount() - 1);
229             }
230         });
231
232         removeButton.addActionListener(new ActionListener JavaDoc() {
233
234             public void actionPerformed(ActionEvent JavaDoc e) {
235                 DbJoinTableModel model = (DbJoinTableModel) table.getModel();
236                 stopEditing();
237                 int row = table.getSelectedRow();
238                 model.removeRow(model.getJoin(row));
239             }
240         });
241
242         saveButton.addActionListener(new ActionListener JavaDoc() {
243
244             public void actionPerformed(ActionEvent JavaDoc e) {
245                 cancelPressed = false;
246                 save();
247             }
248         });
249
250         cancelButton.addActionListener(new ActionListener JavaDoc() {
251
252             public void actionPerformed(ActionEvent JavaDoc e) {
253                 cancelPressed = true;
254                 setVisible(false);
255             }
256         });
257     }
258
259     public boolean isCancelPressed() {
260         return cancelPressed;
261     }
262
263     private void stopEditing() {
264         // Stop whatever editing may be taking place
265
int col_index = table.getEditingColumn();
266         if (col_index >= 0) {
267             TableColumn JavaDoc col = table.getColumnModel().getColumn(col_index);
268             col.getCellEditor().stopCellEditing();
269         }
270     }
271
272     private void save() {
273
274         // extract names...
275
String JavaDoc name = this.name.getText();
276         if (name.length() == 0) {
277             name = null;
278         }
279
280         if (name == null) {
281             name = NamedObjectFactory.createName(DbRelationship.class, relationship
282                     .getSourceEntity());
283         }
284
285         if (!validateName(relationship.getSourceEntity(), relationship, name)) {
286             return;
287         }
288
289         String JavaDoc reverseName = this.reverseName.getText().trim();
290         if (reverseName.length() == 0) {
291             reverseName = null;
292         }
293
294         if (reverseName == null) {
295             reverseName = NamedObjectFactory.createName(
296                     DbRelationship.class,
297                     relationship.getTargetEntity());
298         }
299
300         // check if reverse name is valid
301
DbJoinTableModel model = (DbJoinTableModel) table.getModel();
302         boolean updatingReverse = model.getObjectList().size() > 0;
303
304         if (updatingReverse
305                 && !validateName(
306                         relationship.getTargetEntity(),
307                         reverseRelationship,
308                         reverseName)) {
309             return;
310         }
311
312         // handle name update
313
if (!Util.nullSafeEquals(name, relationship.getName())) {
314             String JavaDoc oldName = relationship.getName();
315             ProjectUtil.setRelationshipName(
316                     relationship.getSourceEntity(),
317                     relationship,
318                     name);
319
320             getMediator().fireDbRelationshipEvent(
321                     new RelationshipEvent(this, relationship, relationship
322                             .getSourceEntity(), oldName));
323         }
324
325         model.commit();
326
327         // check "to dep pk" setting,
328
// maybe this is no longer valid
329
if (relationship.isToDependentPK() && !relationship.isValidForDepPk()) {
330             relationship.setToDependentPK(false);
331         }
332
333         // If new reverse DbRelationship was created, add it to the target
334
// Don't create reverse with no joins - makes no sense...
335
if (updatingReverse) {
336
337             // If didn't find anything, create reverseDbRel
338
if (reverseRelationship == null) {
339                 reverseRelationship = new DbRelationship(reverseName);
340                 reverseRelationship.setSourceEntity(relationship.getTargetEntity());
341                 reverseRelationship.setTargetEntity(relationship.getSourceEntity());
342                 reverseRelationship.setToMany(!relationship.isToMany());
343                 relationship.getTargetEntity().addRelationship(reverseRelationship);
344
345                 // fire only if the relationship is to the same entity...
346
// this is needed to update entity view...
347
if (relationship.getSourceEntity() == relationship.getTargetEntity()) {
348                     getMediator().fireDbRelationshipEvent(
349                             new RelationshipEvent(
350                                     this,
351                                     reverseRelationship,
352                                     reverseRelationship.getSourceEntity(),
353                                     RelationshipEvent.ADD));
354                 }
355             }
356             else if (!Util.nullSafeEquals(reverseName, reverseRelationship.getName())) {
357                 String JavaDoc oldName = reverseRelationship.getName();
358                 ProjectUtil.setRelationshipName(
359                         reverseRelationship.getSourceEntity(),
360                         reverseRelationship,
361                         reverseName);
362
363                 getMediator().fireDbRelationshipEvent(
364                         new RelationshipEvent(
365                                 this,
366                                 reverseRelationship,
367                                 reverseRelationship.getSourceEntity(),
368                                 oldName));
369             }
370
371             Collection JavaDoc reverseJoins = getReverseJoins();
372             reverseRelationship.setJoins(reverseJoins);
373
374             // check if joins map to a primary key of this entity
375
if (!relationship.isToDependentPK()) {
376                 Iterator JavaDoc it = reverseJoins.iterator();
377                 if (it.hasNext()) {
378                     boolean toDepPK = true;
379                     while (it.hasNext()) {
380                         DbJoin join = (DbJoin) it.next();
381                         if (!join.getTarget().isPrimaryKey()) {
382                             toDepPK = false;
383                             break;
384                         }
385                     }
386
387                     reverseRelationship.setToDependentPK(toDepPK);
388                 }
389             }
390
391         }
392
393         getMediator()
394                 .fireDbRelationshipEvent(
395                         new RelationshipEvent(this, relationship, relationship
396                                 .getSourceEntity()));
397         dispose();
398     }
399
400     private boolean validateName(Entity entity, Relationship relationship, String JavaDoc newName) {
401
402         Relationship existing = entity.getRelationship(newName);
403         if (existing != null && (relationship == null || relationship != existing)) {
404             JOptionPane.showMessageDialog(
405                     this,
406                     "There is an existing relationship named \""
407                             + newName
408                             + "\". Select a different name.");
409             return false;
410         }
411
412         return true;
413     }
414
415     private Collection JavaDoc getReverseJoins() {
416         Collection JavaDoc joins = relationship.getJoins();
417
418         if ((joins == null) || (joins.size() == 0)) {
419             return Collections.EMPTY_LIST;
420         }
421
422         List JavaDoc reverseJoins = new ArrayList JavaDoc(joins.size());
423
424         // Loop through the list of attribute pairs, create reverse pairs
425
// and put them to the reverse list.
426
Iterator JavaDoc it = joins.iterator();
427         while (it.hasNext()) {
428             DbJoin pair = (DbJoin) it.next();
429             DbJoin reverseJoin = pair.createReverseJoin();
430
431             // since reverse relationship is not yet initialized,
432
// reverse join will not have it set automatically
433
reverseJoin.setRelationship(reverseRelationship);
434             reverseJoins.add(reverseJoin);
435         }
436
437         return reverseJoins;
438     }
439
440     final class AttributeTable extends CayenneTable {
441
442         final Dimension JavaDoc preferredSize = new Dimension JavaDoc(203, 100);
443
444         public Dimension JavaDoc getPreferredScrollableViewportSize() {
445             return preferredSize;
446         }
447     }
448 }
Popular Tags