001    /*
002    // $Id: //open/mondrian/src/main/mondrian/gui/PropertyTableModel.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.lang.reflect.Field;
014    import java.util.*;
015    
016    import org.apache.log4j.Logger;
017    
018    /**
019     *
020     * @author  sean
021     * @version $Id: //open/mondrian/src/main/mondrian/gui/PropertyTableModel.java#14 $
022     */
023    public class PropertyTableModel extends javax.swing.table.AbstractTableModel {
024    
025        private static final Logger LOGGER = Logger.getLogger(PropertyTableModel.class);
026    
027        private Object parentTarget; // parent of target
028        private String factTable;   // selected fact table
029        private String factTableSchema;   // selected fact table schema
030        private ArrayList names; // List of names  for this object's siblings already existing in parent'
031        private String errorMsg = null; // error msg when property value could not be set.
032    
033        String[] propertyNames;
034        Object target;
035        Workbench workbench;
036    
037        public PropertyTableModel(Workbench wb, Object t, String[] pNames) {
038            super();
039            workbench = wb;
040            propertyNames = pNames;
041            target = t;
042        }
043    
044        public String getColumnName(int i) {
045            if (i == 0) {
046                return workbench.getResourceConverter().getString("propertyTableModel.attribute","Attribute");
047            } else if (i == 1) {
048                return workbench.getResourceConverter().getString("propertyTableModel.value","Value");
049            }
050    
051            return workbench.getResourceConverter().getString("propertyTableModel.unknown","?");
052        }
053    
054        // get property name for given row no.
055        public String getRowName(int i) {
056            String pName = propertyNames[i];
057            int j=-1;
058            if ((j = pName.indexOf('|')) != -1) {  //"|"
059                return pName.substring(0,j).trim();
060            } else {
061                return propertyNames[i];   }
062        }
063    
064        public boolean isCellEditable(int row, int col) {
065            if (col == 1) {
066                Object cellObj = getValueAt(row, col);
067                if (cellObj instanceof MondrianGuiDef.Join) {
068                    return false;
069                } else {
070                    return true;
071                }
072            }
073    
074            return false;
075        }
076    
077        /** Returns the number of columns in the model. A
078         * <code>JTable</code> uses this method to determine how many columns it
079         * should create and display by default.
080         *
081         * @return the number of columns in the model
082         * @see #getRowCount
083         *
084         */
085        public int getColumnCount() {
086            return 2; //that's 'Property' and 'Value'
087        }
088    
089        /** Returns the number of rows in the model. A
090         * <code>JTable</code> uses this method to determine how many rows it
091         * should display.  This method should be quick, as it
092         * is called frequently during rendering.
093         *
094         * @return the number of rows in the model
095         * @see #getColumnCount
096         *
097         */
098        public int getRowCount() {
099            return propertyNames.length;
100        }
101    
102        /** Returns the value for the cell at <code>columnIndex</code> and
103         * <code>rowIndex</code>.
104         *
105         * @param   rowIndex    the row whose value is to be queried
106         * @param   columnIndex     the column whose value is to be queried
107         * @return  the value Object at the specified cell
108         *
109         */
110        public Object getValueAt(int rowIndex, int columnIndex) {
111            if (columnIndex == 0) {
112                return propertyNames[rowIndex];
113            } else {
114                try {
115                    String pName = propertyNames[rowIndex];
116                    if ((pName.indexOf('|')) != -1) {   //"formula | formulaElement.cdata"
117                        /* This is for special cases where more than one field refers to the same value.
118                         * For eg. calculated memeber's formula and formulaelement.cdata refers to the same formula string.
119                         * These cases arise to handle xml standards where an attribute can also appear as an xml tag.
120                         */
121                        Object obj = null;
122                        String[] pNames = pName.split("\\|",0); // split field names on | to form an array of property names strings that are optional.
123                        for (int j = 0; j < pNames.length; j++) {
124                            if ((pNames[j].indexOf('.')) != -1) {
125                                String[] pNamesField = pNames[j].trim().split("\\.",0); // split string on . to form an array of property name within the property name.
126                                if (pNamesField.length > 1) {
127                                    Field f = target.getClass().getField(pNamesField[0].trim());
128                                    obj = f.get(target);
129                                    if (obj != null) {
130                                        Field f2 = obj.getClass().getField(pNamesField[1].trim());
131                                        Object obj2 = f2.get(obj);
132                                        return obj2;
133                                    }
134                                }
135                                return null;
136                            } else {
137                                Field f = target.getClass().getField(pNames[j].trim());
138                                obj = f.get(target);
139                                if (obj != null) {
140                                    return obj;
141                                }
142                            }
143                        }
144                        return obj;
145                    } else {
146                        // default case where one field refers to one value.
147                        Field f = target.getClass().getField(propertyNames[rowIndex]);
148    
149                        Object obj = f.get(target);
150                        return obj;
151                    }
152                } catch (Exception ex) {
153                    LOGGER.error("getValueAt(row, index)", ex);
154                    return "#ERROR";
155                }
156            }
157        }
158    
159        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
160            setErrorMsg(null);
161            try {
162                String pName = propertyNames[rowIndex];
163                int i=-1;
164                if ((i = pName.indexOf('|')) != -1) {   //"formula | formulaElement.cdata"
165                    Field f = target.getClass().getField(propertyNames[rowIndex].substring(0,i).trim());    // save value in the first field name
166                    f.set(target,aValue);
167                    // delete the value from second and remaining field names
168                    String[] pNames = pName.split("\\|",0); // split field names on | to form an array of property names strings that are optional.
169                    for (int j = 1; j < pNames.length; j++) {
170                        String[] pNamesField = pNames[j].trim().split("\\.",0); // split string on . to form an array of property name within the property name.
171                        Field f2 = target.getClass().getField(pNamesField[0].trim());
172                        f2.set(target,null);
173                    }
174    
175                } else if ((target instanceof MondrianGuiDef.Level) && (pName.equals("ordinalExp")))  {
176                    ((MondrianGuiDef.Level) target).ordinalExp.expressions[0] = (MondrianGuiDef.SQL) aValue;
177                        /*
178                        Field f = target.getClass().getField(propertyNames[rowIndex]);
179                        f.set(((MondrianGuiDef.Level) target).ordinalExp.expressions[0], aValue);
180                         */
181                } else if ((target instanceof MondrianGuiDef.Table && pName.equals("name")) ||
182                        (target instanceof MondrianGuiDef.Hierarchy && pName.equals("primaryKeyTable")) ||
183                        (target instanceof MondrianGuiDef.Level && pName.equals("table")))  {
184                    // updating all table values
185                    if (aValue != null) {   // split and save only if value exists
186                        String[] aValues = ((String) aValue).split("->");
187                        if (aValues.length == 2)  {
188                            if (target instanceof MondrianGuiDef.Table) {
189                                ((MondrianGuiDef.Table) target).name = aValues[1];
190                                ((MondrianGuiDef.Table) target).schema = aValues[0];
191                                fireTableDataChanged(); // to refresh the value in schema field also alongwith table name
192                            } else {
193                                Field f = target.getClass().getField(propertyNames[rowIndex]);
194                                f.set(target,aValues[1]);
195                            }
196                        } else {
197                            Field f = target.getClass().getField(propertyNames[rowIndex]);
198                            f.set(target,aValue);
199                        }
200                    }
201    
202                } else if ((target instanceof MondrianGuiDef.Dimension && pName.equals("foreignKey")) ||
203                        (target instanceof MondrianGuiDef.DimensionUsage && pName.equals("foreignKey")) ||
204                        (target instanceof MondrianGuiDef.Measure && pName.equals("column")) ||
205                        (target instanceof MondrianGuiDef.Hierarchy && pName.equals("primaryKey")) ||
206                        (target instanceof MondrianGuiDef.Level && pName.equals("column")) ||
207                        (target instanceof MondrianGuiDef.Level && pName.equals("nameColumn")) ||
208                        (target instanceof MondrianGuiDef.Level && pName.equals("ordinalColumn")) ||
209                        (target instanceof MondrianGuiDef.Level && pName.equals("parentColumn")) ||
210                        (target instanceof MondrianGuiDef.Level && pName.equals("captionColumn")) ||
211                        (target instanceof MondrianGuiDef.Closure && pName.equals("parentColumn")) ||
212                        (target instanceof MondrianGuiDef.Closure && pName.equals("childColumn")) ||
213                        (target instanceof MondrianGuiDef.Property && pName.equals("column")))  {
214                    // updating all column values
215                    if (aValue != null) {   // split and save only if value exists
216                        String[] aValues = ((String) aValue).split("->");
217                        Field f = target.getClass().getField(propertyNames[rowIndex]);
218                        f.set(target, aValues[aValues.length - 1]);    // save the last value in the array from split
219                    }
220    
221                } else {
222                    if (propertyNames[rowIndex].equals("name")
223                    && (! (target instanceof MondrianGuiDef.Table))
224                    && (! aValue.equals(target.getClass().getField(propertyNames[rowIndex]).get(target)))
225                    && duplicateName(aValue)) {
226                        setErrorMsg(workbench.getResourceConverter().getFormattedString("propertyTableModel.duplicateValue.error",
227                                "Error setting name property. {0} already exists",
228                                    new String[] { aValue.toString() }));
229                    } else {
230                        Field f = target.getClass().getField(propertyNames[rowIndex]);
231                        f.set(target,aValue);
232                    }
233                }
234            } catch (Exception ex) {
235                LOGGER.error("setValueAt(aValue, row, index)", ex);
236            }
237        }
238    
239        public Object getValue() {
240            return target;
241        }
242    
243        public Object getParentTarget() {
244            return parentTarget;
245        }
246    
247        public void setParentTarget(Object parentTarget) {
248            this.parentTarget = parentTarget;
249        }
250    
251        public String getFactTable() {
252            return factTable;
253        }
254    
255        public void setFactTable(String factTable) {
256            this.factTable = factTable;
257        }
258    
259        public String getFactTableSchema() {
260            return factTableSchema;
261        }
262    
263        public void setFactTableSchema(String factTableSchema) {
264            this.factTableSchema = factTableSchema;
265        }
266    
267        private boolean duplicateName(Object aValue) {
268            return (names != null && names.contains(aValue));
269        }
270    
271        public ArrayList getNames() {
272            return names;
273        }
274    
275        public void setNames(ArrayList names) {
276            this.names = names;
277        }
278    
279        public String getErrorMsg() {
280            return errorMsg;
281        }
282    
283        public void setErrorMsg(String errorMsg) {
284            this.errorMsg = errorMsg;
285        }
286    }
287    
288    // End PropertyTableModel.java