KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > modeler > editor > ObjEntityTab


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
57 package org.objectstyle.cayenne.modeler.editor;
58
59 import java.awt.BorderLayout JavaDoc;
60 import java.awt.Color JavaDoc;
61 import java.awt.event.ActionEvent JavaDoc;
62 import java.awt.event.ActionListener JavaDoc;
63 import java.util.Arrays JavaDoc;
64 import java.util.EventObject JavaDoc;
65
66 import javax.swing.DefaultComboBoxModel JavaDoc;
67 import javax.swing.JButton JavaDoc;
68 import javax.swing.JCheckBox JavaDoc;
69 import javax.swing.JComboBox JavaDoc;
70 import javax.swing.JOptionPane JavaDoc;
71 import javax.swing.JPanel JavaDoc;
72 import javax.swing.JTextField JavaDoc;
73 import javax.swing.JToolBar JavaDoc;
74
75 import org.apache.commons.collections.CollectionUtils;
76 import org.apache.commons.collections.Predicate;
77 import org.objectstyle.cayenne.access.DataDomain;
78 import org.objectstyle.cayenne.exp.Expression;
79 import org.objectstyle.cayenne.map.DataMap;
80 import org.objectstyle.cayenne.map.DbEntity;
81 import org.objectstyle.cayenne.map.MapObject;
82 import org.objectstyle.cayenne.map.ObjEntity;
83 import org.objectstyle.cayenne.map.event.EntityEvent;
84 import org.objectstyle.cayenne.modeler.Application;
85 import org.objectstyle.cayenne.modeler.ProjectController;
86 import org.objectstyle.cayenne.modeler.action.CreateAttributeAction;
87 import org.objectstyle.cayenne.modeler.action.CreateRelationshipAction;
88 import org.objectstyle.cayenne.modeler.action.ObjEntitySyncAction;
89 import org.objectstyle.cayenne.modeler.event.EntityDisplayEvent;
90 import org.objectstyle.cayenne.modeler.event.ObjEntityDisplayListener;
91 import org.objectstyle.cayenne.modeler.util.CayenneWidgetFactory;
92 import org.objectstyle.cayenne.modeler.util.CellRenderers;
93 import org.objectstyle.cayenne.modeler.util.Comparators;
94 import org.objectstyle.cayenne.modeler.util.ModelerUtil;
95 import org.objectstyle.cayenne.modeler.util.TextAdapter;
96 import org.objectstyle.cayenne.util.Util;
97 import org.objectstyle.cayenne.util.XMLEncoder;
98 import org.objectstyle.cayenne.validation.ValidationException;
99 import org.scopemvc.util.convertor.StringConvertor;
100 import org.scopemvc.util.convertor.StringConvertors;
101
102 import com.jgoodies.forms.builder.DefaultFormBuilder;
103 import com.jgoodies.forms.layout.FormLayout;
104
105 /**
106  * Detail view of the ObjEntity properties.
107  *
108  * @author Michael Misha Shengaout
109  * @author Andrei Adamchik
110  */

