001    /*
002    // $Id: //open/mondrian/src/main/mondrian/gui/SchemaPropertyCellEditor.java#14 $
003    // This software is subject to the terms of the Common Public License
004    // Agreement, available at the following URL:
005    // http://www.opensource.org/licenses/cpl.html.
006    // Copyright (C) 2002-2008 Julian Hyde and others
007    // Copyright (C) 2006-2007 CINCOM SYSTEMS, INC.
008    // All Rights Reserved.
009    // You must accept the terms of that agreement to use this software.
010    */
011    package mondrian.gui;
012    
013    import java.awt.event.FocusAdapter;
014    import java.awt.event.ItemListener;
015    import java.awt.event.MouseAdapter;
016    
017    import javax.swing.*;
018    import javax.swing.event.CellEditorListener;
019    import javax.swing.event.ChangeEvent;
020    import java.awt.*;
021    import java.awt.event.ActionEvent;
022    import java.awt.event.ActionListener;
023    import java.awt.event.KeyAdapter;
024    import java.awt.event.KeyEvent;
025    import java.awt.event.MouseEvent;
026    import java.awt.event.MouseListener;
027    import java.util.ArrayList;
028    import java.util.EventObject;
029    import java.util.Vector;
030    import javax.swing.border.*;
031    import javax.swing.text.JTextComponent;
032    
033    /**
034     *
035     * @author  sean
036     * @version $Id: //open/mondrian/src/main/mondrian/gui/SchemaPropertyCellEditor.java#14 $
037     */
038    public class SchemaPropertyCellEditor implements javax.swing.table.TableCellEditor {
039        Workbench workbench;
040    
041        ArrayList listeners;
042    
043        JTextField stringEditor;
044        JCheckBox booleanEditor;
045        JTextField integerEditor;
046        JTable tableEditor;
047        Component activeEditor;
048        JComboBox listEditor;
049        JComboBox relationList;  // Join, Table
050        JTable relationTable;
051        JPanel relationRenderer;
052    
053        JDBCMetaData jdbcMetaData;
054        ComboBoxModel allOptions, selOptions;
055        String listEditorValue ;
056        MouseListener ml;
057        ItemListener il;
058        ActionListener al;
059    
060        String noSelect = "-- No Selection --";
061        FocusAdapter editorFocus;
062    
063        public SchemaPropertyCellEditor(Workbench workbench, JDBCMetaData jdbcMetaData) {
064            this(workbench);
065            this.jdbcMetaData = jdbcMetaData;
066        }
067    
068        /** Creates a new instance of SchemaPropertyCellEditor */
069        public SchemaPropertyCellEditor(Workbench workbench) {
070    
071            this.workbench = workbench;
072    
073            noSelect = getResourceConverter().getString("schemaPropertyCellEditor.noSelection",
074                    "-- No Selection --");
075    
076            listeners = new ArrayList();
077            stringEditor = new JTextField();
078            stringEditor.setFont(Font.decode("Dialog"));
079            stringEditor.setBorder(null);
080    
081            booleanEditor = new JCheckBox();
082            booleanEditor.setBackground(Color.white);
083    
084            integerEditor = new JTextField();
085            integerEditor.setBorder(null);
086            integerEditor.setHorizontalAlignment(JTextField.RIGHT);
087            integerEditor.setFont(Font.decode("Courier"));
088    
089            tableEditor = new JTable();
090    
091            listEditor = new JComboBox();
092            listEditor.setEditable(true);
093            listEditor.setMaximumSize(stringEditor.getMaximumSize());
094            listEditor.setFont(Font.decode("Dialog"));
095            listEditor.setBackground(Color.white);
096            listEditor.setBorder(new EmptyBorder(0, 0, 0, 0)); //super.noFocusBorder);
097    
098            al = new ActionListener() {
099                boolean all = true;
100                public void actionPerformed(ActionEvent e) {
101                    if (e.getActionCommand().equals("comboBoxChanged") && listEditor.getSelectedIndex() == 0) {   // 0 index refers to less or more options
102                        if (all) {
103                            listEditor.setModel(allOptions);
104                        } else {
105                            listEditor.setModel(selOptions);
106                        }
107                        listEditor.setSelectedIndex(-1);
108                        all = !all;
109    
110                    }
111                    if (listEditor.isDisplayable()) {
112                        listEditor.setPopupVisible(true);
113                    }
114                }
115    
116            };
117    
118            JTextComponent editor = (JTextComponent) listEditor.getEditor().getEditorComponent();
119    
120            editor.addMouseListener(new MouseAdapter() {
121                public void mousePressed(MouseEvent e) {
122                    if (listEditor.isDisplayable()) {
123                        listEditor.setPopupVisible(true);
124                    }
125                }
126            });
127    
128            editor.addKeyListener(new KeyAdapter() {
129    
130                public void keyPressed(KeyEvent e) {
131                    if (listEditor.isDisplayable()) {
132                        listEditor.setPopupVisible(true);
133                    }
134                }
135                public void keyReleased(KeyEvent e) {
136                    //listEditor.setSelectedItem(((JTextComponent) e.getSource()).getText());
137                    if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
138                        listEditor.setSelectedItem(listEditorValue);
139                        listEditor.getEditor().setItem(listEditorValue);
140                    }
141                }
142            });
143    
144            relationRenderer = new JPanel();
145    
146            relationList = new JComboBox(new String[] {getResourceConverter().getString("schemaPropertyCellEditor.join","Join"),
147                                                        getResourceConverter().getString("schemaPropertyCellEditor.table","Table")});
148            relationList.setMaximumSize(stringEditor.getMaximumSize());
149            relationTable = new JTable();
150            relationRenderer.add(relationList);
151            relationRenderer.add(relationTable);
152    
153        }
154    
155        public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, final int row, final int column) {
156    
157            PropertyTableModel tableModel = (PropertyTableModel) table.getModel();
158            Class parentClassz = null;
159            if (tableModel.getParentTarget() != null) {
160                parentClassz = tableModel.getParentTarget().getClass();}
161            Class targetClassz = tableModel.target.getClass();
162            String propertyName = tableModel.getRowName(row);
163            String selectedFactTable = tableModel.getFactTable();
164            String selectedFactTableSchema = tableModel.getFactTableSchema();
165            listEditorValue = null;  // reset value of combo-box
166    
167            if (targetClassz == MondrianGuiDef.UserDefinedFunction.class && propertyName.equals("className")) {
168                Vector udfs = getUdfs();
169                ComboBoxModel cAlludfs = new DefaultComboBoxModel(udfs);
170    
171                listEditor.setEditable(true);
172                listEditor.setToolTipText(null);
173                //listEditor.removeMouseListener(ml);
174                listEditor.removeActionListener(al);
175    
176                listEditor.setModel(cAlludfs);
177                listEditor.setSelectedItem((String)value);
178                listEditorValue = (String)value;
179                activeEditor = listEditor;
180            } else if (targetClassz == MondrianGuiDef.Measure.class && propertyName.equals("formatString")) {
181                Vector formatStrs = getFormatStrings();
182                ComboBoxModel cAllformatStrs = new DefaultComboBoxModel(formatStrs);
183    
184                listEditor.setEditable(true);
185                listEditor.setToolTipText(null);
186                listEditor.removeActionListener(al);
187    
188                listEditor.setModel(cAllformatStrs);
189                listEditor.setSelectedItem((String)value);
190                listEditorValue = (String)value;
191                activeEditor = listEditor;
192            } else if (targetClassz == MondrianGuiDef.Measure.class && propertyName.equals("aggregator")) {
193                listEditor.setEditable(false);
194                listEditor.setToolTipText(null);
195                listEditor.removeActionListener(al);
196                listEditor.setModel(new DefaultComboBoxModel(MondrianGuiDef.Measure._aggregator_values));
197                listEditor.setSelectedItem((String)value);
198                activeEditor = listEditor;
199    
200            } else if (targetClassz == MondrianGuiDef.Measure.class && propertyName.equals("datatype")) {
201                listEditor.setEditable(false);
202                listEditor.setToolTipText(null);
203                listEditor.removeActionListener(al);
204                listEditor.setModel(new DefaultComboBoxModel(MondrianGuiDef.Measure._datatype_values));
205                listEditor.setSelectedItem((String)value);
206                activeEditor = listEditor;
207    
208            } else if (targetClassz == MondrianGuiDef.SQL.class && propertyName.equals("dialect")) {
209                listEditor.setEditable(false);
210                listEditor.setToolTipText(null);
211                listEditor.removeActionListener(al);
212                listEditor.setModel(new DefaultComboBoxModel(MondrianGuiDef.SQL._dialect_values));
213                listEditor.setSelectedItem((String)value);
214                activeEditor = listEditor;
215    
216            } else if (targetClassz == MondrianGuiDef.Level.class && propertyName.equals("hideMemberIf")) {
217                listEditor.setEditable(false);
218                listEditor.setToolTipText(null);
219                listEditor.removeActionListener(al);
220                listEditor.setModel(new DefaultComboBoxModel(MondrianGuiDef.Level._hideMemberIf_values));
221                listEditor.setSelectedItem((String)value);
222                activeEditor = listEditor;
223    
224            } else if (targetClassz == MondrianGuiDef.Level.class && propertyName.equals("levelType")) {
225                listEditor.setEditable(false);
226                listEditor.setToolTipText(null);
227                listEditor.removeActionListener(al);
228                listEditor.setModel(new DefaultComboBoxModel(MondrianGuiDef.Level._levelType_values));
229                listEditor.setSelectedItem((String)value);
230                activeEditor = listEditor;
231    
232            } else if (targetClassz == MondrianGuiDef.Level.class && propertyName.equals("type")) {
233                listEditor.setEditable(false);
234                listEditor.setToolTipText(null);
235                listEditor.removeActionListener(al);
236                listEditor.setModel(new DefaultComboBoxModel(MondrianGuiDef.Level._type_values));
237                listEditor.setSelectedItem((String)value);
238                activeEditor = listEditor;
239    
240            } else if (targetClassz == MondrianGuiDef.Dimension.class && propertyName.equals("type")) {
241                listEditor.setEditable(false);
242                listEditor.setToolTipText(null);
243                listEditor.removeActionListener(al);
244                listEditor.setModel(new DefaultComboBoxModel(MondrianGuiDef.Dimension._type_values));
245                listEditor.setSelectedItem((String)value);
246                activeEditor = listEditor;
247    
248            } else if (targetClassz == MondrianGuiDef.DimensionUsage.class && propertyName.equals("source")) {
249                Vector source = getSource();
250                ComboBoxModel cAllsource = new DefaultComboBoxModel(source);
251    
252                listEditor.setEditable(true);
253                listEditor.setToolTipText(null);
254                listEditor.removeActionListener(al);
255    
256                listEditor.setModel(cAllsource);
257                listEditor.setSelectedItem((String)value);
258                listEditorValue = (String)value;
259                activeEditor = listEditor;
260    
261            } else if ((tableModel.target instanceof MondrianGuiDef.Grant || tableModel.target instanceof MondrianGuiDef.MemberGrant) && propertyName.equals("access")) {
262    
263                listEditor.setEditable(false);
264                listEditor.setToolTipText(null);
265                listEditor.removeActionListener(al);
266    
267                ComboBoxModel cAccess = new DefaultComboBoxModel(MondrianGuiDef.Grant._access_values);
268    
269                if (targetClassz == MondrianGuiDef.SchemaGrant.class) {
270                    cAccess = new DefaultComboBoxModel(new String[] {"all", "none", "all_dimensions"});
271                } else if (targetClassz == MondrianGuiDef.CubeGrant.class ||
272                        targetClassz == MondrianGuiDef.DimensionGrant.class ||
273                        targetClassz == MondrianGuiDef.MemberGrant.class) {
274                    cAccess = new DefaultComboBoxModel(new String[] {"all", "none"});
275                } else if (targetClassz == MondrianGuiDef.HierarchyGrant.class) {
276                    cAccess = new DefaultComboBoxModel(new String[] {"all", "none", "custom"});
277                }
278                listEditor.setModel(cAccess);
279    
280                listEditor.setSelectedItem((String)value);
281                activeEditor = listEditor;
282    
283            } else if ((targetClassz ==  MondrianGuiDef.DimensionGrant.class && propertyName.equals("dimension")) ||
284                    (targetClassz ==  MondrianGuiDef.HierarchyGrant.class && propertyName.equals("hierarchy"))) {
285                Vector source = getDimensions();
286                ComboBoxModel cAllsource = new DefaultComboBoxModel(source);
287    
288                listEditor.setEditable(false);
289                listEditor.setToolTipText(null);
290                listEditor.removeActionListener(al);
291    
292                listEditor.setModel(cAllsource);
293                listEditor.setSelectedItem((String)value);
294                listEditorValue = (String)value;
295                activeEditor = listEditor;
296    
297            } else if ((targetClassz ==  MondrianGuiDef.HierarchyGrant.class && (propertyName.equals("topLevel") || propertyName.equals("bottomLevel")))) {
298                Vector source = getLevels(((MondrianGuiDef.HierarchyGrant) tableModel.target).hierarchy);
299                ComboBoxModel cAllsource = new DefaultComboBoxModel(source);
300    
301                listEditor.setEditable(false);
302                listEditor.setToolTipText(null);
303                listEditor.removeActionListener(al);
304    
305                listEditor.setModel(cAllsource);
306                listEditor.setSelectedItem((String)value);
307                listEditorValue = (String)value;
308                activeEditor = listEditor;
309    
310            } else if (((targetClassz == MondrianGuiDef.VirtualCubeDimension.class || targetClassz == MondrianGuiDef.VirtualCubeMeasure.class) &&
311                    propertyName.equals("cubeName")) ||
312                    (targetClassz == MondrianGuiDef.CubeGrant.class && propertyName.equals("cube"))) {
313                Vector source = getCubes();
314                ComboBoxModel cAllsource = new DefaultComboBoxModel(source);
315    
316                listEditor.setEditable(false);
317                listEditor.setToolTipText(null);
318                listEditor.removeActionListener(al);
319    
320                listEditor.setModel(cAllsource);
321                listEditor.setSelectedItem((String)value);
322                listEditorValue = (String)value;
323                activeEditor = listEditor;
324                //===================================================================================
325            } else if ((targetClassz == MondrianGuiDef.Dimension.class && propertyName.equals("foreignKey")) ||
326                    (targetClassz == MondrianGuiDef.DimensionUsage.class && propertyName.equals("foreignKey")) ||
327                    (targetClassz == MondrianGuiDef.Measure.class && propertyName.equals("column"))) {
328                Vector fks      = new Vector(jdbcMetaData.getFactTableFKs(selectedFactTableSchema, selectedFactTable)); //===
329                fks.add(0, getResourceConverter().getString("schemaPropertyCellEditor.allColumns","<< All Columns >>"));
330                Vector allcols  = new Vector(jdbcMetaData.getAllColumns(selectedFactTableSchema, selectedFactTable));
331                ComboBoxModel cFks = new DefaultComboBoxModel(fks);
332    
333                listEditor.setEditable(true);
334                listEditor.setToolTipText(null);
335                listEditor.removeActionListener(al);
336                if ((fks.size() > 1) && propertyName.equals("foreignKey")) {
337                    allcols.add(0, getResourceConverter().getString("schemaPropertyCellEditor.foreignKeys", "<< Foreign keys >>"));
338                    ComboBoxModel cAllcols = new DefaultComboBoxModel(allcols);
339                    listEditor.setModel(cFks);
340                    //listEditor.setToolTipText("Relavant Options shows Foreign keys and All Columns in selected Fact Table");
341                    selOptions = cFks;
342                    allOptions = cAllcols;
343                    //listEditor.addItemListener(il);     // executes twice for each selection
344                    //listEditor.addMouseListener(ml);    //does not execute when ComboBox isEditable true.
345                    listEditor.addActionListener(al);
346                } else {
347                    ComboBoxModel cAllcols = new DefaultComboBoxModel(allcols);
348                    listEditor.setModel(cAllcols);
349                }
350    
351                listEditor.setSelectedItem((String)value);
352                listEditorValue = (String)value;
353                activeEditor = listEditor;
354            } else if (targetClassz == MondrianGuiDef.Hierarchy.class && propertyName.equals("primaryKey")) {
355                MondrianGuiDef.Hierarchy hProps = (MondrianGuiDef.Hierarchy) tableModel.getValue();
356                String pkTable = hProps.primaryKeyTable;
357    
358                String schemaName = null;
359                Vector allcols  = jdbcMetaData.getAllColumns(schemaName, pkTable);
360                String pk = jdbcMetaData.getTablePK(schemaName, pkTable);
361    
362                ComboBoxModel cAllcols = new DefaultComboBoxModel(allcols);
363    
364                listEditor.setEditable(true);
365                listEditor.setToolTipText(null);
366                listEditor.removeActionListener(al);
367    
368                listEditor.setModel(cAllcols);
369                if (value == null || ((String) value).equals("")) {
370                    listEditor.setSelectedItem(pk);
371                } else {
372                    listEditor.setSelectedItem((String)value);
373                    listEditorValue = (String)value;
374                }
375                activeEditor = listEditor;
376            } else if ((targetClassz == MondrianGuiDef.Level.class && propertyName.equals("column")) ||
377                    (targetClassz == MondrianGuiDef.Level.class && propertyName.equals("nameColumn")) ||
378                    (targetClassz == MondrianGuiDef.Level.class && propertyName.equals("parentColumn")) ||
379                    (targetClassz == MondrianGuiDef.Level.class && propertyName.equals("ordinalColumn")) ||
380                    (targetClassz == MondrianGuiDef.Level.class && propertyName.equals("captionColumn")) ||
381                    (targetClassz == MondrianGuiDef.Closure.class && propertyName.equals("parentColumn")) ||
382                    (targetClassz == MondrianGuiDef.Closure.class && propertyName.equals("childColumn")) ||
383                    (targetClassz == MondrianGuiDef.Property.class && propertyName.equals("column"))) {
384                MondrianGuiDef.Level lProps;
385                if (targetClassz == MondrianGuiDef.Level.class) {
386                    lProps = (MondrianGuiDef.Level) tableModel.getValue();
387                } else {
388                    lProps = (MondrianGuiDef.Level) this.getParentObject();
389                }
390    
391                String lTable = lProps.table;
392                Vector allcols;
393                if (lTable != null) {
394                    allcols  = jdbcMetaData.getAllColumns(null, lTable);
395                } else {
396                    allcols  = jdbcMetaData.getAllColumns(selectedFactTableSchema, null);
397                }
398                ComboBoxModel cAllcols = new DefaultComboBoxModel(allcols);
399    
400                listEditor.setEditable(true);
401                listEditor.setToolTipText(null);
402                listEditor.removeActionListener(al);
403    
404                listEditor.setModel(cAllcols);
405                listEditor.setSelectedItem((String)value);
406                listEditorValue = (String)value;
407                activeEditor = listEditor;
408                //===================================================================================
409    
410            } else if (targetClassz == MondrianGuiDef.Property.class && propertyName.equals("type")) {
411                listEditor.setEditable(false);
412                listEditor.setToolTipText(null);
413                listEditor.removeActionListener(al);
414                listEditor.setModel(new DefaultComboBoxModel(MondrianGuiDef.Property._type_values));
415                listEditor.setSelectedItem((String)value);
416                activeEditor = listEditor;
417    
418            } else if ((targetClassz == MondrianGuiDef.AggFactCount.class && propertyName.equals("column")) ||
419                       (targetClassz == MondrianGuiDef.AggIgnoreColumn.class && propertyName.equals("column")) ||
420                       (targetClassz == MondrianGuiDef.AggLevel.class && propertyName.equals("column")) ||
421                       (targetClassz == MondrianGuiDef.AggMeasure.class && propertyName.equals("column")) ||
422                       (targetClassz == MondrianGuiDef.AggForeignKey.class && propertyName.equals("factColumn")) ||
423                       (targetClassz == MondrianGuiDef.AggForeignKey.class && propertyName.equals("aggColumn"))) {
424                Vector allcols;
425                allcols  = jdbcMetaData.getAllColumns(null, null);
426                ComboBoxModel cAllcols = new DefaultComboBoxModel(allcols);
427    
428                listEditor.setEditable(true);
429                listEditor.setToolTipText(null);
430                listEditor.removeActionListener(al);
431    
432                listEditor.setModel(cAllcols);
433                listEditor.setSelectedItem((String)value);
434                listEditorValue = (String)value;
435                activeEditor = listEditor;
436    
437            } else if (targetClassz == MondrianGuiDef.Table.class && propertyName.equals("schema")) {
438                Vector allschemas  = jdbcMetaData.getAllSchemas();
439                ComboBoxModel cAllschemas = new DefaultComboBoxModel(allschemas);
440    
441                listEditor.setEditable(true);
442                listEditor.setToolTipText(null);
443                listEditor.removeActionListener(al);
444    
445                listEditor.setModel(cAllschemas);
446                listEditor.setSelectedItem((String)value);
447                listEditorValue = (String)value;
448                activeEditor = listEditor;
449            } else if ((targetClassz == MondrianGuiDef.Table.class && propertyName.equals("name")) ||
450                (targetClassz == MondrianGuiDef.Hierarchy.class && propertyName.equals("primaryKeyTable")) ||
451                (targetClassz == MondrianGuiDef.Level.class && propertyName.equals("table"))) {
452                String schema = "";
453                if (targetClassz == MondrianGuiDef.Table.class) {
454                    MondrianGuiDef.Table tProps = (MondrianGuiDef.Table) tableModel.getValue();
455                    schema = tProps.schema;
456                }
457                Vector factTables           = new Vector(jdbcMetaData.getFactTables(schema));
458                Vector allTablesMinusFact   = new Vector(jdbcMetaData.getAllTables(schema, selectedFactTable));
459                Vector allTables            = new Vector(jdbcMetaData.getAllTables(schema));
460                Vector dimeTables           = new Vector(jdbcMetaData.getDimensionTables(schema, selectedFactTable));
461    
462                ComboBoxModel cFactTables = new DefaultComboBoxModel(factTables);   //suggestive fact tables
463                ComboBoxModel cAllTables  = new DefaultComboBoxModel((allTablesMinusFact.size() > 0) ? allTablesMinusFact : allTables);  // all tables of selected schema
464                ComboBoxModel cDimeTables = new DefaultComboBoxModel(dimeTables); // suggestive dimension tables based on selected fact table .
465    
466                listEditor.setEditable(true);
467                listEditor.setToolTipText(null);
468                listEditor.removeActionListener(al);
469                listEditor.setModel(cAllTables);
470                allOptions = cAllTables;
471                boolean toggleModel = false;
472                if (parentClassz == MondrianGuiDef.Cube.class) {
473                    cAllTables  = new DefaultComboBoxModel(allTables);
474                    allOptions = cAllTables;
475                    if (factTables.size() > 0) {
476                        ((DefaultComboBoxModel) cFactTables).insertElementAt(workbench.getResourceConverter().getString("schemaPropertyCellEditor.allTables","<< All Tables >>"),0);
477                        ((DefaultComboBoxModel) cAllTables).insertElementAt(workbench.getResourceConverter().getString("schemaPropertyCellEditor.factTables","<< Fact Tables >>"),0);
478                        listEditor.setModel(cFactTables);
479                        //listEditor.setToolTipText("Double-Click to toggle between Fact tables and All tables");
480                        selOptions = cFactTables;
481                        toggleModel = true;
482                    }
483                } else {
484                    if (dimeTables.size() > 0) {
485                        ((DefaultComboBoxModel) cDimeTables).insertElementAt(workbench.getResourceConverter().getString("schemaPropertyCellEditor.allTables","<< All Tables >>"),0);
486                        ((DefaultComboBoxModel) cAllTables).insertElementAt(workbench.getResourceConverter().getString("schemaPropertyCellEditor.dimensionTables","<< Dimension Tables >>"),0);
487                        listEditor.setModel(cDimeTables);
488                        //listEditor.setToolTipText("Double-Click to toggle between Dimension tables and All tables");
489                        selOptions = cDimeTables;
490                        toggleModel = true;
491                    }
492                }
493    
494                if (toggleModel) {
495                    listEditor.addActionListener(al);}
496                listEditor.setSelectedItem((String)value);
497                listEditorValue = (String)value;
498                activeEditor = listEditor;
499            } else if (value instanceof String) {
500                activeEditor = stringEditor;
501                stringEditor.setText((String)value);
502            } else if (value instanceof Boolean) {
503                activeEditor = booleanEditor;
504                booleanEditor.setSelected((Boolean) value);
505            } else if (value instanceof Integer) {
506                activeEditor = integerEditor;
507                integerEditor.setText((String)value);
508            } else if (value == null) {
509                value = "";
510                activeEditor = stringEditor;
511                stringEditor.setText((String)value);
512            } else if (value.getClass() == MondrianGuiDef.Join.class) {
513                SchemaPropertyCellEditor spce = new SchemaPropertyCellEditor(workbench);
514                tableEditor.setDefaultEditor(Object.class, spce);
515                SchemaPropertyCellRenderer spcr = new SchemaPropertyCellRenderer(workbench);
516                tableEditor.setDefaultRenderer(Object.class, spcr);
517                PropertyTableModel ptm = new PropertyTableModel(workbench, value,SchemaExplorer.DEF_JOIN);
518                tableEditor.setModel(ptm);
519                activeEditor = tableEditor;
520            } else if (value.getClass() == MondrianGuiDef.NameExpression.class) {
521                return null;
522            } else if (value.getClass() == MondrianGuiDef.RelationOrJoin.class) {
523                // REVIEW: I don't think this code will ever be executed, because
524                // class RelationOrJoin is abstract.
525                SchemaPropertyCellEditor spce = new SchemaPropertyCellEditor(workbench);
526                tableEditor.setDefaultEditor(Object.class, spce);
527                SchemaPropertyCellRenderer spcr = new SchemaPropertyCellRenderer(workbench);
528                tableEditor.setDefaultRenderer(Object.class, spcr);
529                PropertyTableModel ptm = new PropertyTableModel(workbench, value,SchemaExplorer.DEF_RELATION);
530                tableEditor.setModel(ptm);
531                activeEditor = tableEditor;
532                return null;
533            } else if (value.getClass() == MondrianGuiDef.OrdinalExpression.class) {
534                SchemaPropertyCellEditor spce = new SchemaPropertyCellEditor(workbench);
535                tableEditor.setDefaultEditor(Object.class, spce);
536                SchemaPropertyCellRenderer spcr = new SchemaPropertyCellRenderer(workbench);
537                tableEditor.setDefaultRenderer(Object.class, spcr);
538                //===PropertyTableModel ptm = new PropertyTableModel(value,SchemaExplorer.DEF_SQL);
539                PropertyTableModel ptm = new PropertyTableModel(workbench, ((MondrianGuiDef.OrdinalExpression)value).expressions[0],SchemaExplorer.DEF_SQL);
540                ptm.setParentTarget(((PropertyTableModel) table.getModel()).target);
541                tableEditor.setModel(ptm);
542                activeEditor = tableEditor;
543            } else if (value.getClass() == MondrianGuiDef.Formula.class) {
544                SchemaPropertyCellEditor spce = new SchemaPropertyCellEditor(workbench, jdbcMetaData);
545                tableEditor.setDefaultEditor(Object.class, spce);
546                SchemaPropertyCellRenderer spcr = new SchemaPropertyCellRenderer(workbench);
547                tableEditor.setDefaultRenderer(Object.class, spcr);
548                PropertyTableModel ptm = new PropertyTableModel(workbench, value,SchemaExplorer.DEF_FORMULA);
549                tableEditor.setModel(ptm);
550                tableEditor.getColumnModel().getColumn(0).setMaxWidth(100);
551                tableEditor.getColumnModel().getColumn(0).setMinWidth(100);
552                activeEditor = tableEditor;
553            } else if (value.getClass() == MondrianGuiDef.CalculatedMemberProperty.class) {
554                SchemaPropertyCellEditor spce = new SchemaPropertyCellEditor(workbench, jdbcMetaData);
555                tableEditor.setDefaultEditor(Object.class, spce);
556                SchemaPropertyCellRenderer spcr = new SchemaPropertyCellRenderer(workbench);
557                tableEditor.setDefaultRenderer(Object.class, spcr);
558                PropertyTableModel ptm = new PropertyTableModel(workbench, value,SchemaExplorer.DEF_CALCULATED_MEMBER_PROPERTY);
559                tableEditor.setModel(ptm);
560                tableEditor.getColumnModel().getColumn(0).setMaxWidth(100);
561                tableEditor.getColumnModel().getColumn(0).setMinWidth(100);
562                activeEditor = tableEditor;
563            } else if (value.getClass() == MondrianGuiDef.Table.class) {
564                SchemaPropertyCellEditor spce = new SchemaPropertyCellEditor(workbench, jdbcMetaData);
565                // adding cell editing stopped listeners to nested property of type table
566                // so that any change in value of table fields are reflected in tree
567                for (int i = listeners.size() - 1; i >= 0; i--) {
568                    spce.addCellEditorListener(((CellEditorListener)listeners.get(i)));
569                }
570                tableEditor.setDefaultEditor(Object.class, spce);
571                SchemaPropertyCellRenderer spcr = new SchemaPropertyCellRenderer(workbench);
572                tableEditor.setDefaultRenderer(Object.class, spcr);
573                PropertyTableModel ptm = new PropertyTableModel(workbench, value,SchemaExplorer.DEF_TABLE);
574                ptm.setFactTable(selectedFactTable);
575                if (targetClassz == MondrianGuiDef.Cube.class) {
576                    ptm.setParentTarget(((PropertyTableModel) table.getModel()).target);}
577                tableEditor.setModel(ptm);
578                tableEditor.getColumnModel().getColumn(0).setMaxWidth(100);
579                tableEditor.getColumnModel().getColumn(0).setMinWidth(100);
580                activeEditor = tableEditor;
581            } else if (value.getClass() == MondrianGuiDef.AggFactCount.class) {
582                SchemaPropertyCellEditor spce = new SchemaPropertyCellEditor(workbench, jdbcMetaData);
583                // adding cell editing stopped listeners to nested property of type table
584                // so that any change in value of table fields are reflected in tree
585                for (int i = listeners.size() - 1; i >= 0; i--) {
586                    spce.addCellEditorListener(((CellEditorListener)listeners.get(i)));
587                }
588                tableEditor.setDefaultEditor(Object.class, spce);
589                SchemaPropertyCellRenderer spcr = new SchemaPropertyCellRenderer(workbench);
590                tableEditor.setDefaultRenderer(Object.class, spcr);
591                PropertyTableModel ptm = new PropertyTableModel(workbench, value,SchemaExplorer.DEF_AGG_FACT_COUNT);
592                ptm.setFactTable(selectedFactTable);
593                /*
594                if (targetClassz == MondrianGuiDef.Cube.class) {
595                    ptm.setParentTarget(((PropertyTableModel) table.getModel()).target);}
596                 */
597                tableEditor.setModel(ptm);
598                tableEditor.getColumnModel().getColumn(0).setMaxWidth(100);
599                tableEditor.getColumnModel().getColumn(0).setMinWidth(100);
600                activeEditor = tableEditor;
601            } else if (value.getClass() == MondrianGuiDef.Closure.class) {
602                SchemaPropertyCellEditor spce = new SchemaPropertyCellEditor(workbench, jdbcMetaData);
603                // adding cell editing stopped listeners to nested property of type table
604                // so that any change in value of table fields are reflected in tree
605                for (int i = listeners.size() - 1; i >= 0; i--) {
606                    spce.addCellEditorListener(((CellEditorListener)listeners.get(i)));
607                }
608                tableEditor.setDefaultEditor(Object.class, spce);
609                SchemaPropertyCellRenderer spcr = new SchemaPropertyCellRenderer(workbench);
610                tableEditor.setDefaultRenderer(Object.class, spcr);
611                PropertyTableModel ptm = new PropertyTableModel(workbench, value,SchemaExplorer.DEF_CLOSURE);
612                ptm.setFactTable(selectedFactTable);
613                if (targetClassz == MondrianGuiDef.Level.class) {
614                    ptm.setParentTarget(((PropertyTableModel) table.getModel()).target);}
615                tableEditor.setModel(ptm);
616                tableEditor.getColumnModel().getColumn(0).setMaxWidth(100);
617                tableEditor.getColumnModel().getColumn(0).setMinWidth(100);
618                spcr.setTableRendererHeight(tableEditor, null);
619                activeEditor = tableEditor;
620            } else if (value.getClass() == MondrianGuiDef.Property.class) {
621                SchemaPropertyCellEditor spce = new SchemaPropertyCellEditor(workbench);
622                tableEditor.setDefaultEditor(Object.class, spce);
623                SchemaPropertyCellRenderer spcr = new SchemaPropertyCellRenderer(workbench);
624                tableEditor.setDefaultRenderer(Object.class, spcr);
625                PropertyTableModel ptm = new PropertyTableModel(workbench, value,SchemaExplorer.DEF_PROPERTY);
626                tableEditor.setModel(ptm);
627                activeEditor = tableEditor;
628            } else {
629                value = "";
630                activeEditor = stringEditor;
631                stringEditor.setText((String)value);
632            }
633            activeEditor.setVisible(true);
634    
635            /*  Focus lost on table was supposed to save the last edited value in table model object
636                     but this activeeditor saved the last edited value in the new table model object
637                activeEditor.addFocusListener(new FocusAdapter() {
638                    public void focusGained(FocusEvent e) {System.out.println("**Editor GAINED focus "+this.getClass()); }
639                    public void focusLost(FocusEvent e) {System.out.println("**Editor LOST focus "+this.getClass());
640    
641                        Object value = table.getCellEditor(row, column).getCellEditorValue();
642                        table.getModel().setValueAt(value, row, column);
643                            Object value = table.getCellEditor().getCellEditorValue();
644                            table.setValueAt(value, row, column);
645                    }
646                });
647             */
648    
649            table.changeSelection(row, column, false, false);
650            activeEditor.setBackground(new java.awt.Color(224, 249, 255));
651            activeEditor.requestFocusInWindow();
652            return activeEditor;
653        }
654    
655        /** Adds a listener to the list that's notified when the editor
656         * stops, or cancels editing.
657         *
658         * @param   l       the CellEditorListener
659         *
660         */
661        public void addCellEditorListener(CellEditorListener l) {
662            listeners.add(l);
663        }
664    
665        /** Tells the editor to cancel editing and not accept any partially
666         * edited value.
667         *
668         */
669        public void cancelCellEditing() {
670            if (activeEditor != null) {
671                activeEditor.setVisible(false);
672                fireEditingCancelled();
673            }
674        }
675    
676        /** Returns the value contained in the editor.
677         * @return the value contained in the editor
678         *
679         */
680        public Object getCellEditorValue() {
681            if (activeEditor == stringEditor) {
682                return stringEditor.getText();
683            } else if (activeEditor == booleanEditor) {
684                return booleanEditor.isSelected();
685            } else if (activeEditor == listEditor) {
686                if (listEditor.isEditable()) {
687                    return listEditor.getEditor().getItem();   // returns the edited value from combox box
688                } else {
689                    if (listEditor.getSelectedItem() == noSelect) {
690                        return null;  // blank selection
691                    }
692                    return listEditor.getSelectedItem(); //// returns the selected value from combox box
693                }
694            } else if (activeEditor == tableEditor) {
695                return ((PropertyTableModel) tableEditor.getModel()).getValue();
696            }
697    
698            return null;
699        }
700    
701        /** Asks the editor if it can start editing using <code>anEvent</code>.
702         * <code>anEvent</code> is in the invoking component coordinate system.
703         * The editor can not assume the Component returned by
704         * <code>getCellEditorComponent</code> is installed.  This method
705         * is intended for the use of client to avoid the cost of setting up
706         * and installing the editor component if editing is not possible.
707         * If editing can be started this method returns true.
708         *
709         * @param   anEvent     the event the editor should use to consider
710         *              whether to begin editing or not
711         * @return  true if editing can be started
712         * @see #shouldSelectCell
713         *
714         */
715        public boolean isCellEditable(EventObject anEvent) {
716            return true;
717        }
718    
719        /** Removes a listener from the list that's notified
720         *
721         * @param   l       the CellEditorListener
722         *
723         */
724        public void removeCellEditorListener(CellEditorListener l) {
725            listeners.remove(l);
726        }
727    
728        /** Returns true if the editing cell should be selected, false otherwise.
729         * Typically, the return value is true, because is most cases the editing
730         * cell should be selected.  However, it is useful to return false to
731         * keep the selection from changing for some types of edits.
732         * eg. A table that contains a column of check boxes, the user might
733         * want to be able to change those checkboxes without altering the
734         * selection.  (See Netscape Communicator for just such an example)
735         * Of course, it is up to the client of the editor to use the return
736         * value, but it doesn't need to if it doesn't want to.
737         *
738         * @param   anEvent     the event the editor should use to start
739         *              editing
740         * @return  true if the editor would like the editing cell to be selected;
741         *    otherwise returns false
742         * @see #isCellEditable
743         *
744         */
745        public boolean shouldSelectCell(EventObject anEvent) {
746            return true;
747        }
748    
749        /** Tells the editor to stop editing and accept any partially edited
750         * value as the value of the editor.  The editor returns false if
751         * editing was not stopped; this is useful for editors that validate
752         * and can not accept invalid entries.
753         *
754         * @return  true if editing was stopped; false otherwise
755         *
756         */
757        public boolean stopCellEditing() {
758            if (activeEditor != null) {
759                /* save the nested table as well */
760                if (activeEditor == tableEditor) {
761                    if (tableEditor.isEditing()) {
762                        /*
763                        System.out.println("    tableEditor.isEditing()=="+tableEditor.isEditing());
764                        System.out.println("    tableEditor.getEditingRow()=="+tableEditor.getEditingRow());
765                        System.out.println("    tableEditor.getEditingColumn()=="+tableEditor.getEditingColumn());
766                         */
767                        ArrayList nestedTableEditors = new ArrayList();
768                        JTable nestedTableEditor = tableEditor;
769                        // get the list of nested tables from outer->inner sequence, descending towards innermost nested table
770                        // so that we can stop the editing in this order.
771                        while (nestedTableEditor != null) {
772                            nestedTableEditors.add(nestedTableEditor);
773                            SchemaPropertyCellEditor sce = (SchemaPropertyCellEditor) nestedTableEditor.getCellEditor();
774                            if (sce != null && sce.activeEditor == sce.tableEditor && sce.tableEditor.isEditing()) {
775                                nestedTableEditor = sce.tableEditor; //
776                                //tableEditor.editingStopped(null);
777                            } else {
778                                nestedTableEditor = null;
779                            }
780                        }
781                        for (int i = nestedTableEditors.size() - 1; i >= 0; i--) {
782                            ((JTable) nestedTableEditors.get(i)).editingStopped(null);
783                        }
784                            /*
785                            SchemaPropertyCellEditor sce = (SchemaPropertyCellEditor) tableEditor.getCellEditor();
786                            if (sce != null) {
787                                //tableEditor.editingStopped(null);
788                                Object value = sce.getCellEditorValue();
789                                tableEditor.setValueAt(value, tableEditor.getEditingRow(), tableEditor.getEditingColumn());
790                                //sce.stopCellEditing();
791                            }
792                             **/
793    
794                    }
795    
796                }
797                activeEditor.setVisible(false);
798                fireEditingStopped();
799            }
800            return true;
801        }
802    
803        protected void fireEditingStopped() {
804            ChangeEvent ce = new ChangeEvent(this);
805            for (int i = listeners.size() - 1; i >= 0; i--) {
806                ((CellEditorListener)listeners.get(i)).editingStopped(ce);
807            }
808        }
809    
810        protected void fireEditingCancelled() {
811            ChangeEvent ce = new ChangeEvent(this);
812            for (int i = listeners.size() - 1; i >= 0; i--) {
813                ((CellEditorListener)listeners.get(i)).editingCanceled(ce);
814            }
815        }
816        private Vector getUdfs() {
817            Vector udfs = new Vector();
818            MondrianGuiDef.Schema s = this.getSchema();
819            if (s != null) {
820                MondrianGuiDef.UserDefinedFunction [] u = s.userDefinedFunctions;
821                for (int i = 0; i < u.length; i++) {
822                    if (!(u[i].className == null || udfs.contains(u[i].className))) {
823                        udfs.add(u[i].className);
824                    }
825                }
826            }
827    
828            return udfs;
829        }
830    
831        private Vector getFormatStrings() {
832            Vector fs = new Vector();
833            MondrianGuiDef.Schema s = this.getSchema();
834            if (s != null) {
835                MondrianGuiDef.Cube [] c = s.cubes;
836                for (int i = 0; i < c.length; i++) {
837                    MondrianGuiDef.Measure [] m = c[i].measures;
838                    for (int j = 0; j < m.length; j++) {
839                        if (!(m[j].formatString == null || fs.contains(m[j].formatString))) {
840                            fs.add(m[j].formatString);
841                        }
842                    }
843                }
844            }
845            return fs;
846        }
847    
848        private MondrianGuiDef.Schema getSchema() {
849            SchemaExplorer se = this.getSchemaExplorer();
850            return (se == null) ? null : se.getSchema();
851        }
852    
853        private Object getParentObject() {
854            SchemaExplorer se = this.getSchemaExplorer();
855            if (se != null) {
856                Object po = se.getParentObject();
857                return po;
858            }
859            return null;
860        }
861    
862        private SchemaExplorer getSchemaExplorer() {
863            SchemaExplorer se = null;
864            for (int i = listeners.size() - 1; i >= 0; i--) {
865                CellEditorListener cel = ((CellEditorListener)listeners.get(i));
866                if (cel instanceof SchemaExplorer) {
867                    se = (SchemaExplorer) cel;
868                    break;
869                }
870            }
871            return se;
872        }
873    
874        private Vector getSource() {    //shared dimensions in schema
875            Vector source = new Vector();
876            MondrianGuiDef.Schema s = this.getSchema();
877            if (s != null) {
878                MondrianGuiDef.Dimension [] u = s.dimensions;
879                for (int i = 0; i < u.length; i++) {
880                    source.add(u[i].name);
881                }
882            }
883            return source;
884        }
885    
886        private Vector getCubes() {
887            Vector source = new Vector();
888            //===source.add(noSelect);
889            MondrianGuiDef.Schema s = this.getSchema();
890            if (s != null) {
891                MondrianGuiDef.Cube [] u = s.cubes;
892                for (int i = 0; i < u.length; i++) {
893                    source.add(u[i].name);
894                }
895            }
896            return source;
897        }
898    
899        private void generatePrimaryKeyTables(Object relation, Vector v) {
900            if (relation == null) {
901                return;
902            }
903            if (relation instanceof MondrianGuiDef.Table) {
904                String sname = ((MondrianGuiDef.Table) relation).schema;
905                v.add(((sname == null || sname.equals("")) ? "" : sname + "->") + ((MondrianGuiDef.Table) relation).name);
906                return;
907            }
908            MondrianGuiDef.Join currentJoin = (MondrianGuiDef.Join)relation;
909            generatePrimaryKeyTables(currentJoin.left, v);
910            generatePrimaryKeyTables(currentJoin.right, v);
911            return ;
912        }
913    
914        private Vector getDimensions() {
915            Vector dims = new Vector();
916            Object po = getParentObject() ; //cubegrant
917            if (po != null) {
918                MondrianGuiDef.CubeGrant parent = (MondrianGuiDef.CubeGrant) po;
919                if (! (parent.cube == null || parent.cube.equals(""))) {
920                    MondrianGuiDef.Schema s = getSchema();
921                    if (s != null) {
922                        for (int i = 0; i < s.cubes.length ; i++) {
923                            if (s.cubes[i].name.equals(parent.cube)) {
924                                for (int j = 0; j < s.cubes[i].dimensions.length; j++) {
925                                    dims.add(s.cubes[i].dimensions[j].name);
926                                }
927                                break;
928                            }
929                        }
930                    }
931                }
932            }
933            return dims;
934        }
935    
936        private String cacheCube = "";
937        private String cacheHierarchy = "";
938        private Vector hlevels = new Vector();
939    
940        private Vector getLevels(String hierarchy) {
941            if (! (hierarchy == null || hierarchy.equals(""))) {
942                if (hierarchy.startsWith("[") && hierarchy.endsWith("]")) {
943                    hierarchy = hierarchy.substring(1, hierarchy.length() - 1);
944                }
945                Object po = getParentObject() ; //cubegrant
946                if (po != null) {
947                    MondrianGuiDef.CubeGrant parent = (MondrianGuiDef.CubeGrant) po;
948                    if (! (parent.cube == null || parent.cube.equals(""))) {
949                        if (cacheCube.equals(parent.cube) && cacheHierarchy.equals(hierarchy)) {
950                            return hlevels;
951                        } else {
952                            hlevels = new Vector();
953                            cacheCube = parent.cube;
954                            cacheHierarchy = hierarchy;
955                            MondrianGuiDef.Schema s = getSchema();
956                            if (s != null) {
957                                // search for cube in schema
958                                for (int i = 0; i < s.cubes.length; i++) {
959                                    if (s.cubes[i].name.equals(parent.cube)) {
960                                        // serach for hierarchy in cube
961                                        for (int j = 0; j < s.cubes[i].dimensions.length; j++) {
962                                            if (s.cubes[i].dimensions[j].name.equals(hierarchy)) {
963                                                MondrianGuiDef.Dimension d = null;
964                                                if (s.cubes[i].dimensions[j] instanceof MondrianGuiDef.Dimension) {
965                                                   d =  (MondrianGuiDef.Dimension)s.cubes[i].dimensions[j];
966                                                } else {
967                                                   MondrianGuiDef.DimensionUsage d2 = (MondrianGuiDef.DimensionUsage)s.cubes[i].dimensions[j];
968                                                   for (int m = 0; m < s.dimensions.length; m++) {
969                                                        if (s.dimensions[m].name.equals(d2.source)) {
970                                                            d = s.dimensions[m];
971                                                            break;
972                                                        }
973                                                   }
974                                                }
975                                                if (d.hierarchies[0] != null) {
976                                                    for (int k = 0; k < d.hierarchies[0].levels.length; k++) {
977                                                        hlevels.add(d.hierarchies[0].levels[k].name);
978                                                    }
979                                                }
980                                                break;
981                                            }
982                                        }
983                                        break;
984                                    }
985                                }
986                            }
987                        }
988                    }
989                }
990            }
991            return hlevels;
992        }
993    
994        private I18n getResourceConverter() {
995            return workbench.getResourceConverter();
996        }
997    
998        /* // Not required for time being
999        class MapComboBoxModel extends DefaultComboBoxModel {
1000            Map objectsMap;
1001    
1002            public MapComboBoxModel(Map m) {
1003                super(m.keySet().toArray());
1004                objectsMap = m;
1005            }
1006    
1007            public Object getListEditorValue() {
1008                return objectsMap.get(super.getSelectedItem());
1009            }
1010        }
1011         */
1012    }
1013    
1014    
1015    // End SchemaPropertyCellEditor.java