[hibernate-commits] Hibernate SVN: r10498 - in trunk/HibernateExt/tools/src/java/org/hibernate/tool: . stat

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Sep 20 12:25:49 EDT 2006


Author: max.andersen at jboss.com
Date: 2006-09-20 12:25:44 -0400 (Wed, 20 Sep 2006)
New Revision: 10498

Added:
   trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/
   trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/AbstractTreeModel.java
   trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/BeanTableModel.java
   trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/StatisticsBrowser.java
   trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/StatisticsCellRenderer.java
   trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/StatisticsTreeModel.java
Log:
HBX-759 Add a statistics browser that is easy to use from hibernate apps

Added: trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/AbstractTreeModel.java
===================================================================
--- trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/AbstractTreeModel.java	2006-09-20 09:27:18 UTC (rev 10497)
+++ trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/AbstractTreeModel.java	2006-09-20 16:25:44 UTC (rev 10498)
@@ -0,0 +1,158 @@
+package org.hibernate.tool.stat; 
+
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
+import javax.swing.event.EventListenerList;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+
+/**
+ * Abstract class implementing the support for TreeModelEvents
+ * and TreeModelListeners. The code is partly snipped from the
+ * implementation of DefaultTreeModel.
+ *
+ * @version $Revision: 1.1.2.1 $
+ **/
+
+public abstract class AbstractTreeModel implements TreeModel {
+
+    private EventListenerList listenerList = new EventListenerList();
+
+    /**
+     * Adds a listener for the TreeModelEvent posted after the tree changes.
+     *
+     * @see     #removeTreeModelListener
+     * @param   l       the listener to add
+     */
+    public void addTreeModelListener(TreeModelListener l) {
+        listenerList.add(TreeModelListener.class, l);
+    }
+
+    /**
+     * Removes a listener previously added with <B>addTreeModelListener()</B>.
+     *
+     * @see     #addTreeModelListener
+     * @param   l       the listener to remove
+     */  
+    public void removeTreeModelListener(TreeModelListener l) {
+        listenerList.remove(TreeModelListener.class, l);
+    }
+
+    /**
+      * Messaged when the user has altered the value for the item identified
+      * by <I>path</I> to <I>newValue</I>.  If <I>newValue</I> signifies
+      * a truly new value the model should post a treeNodesChanged
+      * event.
+      *
+      * @param path path to the node that the user has altered.
+      * @param newValue the new value from the TreeCellEditor.
+      */
+    public void valueForPathChanged(TreePath path, Object newValue) {
+        throw new RuntimeException("AbstractTreeModel.valueForPathChanged: you MUST override this when using a TreeCellEditor!");
+    }
+
+    /*
+     * Notify all listeners that have registered interest for
+     * notification on this event type.  The event instance 
+     * is lazily created using the parameters passed into 
+     * the fire method.
+     * @see EventListenerList
+     */
+    protected void fireTreeNodesChanged(Object source, Object[] path, 
+                                        int[] childIndices, 
+                                        Object[] children) {
+        // Guaranteed to return a non-null array
+        Object[] listeners = listenerList.getListenerList();
+        TreeModelEvent e = null;
+        // Process the listeners last to first, notifying
+        // those that are interested in this event
+        for (int i = listeners.length-2; i>=0; i-=2) {
+            if (listeners[i]==TreeModelListener.class) {
+                // Lazily create the event:
+                if (e == null)
+                    e = new TreeModelEvent(source, path, 
+                                           childIndices, children);
+                ((TreeModelListener)listeners[i+1]).treeNodesChanged(e);
+            }          
+        }
+    }
+
+    /*
+     * Notify all listeners that have registered interest for
+     * notification on this event type.  The event instance 
+     * is lazily created using the parameters passed into 
+     * the fire method.
+     * @see EventListenerList
+     */
+    protected void fireTreeNodesInserted(Object source, Object[] path, 
+                                        int[] childIndices, 
+                                        Object[] children) {
+        // Guaranteed to return a non-null array
+        Object[] listeners = listenerList.getListenerList();
+        TreeModelEvent e = null;
+        // Process the listeners last to first, notifying
+        // those that are interested in this event
+        for (int i = listeners.length-2; i>=0; i-=2) {
+            if (listeners[i]==TreeModelListener.class) {
+                // Lazily create the event:
+                if (e == null)
+                    e = new TreeModelEvent(source, path, 
+                                           childIndices, children);
+                ((TreeModelListener)listeners[i+1]).treeNodesInserted(e);
+            }          
+        }
+    }
+
+    /*
+     * Notify all listeners that have registered interest for
+     * notification on this event type.  The event instance 
+     * is lazily created using the parameters passed into 
+     * the fire method.
+     * @see EventListenerList
+     */
+    protected void fireTreeNodesRemoved(Object source, Object[] path, 
+                                        int[] childIndices, 
+                                        Object[] children) {
+        // Guaranteed to return a non-null array
+        Object[] listeners = listenerList.getListenerList();
+        TreeModelEvent e = null;
+        // Process the listeners last to first, notifying
+        // those that are interested in this event
+        for (int i = listeners.length-2; i>=0; i-=2) {
+            if (listeners[i]==TreeModelListener.class) {
+                // Lazily create the event:
+                if (e == null)
+                    e = new TreeModelEvent(source, path, 
+                                           childIndices, children);
+                ((TreeModelListener)listeners[i+1]).treeNodesRemoved(e);
+            }          
+        }
+    }
+
+    /*
+     * Notify all listeners that have registered interest for
+     * notification on this event type.  The event instance 
+     * is lazily created using the parameters passed into 
+     * the fire method.
+     * @see EventListenerList
+     */
+    protected void fireTreeStructureChanged(Object source, Object[] path, 
+                                            int[] childIndices, 
+                                            Object[] children) {
+        // Guaranteed to return a non-null array
+        Object[] listeners = listenerList.getListenerList();
+        TreeModelEvent e = null;
+        // Process the listeners last to first, notifying
+        // those that are interested in this event
+        for (int i = listeners.length-2; i>=0; i-=2) {
+            if (listeners[i]==TreeModelListener.class) {
+                // Lazily create the event:
+                if (e == null)
+                    e = new TreeModelEvent(source, path, 
+                                           childIndices, children);
+                ((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
+            }          
+        }
+    }
+    
+}

Added: trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/BeanTableModel.java
===================================================================
--- trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/BeanTableModel.java	2006-09-20 09:27:18 UTC (rev 10497)
+++ trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/BeanTableModel.java	2006-09-20 16:25:44 UTC (rev 10498)
@@ -0,0 +1,112 @@
+package org.hibernate.tool.stat;
+
+import java.beans.BeanDescriptor;
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.table.AbstractTableModel;
+
+public class BeanTableModel extends AbstractTableModel {
+
+	protected List list;
+
+	private BeanInfo beanInfo = null;
+
+	private PropertyDescriptor[] descriptors = null;
+	
+	public BeanTableModel(List list, Class beanClass) {
+		this.list = list;
+		introspect( beanClass );
+	}
+
+	private void introspect(Class beanClass) {
+		try {
+			this.beanInfo = Introspector.getBeanInfo( beanClass,
+					Introspector.USE_ALL_BEANINFO );
+			//descriptor = beanInfo.getBeanDescriptor();
+			descriptors = beanInfo.getPropertyDescriptors();
+		}
+		catch (IntrospectionException ie) {
+			// ignore
+		}
+		
+		List v = new ArrayList(descriptors.length);
+		for (int i = 0; i < descriptors.length; i++) {
+			if(!descriptors[i].getName().equals("class")) {
+				v.add( descriptors[i] );
+			}			
+		}
+		descriptors = (PropertyDescriptor[]) v.toArray( new PropertyDescriptor[v.size()] );
+
+	}
+
+	boolean isSingle() {
+		return list.size()<=1;
+	}
+	
+	public int getRowCount() {
+		return isSingle() ? descriptors.length : list.size();
+	}
+
+	public int getColumnCount() {
+		return isSingle() ? list.size() + 1 : (descriptors != null ? descriptors.length : 0);
+	}
+
+	public Object getValueAt(int row, int col) {
+		if(isSingle()) {
+			if(col==0) {
+				return descriptors[row].getDisplayName();
+			} else {
+				return getValue(0, row);
+			}
+		} else {
+			return getValue( row, col );
+		}
+	}
+
+	private Object getValue(int row, int col) {
+		Object bean = list.get( row );
+		Object result = null;
+		try {
+			result = descriptors[col].getReadMethod().invoke( bean, null );
+		}
+		catch (InvocationTargetException ite) {
+			ite.printStackTrace();
+		}
+		catch (IllegalAccessException iae) {
+			iae.printStackTrace();
+		}
+		return result;
+	}
+
+	public String getColumnName(int col) {
+		if(isSingle()) {
+			if(col==0) {
+				return "Name";
+			} else {
+				return "Value";
+			}
+		} else {
+			return descriptors[col].getDisplayName();
+		}
+	}
+
+	public Class getColumnClass(int c) {
+		if(isSingle()) {
+			return String.class;
+		} else {
+			Class propertyType = descriptors[c].getPropertyType();
+
+			if(propertyType.isPrimitive()) {
+				return String.class; // to avoid jtable complain about null table renderer.
+			} else {
+				return propertyType;
+			}
+		}
+	}
+}
\ No newline at end of file

Added: trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/StatisticsBrowser.java
===================================================================
--- trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/StatisticsBrowser.java	2006-09-20 09:27:18 UTC (rev 10497)
+++ trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/StatisticsBrowser.java	2006-09-20 16:25:44 UTC (rev 10498)
@@ -0,0 +1,102 @@
+package org.hibernate.tool.stat;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTable;
+import javax.swing.JTree;
+import javax.swing.ToolTipManager;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+
+import org.hibernate.stat.Statistics;
+import org.hibernate.stat.ui.BeanTableModel;
+import org.hibernate.stat.ui.StatisticsCellRenderer;
+import org.hibernate.stat.ui.StatisticsTreeModel;
+
+/**
+ * Very rudimentary statistics browser.
+ * 
+ * Usage:
+ * new StatisticsBrowser().showStatistics(getSessions().getStatistics(), shouldBlock);
+ * 
+ * @author max
+ *
+ */
+public class StatisticsBrowser {
+	
+	/**
+	 * 
+	 * @param stats a Statistics instance obtained from a SessionFactory
+	 * @param shouldBlock decides if the ui will be modal or not.
+	 */
+	public void showStatistics(Statistics stats, boolean shouldBlock) {
+		
+		JDialog main = new JDialog((JFrame)null, "Statistics browser");
+		
+		main.getContentPane().setLayout(new BorderLayout());
+		
+		final StatisticsTreeModel statisticsTreeModel = new StatisticsTreeModel(stats);
+		JTree tree = new JTree(statisticsTreeModel);
+		tree.setCellRenderer( new StatisticsCellRenderer() );
+		ToolTipManager.sharedInstance().registerComponent(tree);
+		
+		JScrollPane treePane = new JScrollPane(tree);
+		
+		final JTable table = new JTable();
+		
+		JScrollPane tablePane = new JScrollPane(table);
+		tablePane.getViewport().setBackground( table.getBackground() );
+		final BeanTableModel beanTableModel = new BeanTableModel(Collections.EMPTY_LIST, Object.class);
+		table.setModel( beanTableModel );
+		
+		JSplitPane pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treePane, tablePane);
+		pane.setContinuousLayout( true );
+		
+		main.getContentPane().add(pane, BorderLayout.CENTER);
+		
+		tree.addTreeSelectionListener( new TreeSelectionListener() {
+		
+			public void valueChanged(TreeSelectionEvent e) {
+				Object lastPathComponent = e.getPath().getLastPathComponent();
+				List l = new ArrayList();
+				if(statisticsTreeModel.isContainer( lastPathComponent )) {
+					int childCount = statisticsTreeModel.getChildCount( lastPathComponent );
+					
+					Class cl = Object.class;
+					for (int i = 0; i < childCount; i++) {
+						Object v = statisticsTreeModel.getChild( lastPathComponent, i );
+						if(v!=null) cl = v.getClass();
+						l.add(v);
+					}
+					table.setModel( new BeanTableModel(l, cl) );	
+				} else {
+					l.add( lastPathComponent );
+					table.setModel( new BeanTableModel(l, lastPathComponent.getClass()) );
+				}
+				
+				//table.doLayout();
+				
+			}
+		
+		} );
+		
+		
+		main.getContentPane().setSize(new Dimension(640,480));
+		main.pack();
+		main.setModal(shouldBlock);
+		main.setVisible(true);
+	}
+	
+	
+	
+	
+
+}

Added: trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/StatisticsCellRenderer.java
===================================================================
--- trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/StatisticsCellRenderer.java	2006-09-20 09:27:18 UTC (rev 10497)
+++ trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/StatisticsCellRenderer.java	2006-09-20 16:25:44 UTC (rev 10498)
@@ -0,0 +1,61 @@
+package org.hibernate.tool.stat;
+
+import java.awt.Component;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.swing.JLabel;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import org.hibernate.stat.CategorizedStatistics;
+import org.hibernate.stat.CollectionStatistics;
+import org.hibernate.stat.EntityStatistics;
+import org.hibernate.stat.QueryStatistics;
+import org.hibernate.stat.Statistics;
+
+public class StatisticsCellRenderer extends DefaultTreeCellRenderer {
+
+	SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
+	
+	public Component getTreeCellRendererComponent(JTree tree, Object value,
+			boolean selected, boolean expanded, boolean leaf, int row,
+			boolean hasFocus) {
+		
+		JLabel treeCellRendererComponent = (JLabel) super.getTreeCellRendererComponent( tree, value, selected, expanded, leaf, row, hasFocus );
+		
+		String text = treeCellRendererComponent.getText();
+		String tooltip = null;
+		if(value instanceof Statistics) {
+			Statistics stats = (Statistics) value;
+			text = "Statistics " + formatter.format( new Date(stats.getStartTime()) );
+			tooltip = stats.toString();
+		}
+		
+		if(value instanceof CategorizedStatistics) {
+			CategorizedStatistics stats = (CategorizedStatistics) value;
+			text = stats.getCategoryName();
+			
+		}
+		if(value instanceof EntityStatistics) {
+			EntityStatistics stats = (EntityStatistics) value;
+			
+		}
+		
+		if(value instanceof CollectionStatistics) {
+			CollectionStatistics stats = (CollectionStatistics) value;
+			
+		}
+		
+		if(value instanceof QueryStatistics) {
+			QueryStatistics stats = (QueryStatistics) value;
+		
+		}
+		
+		treeCellRendererComponent.setText( text );
+		treeCellRendererComponent.setToolTipText( tooltip );
+		return treeCellRendererComponent;
+	}
+
+	
+}

Added: trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/StatisticsTreeModel.java
===================================================================
--- trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/StatisticsTreeModel.java	2006-09-20 09:27:18 UTC (rev 10497)
+++ trunk/HibernateExt/tools/src/java/org/hibernate/tool/stat/StatisticsTreeModel.java	2006-09-20 16:25:44 UTC (rev 10498)
@@ -0,0 +1,79 @@
+package org.hibernate.tool.stat;
+
+import org.hibernate.stat.Statistics;
+import org.hibernate.stat.ui.AbstractTreeModel;
+
+public class StatisticsTreeModel extends AbstractTreeModel {
+
+	private final Statistics stats;
+
+	String queries = "Queries";
+	String entities = "Entities";
+	String collections = "Collections";
+	
+	
+	
+	public StatisticsTreeModel(Statistics stats) {
+		this.stats = stats;
+	}
+
+	public Object getChild(Object parent, int index) {
+		if(parent==stats) {
+			switch(index) {
+			case 0: return entities;
+			case 1: return collections;
+			case 2:	return queries;			
+			}
+		} else if(parent==entities) {
+			return stats.getEntityStatistics(stats.getEntityNames()[index]);
+		} else if(parent==collections) {
+			return stats.getCollectionStatistics(stats.getCollectionRoleNames()[index]);
+		} else if(parent==queries) {
+			return stats.getQueryStatistics(stats.getQueries()[index]);
+		}
+		return null;
+	}
+
+	public int getChildCount(Object parent) {
+		if(parent==stats) {
+			return 3;
+		} else if(parent==entities) {
+			return stats.getEntityNames().length;
+		} else if(parent==collections) {
+			return stats.getCollectionRoleNames().length;
+		} else if(parent==queries) {
+			return stats.getQueries().length;
+		}
+		return 0;
+	}
+
+	public int getIndexOfChild(Object parent, Object child) {
+		throw new IllegalAccessError();
+		//return 0;
+	}
+
+	public Object getRoot() {
+		return stats;
+	}
+
+	public boolean isLeaf(Object node) {
+		return false;
+	}
+	
+	public boolean isQueries(Object o) {
+		return o==queries; // hack
+	}
+	
+	public boolean isCollections(Object o) {
+		return o==collections; // hack
+	}
+	
+	public boolean isEntities(Object o) {
+		return o==entities; // hack
+	}
+
+	public boolean isContainer(Object o) {
+		return isEntities( o ) || isQueries( o ) || isCollections( o );
+	}
+	
+}
\ No newline at end of file




More information about the hibernate-commits mailing list