111 public class ObjEntityTab extends JPanel JavaDoc implements ObjEntityDisplayListener,
112         ExistingSelectionProcessor {
113
114     private static final Object JavaDoc noInheritance = new MapObject(
115             "Direct Mapping to Table/View") {
116
117         public void encodeAsXML(XMLEncoder encoder) {
118         }
119     };
120
121     protected ProjectController mediator;
122     protected TextAdapter name;
123     protected TextAdapter className;
124     protected TextAdapter superClassName;
125     protected TextAdapter qualifier;
126     protected JComboBox JavaDoc dbEntityCombo;
127     protected JButton JavaDoc syncWithDbEntityButton;
128     protected JComboBox JavaDoc superEntityCombo;
129     protected JButton JavaDoc tableLabel;
130     protected JCheckBox JavaDoc readOnly;
131     protected JCheckBox JavaDoc optimisticLocking;
132
133     protected TextAdapter clientClassName;
134     protected TextAdapter clientSuperClassName;
135
136     public ObjEntityTab(ProjectController mediator) {
137         this.mediator = mediator;
138         initView();
139         initController();
140     }
141
142     private void initView() {
143         this.setLayout(new BorderLayout JavaDoc());
144
145         JToolBar JavaDoc toolBar = new JToolBar JavaDoc();
146         Application app = Application.getInstance();
147         toolBar.add(app.getAction(ObjEntitySyncAction.getActionName()).buildButton());
148         toolBar.add(app.getAction(CreateAttributeAction.getActionName()).buildButton());
149         toolBar
150                 .add(app
151                         .getAction(CreateRelationshipAction.getActionName())
152                         .buildButton());
153         add(toolBar, BorderLayout.NORTH);
154
155         // create widgets
156
name = new TextAdapter(new JTextField JavaDoc()) {
157
158             protected void updateModel(String JavaDoc text) {
159                 setEntityName(text);
160             }
161         };
162         superClassName = new TextAdapter(new JTextField JavaDoc()) {
163
164             protected void updateModel(String JavaDoc text) {
165                 setSuperClassName(text);
166             }
167         };
168         className = new TextAdapter(new JTextField JavaDoc()) {
169
170             protected void updateModel(String JavaDoc text) {
171                 setClassName(text);
172             }
173         };
174         qualifier = new TextAdapter(new JTextField JavaDoc()) {
175
176             protected void updateModel(String JavaDoc text) {
177                 setQualifier(text);
178             }
179         };
180
181         clientClassName = new TextAdapter(new JTextField JavaDoc()) {
182
183             protected void updateModel(String JavaDoc text) {
184                 setClientClassName(text);
185             }
186         };
187         clientSuperClassName = new TextAdapter(new JTextField JavaDoc()) {
188
189             protected void updateModel(String JavaDoc text) {
190                 setClientSuperClassName(text);
191             }
192         };
193
194         dbEntityCombo = CayenneWidgetFactory.createComboBox();
195         superEntityCombo = CayenneWidgetFactory.createComboBox();
196
197         readOnly = new JCheckBox JavaDoc();
198         optimisticLocking = new JCheckBox JavaDoc();
199
200         tableLabel = CayenneWidgetFactory.createLabelButton("Table/View:");
201         syncWithDbEntityButton = CayenneWidgetFactory.createButton("Sync w/DbEntity");
202         syncWithDbEntityButton.setIcon(ModelerUtil.buildIcon("icon-sync.gif"));
203
204         // assemble
205
FormLayout layout = new FormLayout(
206                 "right:max(50dlu;pref), 3dlu, fill:max(200dlu;pref), 3dlu, fill:140",
207                 "");
208         DefaultFormBuilder builder = new DefaultFormBuilder(layout);
209         builder.setDefaultDialogBorder();
210
211         builder.appendSeparator("ObjEntity Configuration");
212         builder.append("ObjEntity Name:", name.getComponent(), 3);
213         builder.append("Inheritance:", superEntityCombo, 3);
214         builder.append(tableLabel, dbEntityCombo, syncWithDbEntityButton);
215
216         builder.appendSeparator();
217
218         builder.append("Java Class:", className.getComponent(), 3);
219         builder.append("Superclass:", superClassName.getComponent(), 3);
220         builder.append("Qualifier", qualifier.getComponent(), 3);
221         builder.append("Read-Only:", readOnly, 3);
222         builder.append("Optimistic Locking:", optimisticLocking, 3);
223
224         builder.appendSeparator("Java Client");
225         builder.append("Client Java Class:", clientClassName.getComponent(), 3);
226         builder.append("Client Superclass:", clientSuperClassName.getComponent(), 3);
227
228         add(builder.getPanel(), BorderLayout.CENTER);
229     }
230
231     private void initController() {
232         // initialize events processing and tracking of UI updates...
233

234         mediator.addObjEntityDisplayListener(this);
235
236         dbEntityCombo.addActionListener(new ActionListener JavaDoc() {
237
238             public void actionPerformed(ActionEvent JavaDoc e) {
239                 // Change DbEntity for current ObjEntity
240
ObjEntity entity = mediator.getCurrentObjEntity();
241                 DbEntity dbEntity = (DbEntity) dbEntityCombo.getSelectedItem();
242
243                 if (dbEntity != entity.getDbEntity()) {
244                     entity.setDbEntity(dbEntity);
245                     mediator.fireObjEntityEvent(new EntityEvent(this, entity));
246                 }
247             }
248         });
249
250         superEntityCombo.addActionListener(new ActionListener JavaDoc() {
251
252             public void actionPerformed(ActionEvent JavaDoc e) {
253                 // Change super-entity
254
MapObject superEntity = (MapObject) superEntityCombo.getSelectedItem();
255                 String JavaDoc name = (superEntity == noInheritance) ? null : superEntity
256                         .getName();
257
258                 ObjEntity entity = mediator.getCurrentObjEntity();
259
260                 if (!Util.nullSafeEquals(name, entity.getSuperEntityName())) {
261                     entity.setSuperEntityName(name);
262
263                     // if a super-entity selected, disable table selection
264
// and also update parent DbEntity selection...
265
activateFields(name == null);
266                     dbEntityCombo.getModel().setSelectedItem(entity.getDbEntity());
267                     superClassName.setText(entity.getSuperClassName());
268
269                     // fire both EntityEvent and EntityDisplayEvent;
270
// the later is to update attribute and relationship display
271

272                     DataDomain domain = mediator.getCurrentDataDomain();
273                     DataMap map = mediator.getCurrentDataMap();
274
275                     mediator.fireObjEntityEvent(new EntityEvent(this, entity));
276                     mediator.fireObjEntityDisplayEvent(new EntityDisplayEvent(
277                             this,
278                             entity,
279                             map,
280                             domain));
281                 }
282             }
283         });
284
285         tableLabel.addActionListener(new ActionListener JavaDoc() {
286
287             public void actionPerformed(ActionEvent JavaDoc e) {
288                 // Jump to DbEntity of the current ObjEntity
289
DbEntity entity = mediator.getCurrentObjEntity().getDbEntity();
290                 if (entity != null) {
291                     DataDomain dom = mediator.getCurrentDataDomain();
292                     mediator.fireDbEntityDisplayEvent(new EntityDisplayEvent(
293                             this,
294                             entity,
295                             entity.getDataMap(),
296                             dom));
297                 }
298             }
299         });
300
301         syncWithDbEntityButton.addActionListener(new ObjEntitySyncAction(mediator
302                 .getApplication()));
303
304         readOnly.addActionListener(new ActionListener JavaDoc() {
305
306             public void actionPerformed(ActionEvent JavaDoc e) {
307                 ObjEntity entity = mediator.getCurrentObjEntity();
308                 if (entity != null) {
309                     entity.setReadOnly(readOnly.isSelected());
310                     mediator.fireObjEntityEvent(new EntityEvent(this, entity));
311                 }
312             }
313         });
314
315         optimisticLocking.addActionListener(new ActionListener JavaDoc() {
316
317             public void actionPerformed(ActionEvent JavaDoc e) {
318                 ObjEntity entity = mediator.getCurrentObjEntity();
319                 if (entity != null) {
320                     entity.setDeclaredLockType(optimisticLocking.isSelected()
321                             ? ObjEntity.LOCK_TYPE_OPTIMISTIC
322                             : ObjEntity.LOCK_TYPE_NONE);
323                     mediator.fireObjEntityEvent(new EntityEvent(this, entity));
324                 }
325             }
326         });
327     }
328
329     /**
330      * Updates the view from the current model state. Invoked when a currently displayed
331      * ObjEntity is changed.
332      */

333     private void initFromModel(final ObjEntity entity) {
334         // TODO: this is a hack until we implement a real MVC
335
qualifier.getComponent().setBackground(Color.WHITE);
336
337         name.setText(entity.getName());
338         superClassName.setText(entity.getSuperClassName());
339         className.setText(entity.getClassName());
340         readOnly.setSelected(entity.isReadOnly());
341         
342         clientClassName.setText(entity.getClientClassName());
343         clientSuperClassName.setText(entity.getClientSuperClassName());
344         
345
346         StringConvertor convertor = StringConvertors.forClass(Expression.class);
347         qualifier.setText(convertor.valueAsString(entity.getDeclaredQualifier()));
348
349         // TODO: fix inheritance - we should allow to select optimistic
350
// lock if superclass is not already locked,
351
// otherwise we must keep this checked in but not editable.
352
optimisticLocking
353                 .setSelected(entity.getDeclaredLockType() == ObjEntity.LOCK_TYPE_OPTIMISTIC);
354
355         // init DbEntities
356
DataMap map = mediator.getCurrentDataMap();
357         Object JavaDoc[] dbEntities = map.getNamespace().getDbEntities().toArray();
358         Arrays.sort(dbEntities, Comparators.getDataMapChildrenComparator());
359
360         DefaultComboBoxModel JavaDoc dbModel = new DefaultComboBoxModel JavaDoc(dbEntities);
361         dbModel.setSelectedItem(entity.getDbEntity());
362         dbEntityCombo.setRenderer(CellRenderers.entityListRendererWithIcons(map));
363         dbEntityCombo.setModel(dbModel);
364
365         // if a super-entity selected, disable table selection
366
activateFields(entity.getSuperEntityName() == null);
367
368         // init ObjEntities for inheritance
369
Predicate inheritanceFilter = new Predicate() {
370
371             public boolean evaluate(Object JavaDoc object) {
372                 // do not show this entity or any of the subentities
373
if (entity == object) {
374                     return false;
375                 }
376
377                 if (object instanceof ObjEntity) {
378                     return !((ObjEntity) object).isSubentityOf(entity);
379                 }
380
381                 return false;
382             }
383         };
384
385         Object JavaDoc[] objEntities = CollectionUtils
386                 .select(map.getNamespace().getObjEntities(), inheritanceFilter)
387                 .toArray();
388         Arrays.sort(objEntities, Comparators.getDataMapChildrenComparator());
389         Object JavaDoc[] finalObjEntities = new Object JavaDoc[objEntities.length + 1];
390         finalObjEntities[0] = noInheritance;
391         System.arraycopy(objEntities, 0, finalObjEntities, 1, objEntities.length);
392
393         DefaultComboBoxModel JavaDoc superEntityModel = new DefaultComboBoxModel JavaDoc(finalObjEntities);
394         superEntityModel.setSelectedItem(entity.getSuperEntity());
395         superEntityCombo.setRenderer(CellRenderers.entityListRendererWithIcons(map));
396         superEntityCombo.setModel(superEntityModel);
397     }
398
399     void setClassName(String JavaDoc className) {
400         if (className != null && className.trim().length() == 0) {
401             className = null;
402         }
403
404         ObjEntity entity = mediator.getCurrentObjEntity();
405
406         // "ent" may be null if we quit editing by changing tree selection
407
if (entity != null && !Util.nullSafeEquals(entity.getClassName(), className)) {
408             entity.setClassName(className);
409             mediator.fireObjEntityEvent(new EntityEvent(this, entity));
410         }
411     }
412
413     void setSuperClassName(String JavaDoc text) {
414
415         if (text != null && text.trim().length() == 0) {
416             text = null;
417         }
418
419         ObjEntity ent = mediator.getCurrentObjEntity();
420
421         if (ent != null && !Util.nullSafeEquals(ent.getSuperClassName(), text)) {
422             ent.setSuperClassName(text);
423             mediator.fireObjEntityEvent(new EntityEvent(this, ent));
424         }
425     }
426
427     void setClientClassName(String JavaDoc className) {
428         if (className != null && className.trim().length() == 0) {
429             className = null;
430         }
431
432         ObjEntity entity = mediator.getCurrentObjEntity();
433
434         // "ent" may be null if we quit editing by changing tree selection
435
if (entity != null
436                 && !Util.nullSafeEquals(entity.getClientClassName(), className)) {
437             entity.setClientClassName(className);
438             mediator.fireObjEntityEvent(new EntityEvent(this, entity));
439         }
440     }
441
442     void setClientSuperClassName(String JavaDoc text) {
443
444         if (text != null && text.trim().length() == 0) {
445             text = null;
446         }
447
448         ObjEntity ent = mediator.getCurrentObjEntity();
449
450         if (ent != null && !Util.nullSafeEquals(ent.getClientSuperClassName(), text)) {
451             ent.setClientSuperClassName(text);
452             mediator.fireObjEntityEvent(new EntityEvent(this, ent));
453         }
454     }
455
456     void setQualifier(String JavaDoc text) {
457         if (text != null && text.trim().length() == 0) {
458             text = null;
459         }
460
461         ObjEntity entity = mediator.getCurrentObjEntity();
462         if (entity != null) {
463
464             StringConvertor convertor = StringConvertors.forClass(Expression.class);
465             try {
466                 String JavaDoc oldQualifier = convertor.valueAsString(entity
467                         .getDeclaredQualifier());
468                 if (!Util.nullSafeEquals(oldQualifier, text)) {
469                     Expression exp = (Expression) convertor.stringAsValue(text);
470                     entity.setDeclaredQualifier(exp);
471                     mediator.fireObjEntityEvent(new EntityEvent(this, entity));
472                 }
473             }
474             catch (IllegalArgumentException JavaDoc ex) {
475                 // unparsable qualifier
476
throw new ValidationException(ex.getMessage());
477             }
478         }
479     }
480
481     void setEntityName(String JavaDoc newName) {
482         if (newName != null && newName.trim().length() == 0) {
483             newName = null;
484         }
485
486         ObjEntity entity = mediator.getCurrentObjEntity();
487         if (entity == null) {
488             return;
489         }
490
491         if (Util.nullSafeEquals(newName, entity.getName())) {
492             return;
493         }
494
495         if (newName == null) {
496             throw new ValidationException("Entity name is required.");
497         }
498         else if (entity.getDataMap().getObjEntity(newName) == null) {
499             // completely new name, set new name for entity
500
EntityEvent e = new EntityEvent(this, entity, entity.getName());
501             entity.setName(newName);
502
503             mediator.fireObjEntityEvent(e);
504
505             // suggest to update class name
506
String JavaDoc suggestedClassName = suggestedClassName(entity);
507
508             // make sure the current class name is not the default name or blank
509
String JavaDoc entityClassName = entity.getClassName();
510             if (entityClassName == null
511                     || entityClassName.length() == 0
512                     || entityClassName.endsWith("UntitledObjEntity")) {
513                 className.setText(suggestedClassName);
514                 entity.setClassName(suggestedClassName);
515             }
516
517             if (suggestedClassName != null
518                     && !suggestedClassName.equals(entity.getClassName())) {
519                 JOptionPane JavaDoc pane = new JOptionPane JavaDoc(
520                         new Object JavaDoc[] {
521                                 "Change class name to match new entity name?",
522                                 "Suggested class name: " + suggestedClassName
523                         },
524                         JOptionPane.QUESTION_MESSAGE,
525                         JOptionPane.OK_CANCEL_OPTION,
526                         null,
527                         new Object JavaDoc[] {
528                                 "Change", "Cancel"
529                         });
530
531                 pane
532                         .createDialog(Application.getFrame(), "Update Class Name")
533                         .setVisible(true);
534                 if ("Change".equals(pane.getValue())) {
535                     className.setText(suggestedClassName);
536                     setClassName(suggestedClassName);
537                 }
538             }
539         }
540         else {
541             // there is an entity with the same name
542
throw new ValidationException("There is another entity with name '"
543                     + newName
544                     + "'.");
545         }
546     }
547
548     /**
549      * Build a class name based on current entity name.
550      */

551     private String JavaDoc suggestedClassName(ObjEntity entity) {
552         String JavaDoc name = entity.getName();
553         if (name == null || name.trim().length() == 0) {
554             return null;
555         }
556
557         // build suggested package...
558
String JavaDoc oldFQN = entity.getClassName();
559         String JavaDoc pkg = (entity.getDataMap() != null) ? entity
560                 .getDataMap()
561                 .getDefaultPackage() : null;
562
563         if (oldFQN != null && oldFQN.lastIndexOf('.') > 0) {
564             pkg = oldFQN.substring(0, oldFQN.lastIndexOf('.'));
565         }
566
567         if (pkg == null) {
568             pkg = "";
569         }
570         else {
571             pkg = pkg + '.';
572         }
573
574         // build suggested class name
575
int dot = name.lastIndexOf('.');
576         if (dot >= 0 && dot < name.length() - 1) {
577             name = name.substring(dot + 1);
578         }
579
580         return pkg + name;
581     }
582
583     void activateFields(boolean active) {
584         superClassName.getComponent().setEnabled(active);
585         superClassName.getComponent().setEditable(active);
586         clientSuperClassName.getComponent().setEnabled(active);
587         clientSuperClassName.getComponent().setEditable(active);
588         dbEntityCombo.setEnabled(active);
589     }
590
591     public void processExistingSelection(EventObject JavaDoc e) {
592         EntityDisplayEvent ede = new EntityDisplayEvent(this, mediator
593                 .getCurrentObjEntity(), mediator.getCurrentDataMap(), mediator
594                 .getCurrentDataDomain());
595         mediator.fireObjEntityDisplayEvent(ede);
596     }
597
598     public void currentObjEntityChanged(EntityDisplayEvent e) {
599         ObjEntity entity = (ObjEntity) e.getEntity();
600         if (entity == null || !e.isEntityChanged()) {
601             return;
602         }
603
604         initFromModel(entity);
605     }
606
607 }
Popular Tags