001    /*
002     @license.text@
003      */
004    package biz.hammurapi.swing;
005    
006    import java.lang.reflect.Field;
007    import java.lang.reflect.Method;
008    import java.lang.reflect.Modifier;
009    import java.util.ArrayList;
010    import java.util.List;
011    import java.util.logging.Level;
012    import java.util.logging.Logger;
013    
014    import javax.swing.table.DefaultTableModel;
015    import javax.swing.table.TableModel;
016    import javax.swing.tree.TreeNode;
017    
018    import biz.hammurapi.convert.Converter;
019    import biz.hammurapi.convert.ConvertingService;
020    
021    /**
022     * @author Pavel Vlasov
023     *
024     * @version $Revision: 1.1 $
025     */
026    public class BeanVisualizer {
027            
028            private static final Logger logger = Logger.getLogger(BeanVisualizer.class.getName());
029            
030            private static boolean isPrimitive(Class klass) {
031                    return String.class.equals(klass) 
032                    || Number.class.isAssignableFrom(klass) 
033                    || Character.class.equals(klass)
034                    || Boolean.class.equals(klass)
035                    || double.class.equals(klass) 
036                    || float.class.equals(klass) 
037                    || long.class.equals(klass) 
038                    || int.class.equals(klass) 
039                    || short.class.equals(klass) 
040                    || byte.class.equals(klass) 
041                    || char.class.equals(klass) 
042                    || boolean.class.equals(klass); 
043            }
044            
045            public Visualizable convert(final Object obj, Converter master) {
046                    return new Visualizable() {
047    
048                            public TreeNode toTreeNode(TreeNode parent, String title) {
049                                    return new LazyTreeNodeTableVisualizable(parent, title+" ["+obj.getClass().getName()+"] "+obj) {
050    
051                                            protected List loadChildren() {
052                                                    List ret = new ArrayList();
053                                                Class beanClass=obj.getClass();
054                                                Method[] methods = beanClass.getMethods();
055                                                for (int i=0; i<methods.length; i++) {
056                                                    // getXXX() methods. Object.getClass() is not included.
057                                                    if (!(methods[i].getDeclaringClass().equals(Object.class)) 
058                                                                    && methods[i].getName().startsWith("get") 
059                                                                    && methods[i].getParameterTypes().length==0 
060                                                                    && !Modifier.isStatic(methods[i].getModifiers())
061                                                                    && methods[i].isSynthetic()
062                                                                    && !isPrimitive(methods[i].getReturnType())) {
063                                                            try {
064                                                                            Object value=methods[i].invoke(obj, null);
065                                                                            Visualizable vs = (Visualizable) ConvertingService.convert(value, Visualizable.class);
066                                                                            ret.add(vs.toTreeNode(this, methods[i].getName().substring(3)+" ("+methods[i].getReturnType().getName()+")"));
067                                                                    } catch (Exception e) {
068                                                                            logger.log(Level.WARNING, "Could not retrieve value from "+methods[i], e);                                                              
069                                                                    }
070                                                    }                                                                                               
071                                                }
072                                                
073                                                Field[] fields = beanClass.getFields();
074                                                for (int i=0; i<fields.length; i++) {
075                                                    try {
076                                                            if (!isPrimitive(fields[i].getType()) 
077                                                                            && !Modifier.isStatic(methods[i].getModifiers())
078                                                                            && !fields[i].isSynthetic()) {
079                                                                            Object value=fields[i].get(obj);
080                                                                            Visualizable vs = (Visualizable) ConvertingService.convert(value, Visualizable.class);
081                                                                            ret.add(vs.toTreeNode(this, fields[i].getName()+" ("+fields[i].getType().getName()+")"));
082                                                            }
083                                                            } catch (Exception e) {
084                                                                    logger.log(Level.WARNING, "Could not retrieve value from "+methods[i], e);                                                              
085                                                            }
086                                                }
087                                                    
088                                                    return ret;
089                                            }
090    
091                                            public TableModel toTable() {
092                                                    int rowCount=2;
093                                                    DefaultTableModel tm=new DefaultTableModel(rowCount,4);                 
094                                                    tm.setColumnIdentifiers(new String[] {"Property", "Type", "Value"});
095                                                    
096                                                Class beanClass=obj.getClass();
097                                                
098                                                    tm.setValueAt("this", 0, 0);
099                                                    tm.setValueAt(beanClass.getName(), 0, 1);
100                                                    tm.setValueAt(obj, 0, 2);
101                                                    
102                                                    tm.setValueAt("Hash code", 1, 0);
103                                                    tm.setValueAt("int", 1, 1);
104                                                    tm.setValueAt(Integer.toString(obj.hashCode(), Character.MAX_RADIX), 1, 2);
105                                                    
106                                                Method[] methods = beanClass.getMethods();
107                                                for (int i=0; i<methods.length; i++) {
108                                                    // getXXX() methods. Object.getClass() is not included.
109                                                    if (!(methods[i].getDeclaringClass().equals(Object.class)) 
110                                                                    && methods[i].getName().startsWith("get") 
111                                                                    && methods[i].getParameterTypes().length==0 
112                                                                    && !Modifier.isStatic(methods[i].getModifiers())
113                                                                    && methods[i].isSynthetic()
114                                                                    && isPrimitive(methods[i].getReturnType())) {
115                                                            try {
116                                                                            Object value=methods[i].invoke(obj, null);
117                                                                            tm.setRowCount(++rowCount);
118                                                                            int idx = rowCount-1;
119                                                                            tm.setValueAt(methods[i].getName().substring(3), idx, 0);
120                                                                            if (value==null) {
121                                                                                    tm.setValueAt("(null)", idx, 1);
122                                                                                    tm.setValueAt("(null)", idx, 2);
123                                                                            } else {
124                                                                                    tm.setValueAt(value.getClass().getName(), idx, 1);
125                                                                                    tm.setValueAt(value, idx, 2);
126                                                                            }
127                                                                    } catch (Exception e) {
128                                                                            logger.log(Level.WARNING, "Could not retrieve value from "+methods[i], e);                                                              
129                                                                    }
130                                                    }                                                                                               
131                                                }
132                                                
133                                                Field[] fields = beanClass.getFields();
134                                                for (int i=0; i<fields.length; i++) {
135                                                    try {
136                                                            if (isPrimitive(fields[i].getType()) 
137                                                                            && !Modifier.isStatic(methods[i].getModifiers()) 
138                                                                            && !fields[i].isSynthetic()) {
139                                                                            Object value=fields[i].get(obj);                                                                
140                                                                            tm.setRowCount(++rowCount);
141                                                                            int idx = rowCount-1;
142                                                                            tm.setValueAt(fields[i].getName(), idx, 0);
143                                                                            if (value==null) {
144                                                                                    tm.setValueAt("(null)", idx, 1);
145                                                                                    tm.setValueAt("(null)", idx, 2);
146                                                                            } else {
147                                                                                    tm.setValueAt(value.getClass().getName(), idx, 1);
148                                                                                    tm.setValueAt(value, idx, 2);
149                                                                            }
150                                                            }
151                                                            } catch (Exception e) {
152                                                                    logger.log(Level.WARNING, "Could not retrieve value from "+methods[i], e);                                                              
153                                                            }
154                                                }
155                                                
156                                                    return tm;
157                                            }
158                                            
159                                    };
160                            }
161                            
162                    };
163            }
164            
165    }