KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > AppenderTable


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17
18 import org.apache.log4j.helpers.CyclicBuffer;
19 import org.apache.log4j.Level;
20 import org.apache.log4j.Logger;
21 import org.apache.log4j.Layout;
22 import org.apache.log4j.PatternLayout;
23 import org.apache.log4j.spi.LoggingEvent;
24
25 import javax.swing.JFrame JavaDoc;
26 import javax.swing.JButton JavaDoc;
27 import javax.swing.JTable JavaDoc;
28 import javax.swing.JTextArea JavaDoc;
29 import javax.swing.table.AbstractTableModel JavaDoc;
30 import javax.swing.table.TableCellRenderer JavaDoc;
31 import javax.swing.JScrollPane JavaDoc;
32 import javax.swing.BoxLayout JavaDoc;
33
34 import java.awt.Component JavaDoc;
35 import java.awt.Dimension JavaDoc;
36 import java.awt.event.ActionListener JavaDoc;
37 import java.awt.event.ActionEvent JavaDoc;
38 import java.awt.Container JavaDoc;
39
40 /**
41    The AppenderTable illustrates one possible implementation of
42    an Table possibly containing a great many number of rows.
43
44    <p>In this particular example we use a fixed size buffer
45    (CyclicBuffer) although this data structure could be easily
46    replaced by dynamically growing one, such as a Vector. The required
47    properties of the data structure is 1) support for indexed element
48    access 2) support for the insertion of new elements at the end.
49
50    <p>Experimentation on my 1400Mhz AMD machine show that it takes
51    about 45 micro-seconds to insert an element in the table. This
52    number does not depend on the size of the buffer. It takes as much
53    (or as little) time to insert one million elements to a buffer of
54    size 10 as to a buffer of size 10'000. It takes about 4 seconds to
55    insert a total of 100'000 elements into the table.
56
57    <p>On windows NT the test will run about twice as fast if you give
58    the focus to the window that runs "java AppenderTable" and not the
59    window that contains the Swing JFrame. */

60 public class AppenderTable extends JTable JavaDoc {
61
62
63   static Logger logger = Logger.getLogger(AppenderTable.class);
64
65   static public void main(String JavaDoc[] args) {
66
67     if(args.length != 2) {
68       System.err.println(
69       "Usage: java AppenderTable bufferSize runLength\n"
70       +" where bufferSize is the size of the cyclic buffer in the TableModel\n"
71       +" and runLength is the total number of elements to add to the table in\n"
72       +" this test run.");
73       return;
74     }
75
76     JFrame JavaDoc frame = new JFrame JavaDoc("JTableAppennder test");
77     Container JavaDoc container = frame.getContentPane();
78
79     AppenderTable tableAppender = new AppenderTable();
80     
81     int bufferSize = Integer.parseInt(args[0]);
82     AppenderTableModel model = new AppenderTableModel(bufferSize);
83     tableAppender.setModel(model);
84
85     int runLength = Integer.parseInt(args[1]);
86
87     JScrollPane JavaDoc sp = new JScrollPane JavaDoc(tableAppender);
88     sp.setPreferredSize(new Dimension JavaDoc(250, 80));
89     
90     container.setLayout(new BoxLayout JavaDoc(container, BoxLayout.X_AXIS));
91     container.add(sp);
92
93     // The "ADD" button is intended for manual testing. It will
94
// add one new logging event to the table.
95
JButton JavaDoc button = new JButton JavaDoc("ADD");
96     container.add(button);
97     button.addActionListener(new JTableAddAction(tableAppender));
98
99     frame.setSize(new Dimension JavaDoc(500,300));
100     frame.setVisible(true);
101
102     long before = System.currentTimeMillis();
103
104     int i = 0;
105     while(i++ < runLength) {
106       LoggingEvent event = new LoggingEvent("x", logger, Level.ERROR,
107                         "Message "+i, null);
108       tableAppender.doAppend(event);
109     }
110
111     long after = System.currentTimeMillis();
112
113     long totalTime = (after-before);
114     
115     System.out.println("Total time :"+totalTime+ " milliseconds for "+
116                "runLength insertions.");
117     System.out.println("Average time per insertion :"
118                +(totalTime*1000/runLength)+ " micro-seconds.");
119
120
121   }
122
123   public
124   AppenderTable() {
125     this.setDefaultRenderer(Object JavaDoc.class, new Renderer JavaDoc());
126   }
127
128   /**
129      When asked to append we just insert directly into the model. In a
130      real appender we would use two buffers one for accumulating
131      events and another to accumalte events but after filtering. Only
132      the second buffer would be displayed in the table and made
133      visible to the user.*/

134   public
135   void doAppend(LoggingEvent event) {
136     ((AppenderTableModel)getModel()).insert(event);
137   }
138
139   /**
140      The Renderer is required to display object in a friendlier from.
141      This particular renderer is just a JTextArea.
142
143      <p>The important point to note is that we only need *one*
144      renderer. */

145   class Renderer extends JTextArea JavaDoc implements TableCellRenderer JavaDoc {
146
147     PatternLayout layout;
148
149     public
150     Renderer() {
151       layout = new PatternLayout("%r %p %c [%t] - %m");
152     }
153
154     public Component JavaDoc getTableCellRendererComponent(JTable JavaDoc table,
155                            Object JavaDoc value,
156                            boolean isSelected,
157                            boolean hasFocus,
158                            int row,
159                            int column) {
160
161       // If its a LoggingEvent than format it using our layout.
162
if(value instanceof LoggingEvent) {
163     LoggingEvent event = (LoggingEvent) value;
164     String JavaDoc str = layout.format(event);
165     setText(str);
166       } else {
167     setText(value.toString());
168       }
169       return this;
170     }
171   }
172 }
173
174 class AppenderTableModel extends AbstractTableModel JavaDoc {
175
176   CyclicBuffer cb;
177   
178   AppenderTableModel(int size) {
179     cb = new CyclicBuffer(size);
180   }
181
182   /**
183      Insertion to the model always results in a fireTableDataChanged
184      method call. Suprisingly enough this has no crippling impact on
185      performance. */

186   public
187   void insert(LoggingEvent event) {
188     cb.add(event);
189     fireTableDataChanged();
190   }
191
192   /**
193      We assume only one column.
194   */

195   public
196   int getColumnCount() {
197     return 1;
198   }
199   
200   /**
201      The row count is given by the number of elements in the
202      buffer. This number is guaranteed to be between 0 and the buffer
203      size (inclusive). */

204   public int getRowCount() {
205     return cb.length();
206   }
207   
208   /**
209      Get the value in a given row and column. We suppose that there is
210      only one colemn so we are only concerned with the row.
211
212      <p>Interesting enough this method returns an object. This leaves
213      the door open for a TableCellRenderer to render the object in
214      a variety of ways.
215   */

216   public
217   Object JavaDoc getValueAt(int row, int col) {
218     return cb.get(row);
219   }
220 }
221
222
223 /**
224    The JTableAddAction is called when the user clicks on the "ADD"
225    button.
226 */

227 class JTableAddAction implements ActionListener JavaDoc {
228     
229   AppenderTable appenderTable;
230   Logger dummy = Logger.getLogger("x");
231   int counter = 0;
232   public
233   JTableAddAction(AppenderTable appenderTable) {
234     this.appenderTable = appenderTable;
235   }
236     
237   public
238   void actionPerformed(ActionEvent JavaDoc e) {
239     counter++;
240     LoggingEvent event = new LoggingEvent("x", dummy, Level.DEBUG,
241                       "Message "+counter, null);
242     appenderTable.doAppend(event);
243   }
244 }
245
Popular Tags