Source code: org/objectstyle/cayenne/modeler/datamap/ChooseDbRelationshipDialog.java
1 /* ====================================================================
2 *
3 * The ObjectStyle Group Software License, Version 1.0
4 *
5 * Copyright (c) 2002-2003 The ObjectStyle Group
6 * and individual authors of the software. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. The end-user documentation included with the redistribution, if
21 * any, must include the following acknowlegement:
22 * "This product includes software developed by the
23 * ObjectStyle Group (http://objectstyle.org/)."
24 * Alternately, this acknowlegement may appear in the software itself,
25 * if and wherever such third-party acknowlegements normally appear.
26 *
27 * 4. The names "ObjectStyle Group" and "Cayenne"
28 * must not be used to endorse or promote products derived
29 * from this software without prior written permission. For written
30 * permission, please contact andrus@objectstyle.org.
31 *
32 * 5. Products derived from this software may not be called "ObjectStyle"
33 * nor may "ObjectStyle" appear in their names without prior written
34 * permission of the ObjectStyle Group.
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This software consists of voluntary contributions made by many
51 * individuals on behalf of the ObjectStyle Group. For more
52 * information on the ObjectStyle Group, please see
53 * <http://objectstyle.org/>.
54 *
55 */
56 package org.objectstyle.cayenne.modeler.datamap;
57
58 import java.awt.BorderLayout;
59 import java.awt.Color;
60 import java.awt.Component;
61 import java.awt.event.ActionEvent;
62 import java.awt.event.ActionListener;
63 import java.util.ArrayList;
64 import java.util.HashSet;
65 import java.util.Iterator;
66 import java.util.List;
67 import java.util.Set;
68
69 import javax.swing.DefaultComboBoxModel;
70 import javax.swing.JButton;
71 import javax.swing.JComboBox;
72 import javax.swing.JLabel;
73 import javax.swing.JOptionPane;
74 import javax.swing.JPanel;
75
76 import org.objectstyle.cayenne.map.DataMap;
77 import org.objectstyle.cayenne.map.DbEntity;
78 import org.objectstyle.cayenne.map.DbRelationship;
79 import org.objectstyle.cayenne.map.Relationship;
80 import org.objectstyle.cayenne.modeler.CayenneDialog;
81 import org.objectstyle.cayenne.modeler.Editor;
82 import org.objectstyle.cayenne.modeler.PanelFactory;
83 import org.objectstyle.cayenne.modeler.util.CayenneWidgetFactory;
84 import org.objectstyle.cayenne.modeler.util.RelationshipWrapper;
85
86 /**
87 * Used to select the DbRelationship for ObjRelationship mapping.
88 * Allows selecting the relationship, canceling, edit the relationship and
89 * create new relationship. It is needed for the
90 * cases when there is more than one DbRelationship between start and
91 * end entities, like in the case when the DbRelationship starts and
92 * ends in the same DbEntity.
93 *
94 * <p>The choice is returned in getChoice() method. If choice is SELECT or EDIT,
95 * the selected DbRelationship may be retrieved by getDbRelationship(),
96 * which will return the list with one DbRelationship. List is used for the
97 * future expansion, when one ObjRelaitonship will be mapped for
98 * multiple DbRelaitonship's.</p>
99 *
100 * <p>Existing mapping for this ObjRelationship is pre-selected in the combo box.
101 * Combo box contains the DbRelaitonship-s between the start and end DbEntity's</p>
102 *
103 * @author Misha Shengaout
104 * @author Andrei Adamchik
105 */
106 public class ChooseDbRelationshipDialog extends CayenneDialog implements ActionListener {
107 public static final int SELECT = 0;
108 public static final int CANCEL = 1;
109 public static final int NEW = 2;
110 public static final int EDIT = 3;
111
112 private DataMap map;
113 private DbEntity start;
114 private DbEntity end;
115 private List dbRels;
116 private List relList = new ArrayList();
117
118 JComboBox relSelect = CayenneWidgetFactory.createComboBox();
119 JButton select = new JButton("Select");
120 JButton cancel = new JButton("Cancel");
121 JButton create = new JButton("New");
122 JButton edit = new JButton("Edit");
123 private int choice = CANCEL;
124
125 //Looks for a direct relationship from start to end.
126 //Then looks at the destination of each direct relationship from start, and follows any
127 //direct relationships from *that* entity (using recursion). seenEntities is always updated
128 // to ensure that loops do not occur
129 private List findRelationshipPath(
130 DbEntity start,
131 DbEntity end,
132 Set seenEntities,
133 String indent) {
134 // Find matching relationship in the start DbEntity
135 List result = new ArrayList();
136 //Ensure we never come "back" to this entity
137 seenEntities.add(start);
138
139 Iterator iter = start.getRelationships().iterator();
140 while (iter.hasNext()) {
141 DbRelationship db_rel = (DbRelationship) iter.next();
142 if (db_rel.getTargetEntity() == end) {
143 List aList = new ArrayList();
144 aList.add(db_rel);
145 result.add(aList);
146 }
147 else {
148 //Not a direct relationship... recurse, but don't come back to this entity
149 if (!seenEntities.contains(db_rel.getTargetEntity())) {
150 List deeperRels =
151 this.findRelationshipPath(
152 (DbEntity) db_rel.getTargetEntity(),
153 end,
154 seenEntities,
155 indent + " ");
156
157 //deeperRels will be a list of relationship paths that make it from the targetEntity to the end
158 //Create a *new* list with the current relationship at the head of each of these lists
159 Iterator deeperIt = deeperRels.iterator();
160 while (deeperIt.hasNext()) {
161 List deeperRelList = (List) deeperIt.next();
162 List aList = new ArrayList();
163 aList.add(db_rel); //Start of with db_rel...
164 aList.addAll(deeperRelList); //..add the rest..
165 result.add(aList); // ... and pop it into the result
166 }
167 }
168 }
169 }
170 return result;
171 }
172
173 private void populateRelationshipList(DbEntity startEntity, DbEntity endEntity) {
174 relList.addAll(
175 this.findRelationshipPath(startEntity, endEntity, new HashSet(), ""));
176 }
177
178 public ChooseDbRelationshipDialog(
179 DataMap temp_map,
180 java.util.List db_rel_list,
181 DbEntity temp_start,
182 DbEntity temp_end,
183 boolean to_many) {
184 super(Editor.getFrame(), "Select DbRelationship", true);
185 map = temp_map;
186 start = temp_start;
187 end = temp_end;
188
189 this.populateRelationshipList(temp_start, temp_end);
190
191 // If DbRelationship does not exist, create it.
192 if (null != db_rel_list && db_rel_list.size() > 0) {
193 dbRels = new ArrayList(db_rel_list); //Copy
194 }
195
196 init();
197
198 this.pack();
199 this.centerWindow();
200
201 select.addActionListener(this);
202 cancel.addActionListener(this);
203 create.addActionListener(this);
204 edit.addActionListener(this);
205 }
206
207 private boolean relListsSame(List relList1, List relList2) {
208 if (relList1.size() != relList2.size()) {
209 return false;
210 }
211 int i;
212 for (i = 0; i < relList1.size(); i++) {
213 if (!relList1.get(i).equals(relList2.get(i))) {
214 return false;
215 }
216 }
217 return true;
218 }
219
220 /** Sets up the graphical components. */
221 private void init() {
222 getContentPane().setLayout(new BorderLayout());
223
224 relSelect.setBackground(Color.WHITE);
225
226 DefaultComboBoxModel model = new DefaultComboBoxModel();
227 RelationshipWrapper sel_item = new RelationshipWrapper((Relationship) null);
228 model.addElement(sel_item);
229 Iterator iter = relList.iterator();
230 while (iter.hasNext()) {
231 List db_rels = (List) iter.next();
232 RelationshipWrapper wrap = new RelationshipWrapper(db_rels);
233 model.addElement(wrap);
234 if (dbRels != null && relListsSame(db_rels, dbRels)) {
235 sel_item = wrap;
236 }
237 }
238 model.setSelectedItem(sel_item);
239 relSelect.setModel(model);
240
241 JPanel buttons =
242 PanelFactory.createButtonPanel(
243 new JButton[] { select, cancel, create, edit });
244
245 Component[] left =
246 new Component[] {
247 CayenneWidgetFactory.createLabel("Relationships: "),
248 new JLabel()};
249
250 Component[] right = new Component[] { relSelect, buttons };
251
252 JPanel panel = PanelFactory.createForm(left, right, 5, 5, 5, 5);
253 getContentPane().add(panel, BorderLayout.CENTER);
254 }
255
256 public List getDbRelationshipList() {
257 if (getChoice() != SELECT && getChoice() != EDIT)
258 return null;
259 List list = new ArrayList();
260 if (dbRels != null)
261 list.addAll(dbRels);
262 return list;
263 }
264
265 public int getChoice() {
266 return choice;
267 }
268
269 public void actionPerformed(ActionEvent e) {
270 Object src = e.getSource();
271 if (src == this.select) {
272 processSelect();
273 }
274 else if (src == this.cancel) {
275 processCancel();
276 }
277 else if (src == this.edit) {
278 processEdit();
279 }
280 else if (src == this.create) {
281 processNew();
282 }
283 }
284
285 private void processSelect() {
286 RelationshipWrapper wrap;
287 wrap = (RelationshipWrapper) relSelect.getSelectedItem();
288 if (null != wrap && wrap.getRelationshipList() != null)
289 dbRels = wrap.getRelationshipList();
290 else
291 dbRels = null;
292
293 choice = SELECT;
294 hide();
295 }
296
297 private void processEdit() {
298 RelationshipWrapper wrap;
299 wrap = (RelationshipWrapper) relSelect.getSelectedItem();
300 if (null == wrap || wrap.getRelationshipList() == null) {
301 JOptionPane.showMessageDialog(Editor.getFrame(), "Select the relationship");
302 return;
303 }
304 dbRels = wrap.getRelationshipList();
305 choice = EDIT;
306 hide();
307 }
308
309 private void processCancel() {
310 dbRels = null;
311 choice = CANCEL;
312 hide();
313 }
314
315 private void processNew() {
316 dbRels = null;
317 choice = NEW;
318 hide();
319 }
320
321 }