001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2002-2005 Julian Hyde
008// Copyright (C) 2005-2010 Pentaho and others
009// Copyright (C) 2006-2007 CINCOM SYSTEMS, INC.
010// All Rights Reserved.
011*/
012package mondrian.gui;
013
014import mondrian.gui.validate.ValidationUtils;
015import mondrian.gui.validate.impl.*;
016
017import org.eigenbase.xom.ElementDef;
018
019import java.awt.*;
020import javax.swing.*;
021import javax.swing.tree.TreePath;
022
023/**
024 * Render an entry for the tree.
025 *
026 * @author sean
027 */
028public class SchemaTreeCellRenderer
029    extends javax.swing.tree.DefaultTreeCellRenderer
030{
031    private final ClassLoader myClassLoader;
032    public boolean invalidFlag;
033    private JdbcMetaData jdbcMetaData;
034    private final Workbench workbench;
035
036    /**
037     * Creates a SchemaTreeCellRenderer with Workbench and metadata.
038     */
039    public SchemaTreeCellRenderer(
040        Workbench workbench,
041        JdbcMetaData jdbcMetaData)
042    {
043        super();
044        this.myClassLoader = this.getClass().getClassLoader();
045        this.workbench = workbench;
046        this.jdbcMetaData = jdbcMetaData;
047    }
048
049    /**
050     * Creates a SchemaTreeCellRenderer.
051     */
052    public SchemaTreeCellRenderer() {
053        this(null, null);
054    }
055
056    public Component getTreeCellRendererComponent(
057        JTree tree,
058        Object value,
059        boolean sel,
060        boolean expanded,
061        boolean leaf,
062        int row,
063        boolean hasFocus)
064    {
065        super.getTreeCellRendererComponent(
066            tree, value, sel, expanded, leaf, row, hasFocus);
067
068        invalidFlag = isInvalid(tree, value, row);
069
070        // Allow the layout mgr to calculate the pref size of renderer.
071        this.setPreferredSize(null);
072        if (value instanceof MondrianGuiDef.Cube) {
073            setText(invalidFlag, ((MondrianGuiDef.Cube) value).name);
074            super.setIcon(
075                new ImageIcon(
076                    myClassLoader.getResource(
077                        workbench
078                            .getResourceConverter().getGUIReference("cube"))));
079        } else if (value instanceof MondrianGuiDef.Column) {
080            setText(invalidFlag, ((MondrianGuiDef.Column) value).name);
081        } else if (value instanceof MondrianGuiDef.Dimension) {
082            super.setIcon(
083                new ImageIcon(
084                    myClassLoader.getResource(
085                        workbench.getResourceConverter().getGUIReference(
086                            "dimension"))));
087            setText(invalidFlag, ((MondrianGuiDef.CubeDimension) value).name);
088            // Do not remove this line.  This sets the preferred width of tree
089            // cell displaying dimension name.  This resolves the ambiguous
090            // problem of last char or last word truncated from dimension name
091            // in the tree cell.  This problem was there with only Dimension
092            // objects, while all other objects display their names without any
093            // truncation of characters. Therefore, we have to force the setting
094            // of preferred width to desired width so that characters do not
095            // truncate from dimension name.  Along with this the preferred size
096            // of other objects should be set to null, so that the layout mgr
097            // can calculate the preferred width in case of other objects.
098            this.setPreferredSize(
099                new java.awt.Dimension(
100                    this.getPreferredSize().width + 1,
101                    25));
102        } else if (value instanceof MondrianGuiDef.DimensionUsage) {
103            super.setIcon(
104                new ImageIcon(
105                    myClassLoader.getResource(
106                        workbench.getResourceConverter().getGUIReference(
107                            "dimensionUsage"))));
108            setText(invalidFlag, ((MondrianGuiDef.CubeDimension) value).name);
109        } else if (value instanceof MondrianGuiDef.KeyExpression) {
110            super.setIcon(
111                new ImageIcon(
112                    myClassLoader.getResource(
113                        workbench
114                            .getResourceConverter().getGUIReference("key"))));
115            setText(
116                workbench.getResourceConverter().getString(
117                    "common.keyExpression.title",
118                    "Key Expression"));
119        } else if (value instanceof MondrianGuiDef.NameExpression) {
120            super.setIcon(
121                new ImageIcon(
122                    myClassLoader.getResource(
123                        workbench
124                            .getResourceConverter().getGUIReference("name"))));
125            setText(
126                workbench.getResourceConverter().getString(
127                    "common.nameExpression.title",
128                    "Name Expression"));
129        } else if (value instanceof MondrianGuiDef.OrdinalExpression) {
130            super.setIcon(
131                new ImageIcon(
132                    myClassLoader.getResource(
133                        workbench.getResourceConverter().getGUIReference(
134                            "ordinal"))));
135            setText(
136                workbench.getResourceConverter().getString(
137                    "common.ordinalExpression.title",
138                    "Ordinal Expression"));
139        } else if (value instanceof MondrianGuiDef.CaptionExpression) {
140            super.setIcon(
141                new ImageIcon(
142                    myClassLoader.getResource(
143                        workbench
144                            .getResourceConverter().getGUIReference("name"))));
145            setText(
146                workbench.getResourceConverter().getString(
147                    "common.captionExpression.title",
148                    "Caption Expression"));
149        } else if (value instanceof MondrianGuiDef.ParentExpression) {
150            super.setIcon(
151                new ImageIcon(
152                    myClassLoader.getResource(
153                        workbench.getResourceConverter().getGUIReference(
154                            "parent"))));
155            setText(
156                workbench.getResourceConverter().getString(
157                    "common.parentExpression.title",
158                    "Parent Expression"));
159        } else if (value instanceof MondrianGuiDef.Expression) {
160            super.setIcon(
161                new ImageIcon(
162                    myClassLoader.getResource(
163                        workbench.getResourceConverter().getGUIReference(
164                            "expression"))));
165            setText(
166                workbench.getResourceConverter().getString(
167                    "common.expression.title",
168                    "Expression"));
169        } else if (value instanceof MondrianGuiDef.ExpressionView) {
170            super.setIcon(
171                new ImageIcon(
172                    myClassLoader.getResource(
173                        workbench.getResourceConverter().getGUIReference(
174                            "expression"))));
175            setText(
176                workbench.getResourceConverter().getString(
177                    "common.expressionView.title",
178                    "Expression View"));
179        } else if (value instanceof MondrianGuiDef.Hierarchy) {
180            String name = ((MondrianGuiDef.Hierarchy) value).name;
181
182            if (name == null || name.trim().length() == 0) {
183                setText(
184                    invalidFlag,
185                    workbench.getResourceConverter().getString(
186                        "common.hierarchy.default.name",
187                        "default"));
188            } else {
189                setText(invalidFlag, name);
190            }
191            super.setIcon(
192                new ImageIcon(
193                    myClassLoader.getResource(
194                        workbench.getResourceConverter().getGUIReference(
195                            "hierarchy"))));
196            this.setPreferredSize(
197                new java.awt.Dimension(
198                    this.getPreferredSize().width + 1,
199                    25));
200        } else if (value instanceof MondrianGuiDef.RelationOrJoin) {
201            TreePath tpath = tree.getPathForRow(row);
202            String prefix = "";
203            if (tpath != null) {
204                TreePath parentpath = tpath.getParentPath();
205                if (parentpath != null) {
206                    Object parent = parentpath.getLastPathComponent();
207                    if (parent instanceof MondrianGuiDef.Join) {
208                        int indexOfChild = tree.getModel().getIndexOfChild(
209                            parent, value);
210                        switch (indexOfChild) {
211                        case 0:
212                            prefix = workbench.getResourceConverter().getString(
213                                "common.left.title",
214                                "Left")
215                                     + " ";
216                            break;
217                        case 1:
218                            prefix = workbench.getResourceConverter().getString(
219                                "common.right.title",
220                                "Right")
221                                     + " ";
222                            break;
223                        }
224                    }
225                }
226            }
227            if (value instanceof MondrianGuiDef.Join) {
228                setText(
229                    workbench.getResourceConverter().getFormattedString(
230                        "schemaTreeCellRenderer.join.title",
231                        "{0}Join",
232                        prefix));
233                super.setIcon(
234                    new ImageIcon(
235                        myClassLoader.getResource(
236                            workbench.getResourceConverter().getGUIReference(
237                                "join"))));
238            } else if (value instanceof MondrianGuiDef.Table) {
239                // Set the table name to alias if present.
240                MondrianGuiDef.Table theTable = (MondrianGuiDef.Table) value;
241                String theName =
242                    (theTable.alias != null
243                     && theTable.alias.trim().length() > 0)
244                    ? theTable.alias
245                    : theTable.name;
246                setText(
247                    workbench.getResourceConverter().getFormattedString(
248                        "schemaTreeCellRenderer.table.title",
249                        "{0}Table: {1}",
250                        prefix.length() == 0
251                            ? ""
252                            : prefix + " : ",
253                        theName));
254                super.setIcon(
255                    new ImageIcon(
256                        myClassLoader.getResource(
257                            workbench.getResourceConverter().getGUIReference(
258                                "table"))));
259            } else if (value instanceof MondrianGuiDef.View) {
260                setText(
261                    workbench.getResourceConverter().getFormattedString(
262                        "schemaTreeCellRenderer.view.title",
263                        "View"));
264            }
265            // REVIEW: Need to deal with InlineTable here
266            this.getPreferredSize();
267            // Do not remove this
268            this.setPreferredSize(
269                new Dimension(
270                    this.getPreferredSize().width + 35,
271                    24));
272        } else if (value instanceof MondrianGuiDef.Level) {
273            setText(invalidFlag, ((MondrianGuiDef.Level) value).name);
274            super.setIcon(
275                new ImageIcon(
276                    myClassLoader.getResource(
277                        workbench
278                            .getResourceConverter().getGUIReference("level"))));
279            // See earlier comments about setPreferredSize.
280            this.setPreferredSize(
281                new java.awt.Dimension(
282                    this.getPreferredSize().width + 1,
283                    25)); //Do not remove this
284        } else if (value instanceof MondrianGuiDef.Measure) {
285            setText(invalidFlag, ((MondrianGuiDef.Measure) value).name);
286            super.setIcon(
287                new ImageIcon(
288                    myClassLoader.getResource(
289                        workbench.getResourceConverter().getGUIReference(
290                            "measure"))));
291        } else if (value instanceof MondrianGuiDef.Formula) {
292            setText(invalidFlag, ((MondrianGuiDef.Formula) value).getName());
293            super.setIcon(
294                new ImageIcon(
295                    myClassLoader.getResource(
296                        workbench.getResourceConverter().getGUIReference(
297                            "formula"))));
298        } else if (value instanceof MondrianGuiDef.MemberReaderParameter) {
299            setText(
300                invalidFlag,
301                ((MondrianGuiDef.MemberReaderParameter) value).name);
302        } else if (value instanceof MondrianGuiDef.Property) {
303            setText(invalidFlag, ((MondrianGuiDef.Property) value).name);
304            super.setIcon(
305                new ImageIcon(
306                    myClassLoader.getResource(
307                        workbench.getResourceConverter().getGUIReference(
308                            "property"))));
309        } else if (value instanceof MondrianGuiDef.Schema) {
310            setText(
311                invalidFlag, workbench.getResourceConverter().getString(
312                    "common.schema.title",
313                    "Schema"));
314            super.setIcon(
315                new ImageIcon(
316                    myClassLoader.getResource(
317                        workbench.getResourceConverter().getGUIReference(
318                            "schema"))));
319        } else if (value instanceof MondrianGuiDef.NamedSet) {
320            setText(invalidFlag, ((MondrianGuiDef.NamedSet) value).name);
321            super.setIcon(
322                new ImageIcon(
323                    myClassLoader.getResource(
324                        workbench.getResourceConverter().getGUIReference(
325                            "namedSet"))));
326        } else if (value instanceof MondrianGuiDef.CalculatedMember) {
327            setText(
328                invalidFlag, ((MondrianGuiDef.CalculatedMember) value).name);
329            super.setIcon(
330                new ImageIcon(
331                    myClassLoader.getResource(
332                        workbench.getResourceConverter().getGUIReference(
333                            "calculatedMember"))));
334        } else if (value instanceof MondrianGuiDef.CalculatedMemberProperty) {
335            setText(
336                invalidFlag,
337                ((MondrianGuiDef.CalculatedMemberProperty) value).name);
338            super.setIcon(
339                new ImageIcon(
340                    myClassLoader.getResource(
341                        workbench
342                            .getResourceConverter().getGUIReference("nopic"))));
343        } else if (value instanceof MondrianGuiDef.UserDefinedFunction) {
344            setText(
345                invalidFlag, ((MondrianGuiDef.UserDefinedFunction) value).name);
346            super.setIcon(
347                new ImageIcon(
348                    myClassLoader.getResource(
349                        workbench.getResourceConverter().getGUIReference(
350                            "userDefinedFunction"))));
351        } else if (value instanceof MondrianGuiDef.MemberFormatter) {
352            setText(
353                invalidFlag, workbench.getResourceConverter().getString(
354                    "common.memberFormatter.title",
355                    "Member Formatter"));
356            super.setIcon(
357                new ImageIcon(
358                    myClassLoader.getResource(
359                        workbench.getResourceConverter().getGUIReference(
360                            "format"))));
361        } else if (value instanceof MondrianGuiDef.CellFormatter) {
362            setText(
363                invalidFlag, workbench.getResourceConverter().getString(
364                    "common.cellFormatter.title",
365                    "Cell Formatter"));
366            super.setIcon(
367                new ImageIcon(
368                    myClassLoader.getResource(
369                        workbench.getResourceConverter().getGUIReference(
370                            "format"))));
371        } else if (value instanceof MondrianGuiDef.PropertyFormatter) {
372            setText(
373                invalidFlag, workbench.getResourceConverter().getString(
374                    "common.propertyFormatter.title",
375                    "Property Formatter"));
376            super.setIcon(
377                new ImageIcon(
378                    myClassLoader.getResource(
379                        workbench.getResourceConverter().getGUIReference(
380                            "format"))));
381        } else if (value instanceof MondrianGuiDef.Script) {
382            setText(
383                invalidFlag, workbench.getResourceConverter().getString(
384                    "common.script.title",
385                    "Script"));
386            super.setIcon(
387                new ImageIcon(
388                    myClassLoader.getResource(
389                        workbench.getResourceConverter().getGUIReference(
390                            "script"))));
391        } else if (value instanceof MondrianGuiDef.Role) {
392            setText(invalidFlag, ((MondrianGuiDef.Role) value).name);
393            super.setIcon(
394                new ImageIcon(
395                    myClassLoader.getResource(
396                        workbench
397                            .getResourceConverter().getGUIReference("role"))));
398        } else if (value instanceof MondrianGuiDef.Parameter) {
399            setText(invalidFlag, ((MondrianGuiDef.Parameter) value).name);
400            super.setIcon(
401                new ImageIcon(
402                    myClassLoader.getResource(
403                        workbench.getResourceConverter().getGUIReference(
404                            "parameter"))));
405        } else if (value instanceof MondrianGuiDef.SchemaGrant) {
406            setText(
407                invalidFlag, workbench.getResourceConverter().getString(
408                    "common.schemaGrant.title",
409                    "Schema Grant"));
410            super.setIcon(
411                new ImageIcon(
412                    myClassLoader.getResource(
413                        workbench.getResourceConverter().getGUIReference(
414                            "schemaGrant"))));
415        } else if (value instanceof MondrianGuiDef.CubeGrant) {
416            setText(
417                invalidFlag, workbench.getResourceConverter().getString(
418                    "common.cubeGrant.title",
419                    "Cube Grant"));
420            super.setIcon(
421                new ImageIcon(
422                    myClassLoader.getResource(
423                        workbench.getResourceConverter().getGUIReference(
424                            "cubeGrant"))));
425        } else if (value instanceof MondrianGuiDef.DimensionGrant) {
426            setText(
427                invalidFlag, workbench.getResourceConverter().getString(
428                    "common.dimensionGrant.title",
429                    "Dimension Grant"));
430            super.setIcon(
431                new ImageIcon(
432                    myClassLoader.getResource(
433                        workbench.getResourceConverter().getGUIReference(
434                            "dimensionGrant"))));
435        } else if (value instanceof MondrianGuiDef.HierarchyGrant) {
436            setText(
437                invalidFlag, workbench.getResourceConverter().getString(
438                    "common.hierarchyGrant.title",
439                    "Hierarchy Grant"));
440            super.setIcon(
441                new ImageIcon(
442                    myClassLoader.getResource(
443                        workbench.getResourceConverter().getGUIReference(
444                            "hierarchyGrant"))));
445        } else if (value instanceof MondrianGuiDef.MemberGrant) {
446            setText(
447                invalidFlag, workbench.getResourceConverter().getString(
448                    "common.memberGrant.title",
449                    "Member Grant"));
450            super.setIcon(
451                new ImageIcon(
452                    myClassLoader.getResource(
453                        workbench.getResourceConverter().getGUIReference(
454                            "memberGrant"))));
455        } else if (value instanceof MondrianGuiDef.Annotations) {
456            setText(
457                invalidFlag, workbench.getResourceConverter().getString(
458                    "common.annotations.title",
459                    "Annotations"));
460            super.setIcon(
461                new ImageIcon(
462                    myClassLoader.getResource(
463                        workbench.getResourceConverter().getGUIReference(
464                            "annotations"))));
465        } else if (value instanceof MondrianGuiDef.Annotation) {
466            setText(
467                invalidFlag, ((MondrianGuiDef.Annotation)value).name);
468            super.setIcon(
469                new ImageIcon(
470                    myClassLoader.getResource(
471                        workbench.getResourceConverter().getGUIReference(
472                            "annotation"))));
473        } else if (value instanceof MondrianGuiDef.SQL) {
474            setText(invalidFlag, ((MondrianGuiDef.SQL) value).dialect);
475            super.setIcon(
476                new ImageIcon(
477                    myClassLoader.getResource(
478                        workbench
479                            .getResourceConverter().getGUIReference("sql"))));
480        } else if (value instanceof MondrianGuiDef.View) {
481            setText(
482                workbench.getResourceConverter().getString(
483                    "common.view.title",
484                    "View"));
485        } else if (value instanceof MondrianGuiDef.VirtualCube) {
486            setText(invalidFlag, ((MondrianGuiDef.VirtualCube) value).name);
487            super.setIcon(
488                new ImageIcon(
489                    myClassLoader.getResource(
490                        workbench.getResourceConverter().getGUIReference(
491                            "virtualCube"))));
492        } else if (value instanceof MondrianGuiDef.VirtualCubeDimension) {
493            setText(
494                invalidFlag,
495                ((MondrianGuiDef.VirtualCubeDimension) value).name);
496            super.setIcon(
497                new ImageIcon(
498                    myClassLoader.getResource(
499                        workbench.getResourceConverter().getGUIReference(
500                            "virtualCubeDimension"))));
501        } else if (value instanceof MondrianGuiDef.VirtualCubeMeasure) {
502            setText(
503                invalidFlag, ((MondrianGuiDef.VirtualCubeMeasure) value).name);
504            super.setIcon(
505                new ImageIcon(
506                    myClassLoader.getResource(
507                        workbench.getResourceConverter().getGUIReference(
508                            "virtualCubeMeasure"))));
509        } else if (value instanceof MondrianGuiDef.AggName) {
510            setText(
511                invalidFlag, workbench.getResourceConverter().getString(
512                    "common.aggName.title",
513                    "Aggregate Name"));
514            super.setIcon(
515                new ImageIcon(
516                    myClassLoader.getResource(
517                        workbench.getResourceConverter().getGUIReference(
518                            "aggTable"))));
519        } else if (value instanceof MondrianGuiDef.AggForeignKey) {
520            setText(
521                invalidFlag, workbench.getResourceConverter().getString(
522                    "common.aggForeignKey.title",
523                    "Aggregate Foreign Key"));
524            super.setIcon(
525                new ImageIcon(
526                    myClassLoader.getResource(
527                        workbench.getResourceConverter().getGUIReference(
528                            "aggForeignKey"))));
529        } else if (value instanceof MondrianGuiDef.AggIgnoreColumn) {
530            setText(
531                invalidFlag, workbench.getResourceConverter().getString(
532                    "common.aggIgnoreColumn.title",
533                    "Aggregate Ignore Column"));
534            super.setIcon(
535                new ImageIcon(
536                    myClassLoader.getResource(
537                        workbench.getResourceConverter().getGUIReference(
538                            "aggIgnoreColumn"))));
539        } else if (value instanceof MondrianGuiDef.AggLevel) {
540            setText(
541                invalidFlag, workbench.getResourceConverter().getString(
542                    "common.aggLevel.title", "Aggregate Level"));
543            super.setIcon(
544                new ImageIcon(
545                    myClassLoader.getResource(
546                        workbench.getResourceConverter().getGUIReference(
547                            "aggLevel"))));
548        } else if (value instanceof MondrianGuiDef.AggMeasure) {
549            setText(
550                invalidFlag, workbench.getResourceConverter().getString(
551                    "common.aggMeasure.title",
552                    "Aggregate Measure"));
553            super.setIcon(
554                new ImageIcon(
555                    myClassLoader.getResource(
556                        workbench.getResourceConverter().getGUIReference(
557                            "aggMeasure"))));
558        } else if (value instanceof MondrianGuiDef.AggPattern) {
559            setText(
560                invalidFlag, workbench.getResourceConverter().getString(
561                    "common.aggPattern.title",
562                    "Aggregate Pattern"));
563            super.setIcon(
564                new ImageIcon(
565                    myClassLoader.getResource(
566                        workbench.getResourceConverter().getGUIReference(
567                            "aggPattern"))));
568        } else if (value instanceof MondrianGuiDef.AggExclude) {
569            setText(
570                invalidFlag, workbench.getResourceConverter().getString(
571                    "common.aggExclude.title",
572                    "Aggregate Exclude"));
573            super.setIcon(
574                new ImageIcon(
575                    myClassLoader.getResource(
576                        workbench.getResourceConverter().getGUIReference(
577                            "aggExclude"))));
578        } else if (value instanceof MondrianGuiDef.Closure) {
579            setText(
580                invalidFlag, workbench.getResourceConverter().getString(
581                    "common.closure.title",
582                    "Closure"));
583            super.setIcon(
584                new ImageIcon(
585                    myClassLoader.getResource(
586                        workbench.getResourceConverter().getGUIReference(
587                            "closure"))));
588        } else if (value instanceof ElementDef) {
589            setText(((ElementDef) value).getName());
590        } else {
591            super.setText("");
592        }
593
594        return this;
595    }
596
597    // called from external methods
598    public String invalid(JTree tree, TreePath tpath, Object value) {
599        return this.invalid(tree, tpath, value, null, null, null, null);
600    }
601
602    public String invalid(
603        JTree tree,
604        TreePath tpath,
605        Object value,
606        MondrianGuiDef.Cube cube,
607        MondrianGuiDef.Dimension parentDimension,
608        MondrianGuiDef.Hierarchy parentHierarchy,
609        MondrianGuiDef.Level parentLevel)
610    {
611        return ValidationUtils.invalid(
612            new WorkbenchMessages(workbench.getResourceConverter()),
613            new WorkbenchJdbcValidator(jdbcMetaData),
614            new WorkbenchTreeModel((SchemaTreeModel) tree.getModel()),
615            new WorkbenchTreeModelPath(tpath),
616            value,
617            cube,
618            parentDimension,
619            parentHierarchy,
620            parentLevel,
621            jdbcMetaData.getRequireSchema());
622    }
623
624    private boolean isInvalid(JTree tree, Object value, int row) {
625        // getPathForRow(row) returns null for new objects added to tree in the
626        // first run of rendering. Check for null before calling methods on
627        // Treepath returned.
628        return invalid(tree, tree.getPathForRow(row), value) != null;
629    }
630
631    public void setText(boolean invalidFlag, String myText) {
632        if (invalidFlag) {
633            myText = "<html><FONT COLOR=RED><b>x</b></FONT><FONT COLOR="
634                     + getForeground().hashCode()
635                     + ">"
636                     + myText
637                     + "</FONT></html>";
638        }
639        setText(myText);
640    }
641
642    /**
643     * Called from {@link SchemaExplorer#resetMetaData(JdbcMetaData)}. A call to
644     * {@link #updateUI} should be made on the owning SchemaFrame to reflect the
645     * use of the JdbcMetaData being set.
646     *
647     * @param jdbcMetaData Meta data
648     */
649    public void setMetaData(JdbcMetaData jdbcMetaData) {
650        this.jdbcMetaData = jdbcMetaData;
651    }
652}
653
654// End SchemaTreeCellRenderer.java