001 /* 002 * mesopotamia @mesopotamia.version@ 003 * Multilingual parser and repository. 004 * Copyright (C) 2005 Hammurapi Group 005 * 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2 of the License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software 018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 019 * 020 * URL: http://http://www.hammurapi.biz 021 * e-Mail: support@hammurapi.biz 022 */ 023 package org.mesopotamia.util; 024 025 import java.lang.reflect.InvocationTargetException; 026 import java.lang.reflect.Method; 027 import java.lang.reflect.Modifier; 028 import java.util.ArrayList; 029 import java.util.Collection; 030 import java.util.Collections; 031 import java.util.Comparator; 032 import java.util.Iterator; 033 import java.util.List; 034 035 import javax.swing.table.DefaultTableModel; 036 import javax.swing.table.TableModel; 037 import javax.swing.tree.TreeNode; 038 039 import org.mesopotamia.LanguageElement; 040 import org.mesopotamia.MesopotamiaNode; 041 import org.mesopotamia.Scan; 042 import org.mesopotamia.SourceUnit; 043 import org.mesopotamia.SyntaxTree; 044 045 import biz.hammurapi.convert.Converter; 046 import biz.hammurapi.swing.LazyTreeNode; 047 import biz.hammurapi.swing.LazyTreeNodeTableVisualizable; 048 import biz.hammurapi.swing.Visualizable; 049 050 051 /** 052 * @author Pavel Vlasov 053 * 054 * @version $Revision: 1.1 $ 055 */ 056 public class MesopotamiaVisualizer { 057 058 /** 059 * Invokes method and returns non-null value if the method result shall be mounted to the tree. 060 * @param method 061 * @return true if return value shall be mounted to tree, false if it shall be displayed in the table. 062 * @throws InvocationTargetException 063 * @throws IllegalAccessException 064 * @throws 065 */ 066 private Object getNode(Method method, Object obj) throws IllegalAccessException, InvocationTargetException { 067 if (LanguageElement.class.isAssignableFrom(method.getDeclaringClass())) { 068 if (((LanguageElement) obj).showInTree(method)) { 069 Object returnValue = method.invoke(obj); 070 if ((LanguageElement.class.isInstance(returnValue) || List.class.isInstance(returnValue))) { 071 return returnValue; 072 } 073 } 074 } else if (SourceUnit.class.isAssignableFrom(method.getDeclaringClass())) { 075 if ("getLanguageElements".equals(method.getName()) || "getSyntaxTree".equals(method.getName())) { 076 return method.invoke(obj); 077 } 078 } else if (Scan.class.isAssignableFrom(method.getDeclaringClass())) { 079 if ("getSourceUnits".equals(method.getName())) { 080 return method.invoke(obj); 081 } 082 } else if (SyntaxTree.class.isAssignableFrom(method.getDeclaringClass())) { 083 if ("getRoots".equals(method.getName())) { 084 return method.invoke(obj); 085 } 086 } else if (MesopotamiaNode.class.isAssignableFrom(method.getDeclaringClass())) { 087 if ("getChildren".equals(method.getName())) { 088 return method.invoke(obj); 089 } 090 } 091 return null; 092 } 093 094 public Visualizable convert(final LanguageElement le, final Converter master) { 095 return new Visualizable() { 096 097 public TreeNode toTreeNode(TreeNode parent, String title) { 098 return _toTreeNode(parent, title, le, master); 099 } 100 101 }; 102 } 103 104 public Visualizable convert(final Scan sc, final Converter master) { 105 return new Visualizable() { 106 107 public TreeNode toTreeNode(TreeNode parent, String title) { 108 return _toTreeNode(parent, title, sc, master); 109 } 110 111 }; 112 } 113 114 public Visualizable convert(final SourceUnit su, final Converter master) { 115 return new Visualizable() { 116 117 public TreeNode toTreeNode(TreeNode parent, String title) { 118 return _toTreeNode(parent, title, su, master); 119 } 120 121 }; 122 } 123 124 public Visualizable convert(final SyntaxTree st, final Converter master) { 125 return new Visualizable() { 126 127 public TreeNode toTreeNode(TreeNode parent, String title) { 128 return _toTreeNode(parent, title, st, master); 129 } 130 131 }; 132 } 133 134 public Visualizable convert(final MesopotamiaNode mn, final Converter master) { 135 return new Visualizable() { 136 137 public TreeNode toTreeNode(TreeNode parent, String title) { 138 return _toTreeNode(parent, title, mn, master); 139 } 140 141 }; 142 } 143 144 private TreeNode _toTreeNode(final TreeNode parent, final String title, final Object obj, final Converter master) { 145 return new LazyTreeNodeTableVisualizable(parent, title) { 146 147 public String toString() { 148 if (title!=null && title.trim().length()>0) { 149 return title; 150 } 151 152 String ret = obj.getClass().getName(); 153 int idx = ret.lastIndexOf("."); 154 return idx==-1 ? ret : ret.substring(idx+1); 155 } 156 157 @Override 158 protected List<TreeNode> loadChildren() { 159 List<TreeNode> ret = new ArrayList<TreeNode>(); 160 if (obj instanceof SyntaxTree) { 161 SyntaxTree st = (SyntaxTree) obj; 162 Iterator<MesopotamiaNode> it = st.getRoots().iterator(); 163 while (it.hasNext()) { 164 MesopotamiaNode mn = it.next(); 165 Visualizable vs = (Visualizable) master.convert(mn, Visualizable.class, null); 166 ret.add(vs.toTreeNode(this, mn.getTypeName() + " " + (mn.getText()==null ? "" : mn.getText()))); 167 } 168 } else if (obj instanceof MesopotamiaNode) { 169 MesopotamiaNode mNode = (MesopotamiaNode) obj; 170 Iterator<MesopotamiaNode> it = mNode.getChildren().iterator(); 171 while (it.hasNext()) { 172 MesopotamiaNode mn = it.next(); 173 Visualizable vs = (Visualizable) master.convert(mn, Visualizable.class, null); 174 ret.add(vs.toTreeNode(this, mn.getTypeName() + " " + (mn.getText()==null ? "" : mn.getText()))); 175 } 176 } else { 177 if (obj instanceof LanguageElement) { 178 MesopotamiaNode mNode = ((LanguageElement) obj).getNode(); 179 final Collection<MesopotamiaNode> nChildren = mNode.getChildren(); 180 if (!nChildren.isEmpty()) { 181 ret.add(new LazyTreeNode(this, "Syntax tree") { 182 183 @Override 184 protected List<TreeNode> loadChildren() { 185 List<TreeNode> ret = new ArrayList<TreeNode>(); 186 Iterator<MesopotamiaNode> it = nChildren.iterator(); 187 while (it.hasNext()) { 188 MesopotamiaNode mn = it.next(); 189 Visualizable vs = (Visualizable) master.convert(mn, Visualizable.class, null); 190 ret.add(vs.toTreeNode(this, mn.getTypeName() + " " + (mn.getText()==null ? "" : mn.getText()))); 191 } 192 return ret; 193 } 194 195 }); 196 197 } 198 } 199 200 Method[] methods = obj.getClass().getMethods(); 201 for (int i=0; i<methods.length; i++) { 202 // getXXX() methods. Object and LanguageElement classes are not included. 203 if (!(methods[i].getDeclaringClass().equals(Object.class)) 204 && methods[i].getName().startsWith("get") 205 && !Modifier.isStatic(methods[i].getModifiers()) 206 && !methods[i].isSynthetic() 207 && methods[i].getParameterTypes().length==0) { 208 try { 209 Object value=getNode(methods[i], obj); 210 if (value!=null && (!(value instanceof Collection) || !((Collection) value).isEmpty())) { 211 Visualizable vs = (Visualizable) master.convert(value, Visualizable.class, null); 212 ret.add(vs.toTreeNode(this, methods[i].getName().substring("get".length()))); 213 } 214 } catch (Exception e) { 215 e.printStackTrace(); 216 } 217 } 218 } 219 } 220 221 return ret; 222 } 223 224 public TableModel toTable() { 225 int rowCount=2; 226 DefaultTableModel tm=new DefaultTableModel(rowCount,4); 227 tm.setColumnIdentifiers(new String[] {"Property", "Declared type", "Runtime type", "Value"}); 228 229 Class<? extends Object> beanClass=obj.getClass(); 230 231 tm.setValueAt("this", 0, 0); 232 tm.setValueAt(beanClass.getName(), 0, 2); 233 tm.setValueAt(obj, 0, 3); 234 235 tm.setValueAt("Hash code", 1, 0); 236 tm.setValueAt("int", 1, 1); 237 tm.setValueAt("int", 1, 2); 238 tm.setValueAt(Integer.toString(obj.hashCode(), Character.MAX_RADIX), 1, 3); 239 240 Method[] methods = beanClass.getMethods(); 241 List<Method> ml = new ArrayList<Method>(); 242 for (int i=0; i<methods.length; i++) { 243 ml.add(methods[i]); 244 } 245 246 Collections.sort(ml, new Comparator<Method>() { 247 248 public int compare(Method m0, Method m1) { 249 return m0.getName().compareTo(m1.getName()); 250 } 251 252 }); 253 254 Iterator<Method> it = ml.iterator(); 255 while (it.hasNext()) { 256 Method method = it.next(); 257 // getXXX() methods. Object.getClass() is not included. 258 if (!(method.getDeclaringClass().equals(Object.class)) 259 && method.getName().startsWith("get") 260 && method.getParameterTypes().length==0) { 261 try { 262 if (getNode(method, obj)==null) { 263 Object value=method.invoke(obj); 264 if (value!=null) { 265 tm.setRowCount(++rowCount); 266 int idx = rowCount-1; 267 tm.setValueAt(method.getName().substring(3), idx, 0); 268 tm.setValueAt(method.getReturnType().getName(), idx, 1); 269 tm.setValueAt(value.getClass().getName(), idx, 2); 270 tm.setValueAt(value, idx, 3); 271 } 272 } 273 } catch (Exception e) { 274 e.printStackTrace(); 275 } 276 } 277 } 278 279 return tm; 280 } 281 282 }; 283 284 } 285 }