KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > prefuse > data > column > ColumnMetadata


1 package prefuse.data.column;
2
3 import java.util.Comparator JavaDoc;
4 import java.util.HashMap JavaDoc;
5 import java.util.Map JavaDoc;
6
7 import prefuse.data.Table;
8 import prefuse.data.event.ColumnListener;
9 import prefuse.data.util.Index;
10 import prefuse.util.DataLib;
11 import prefuse.util.TypeLib;
12 import prefuse.util.collections.DefaultLiteralComparator;
13
14 /**
15  * ColumnMetadata stores computed metadata and statistics for a singe column
16  * instance. They are created automatically by Table instances and are
17  * retrieved using the {@link prefuse.data.Table#getMetadata(String)} method.
18  * @author <a HREF="http://jheer.org">jeffrey heer</a>
19  */

20 public class ColumnMetadata implements ColumnListener {
21
22     // TODO consider refactor. is non-dynamic mode needed? pass Column reference in?
23

24     private Table m_table;
25     private String JavaDoc m_field;
26     private boolean m_dynamic;
27     private boolean m_init;
28
29     private Comparator JavaDoc m_cmp;
30     
31     private Object JavaDoc m_default;
32     private int m_min;
33     private int m_max;
34     private int m_median;
35     private int m_unique;
36     private Double JavaDoc m_mean;
37     private Double JavaDoc m_stdev;
38     private Double JavaDoc m_sum;
39     private Object JavaDoc[] m_ordinalA;
40     private Map JavaDoc m_ordinalM;
41     
42     // ------------------------------------------------------------------------
43

44     /**
45      * Creates a new ColumnMetadata instance.
46      * @param table the backing table
47      * @param column the name of the column to store metadata for
48      */

49     public ColumnMetadata(Table table, String JavaDoc column) {
50         this(table, column, DefaultLiteralComparator.getInstance(), true);
51     }
52
53     /**
54      * Creates a new ColumnMetadata instance.
55      * @param table the backing table
56      * @param column the name of the column to store metadata for
57      * @param cmp a Comparator that determines the default sort order for
58      * values in the column
59      * @param dynamic indicates if this ColumnMetadata should react to
60      * changes in the underlying table values. If true, computed values
61      * stored in this metadata object will be invalidated when updates to
62      * the column data occur.
63      */

64     public ColumnMetadata(Table table, String JavaDoc column,
65             Comparator JavaDoc cmp, boolean dynamic)
66     {
67         m_table = table;
68         m_field = column;
69         m_cmp = cmp;
70         m_dynamic = dynamic;
71     }
72     
73     /**
74      * Dispose of this metadata, freeing any resources and unregistering any
75      * listeners.
76      */

77     public void dispose() {
78         m_table.getColumn(m_field).removeColumnListener(this);
79     }
80
81     // ------------------------------------------------------------------------
82

83     private void clearCachedValues() {
84         m_min = -1;
85         m_max = -1;
86         m_median = -1;
87         m_unique = -1;
88         m_mean = null;
89         m_stdev = null;
90         m_sum = null;
91         m_ordinalA = null;
92         m_ordinalM = null;
93     }
94     
95     /**
96      * Re-calculates all the metadata and statistics maintained by this object.
97      */

98     public void calculateValues() {
99         clearCachedValues();
100         boolean dyn = m_dynamic;
101         m_dynamic = true;
102         getMinimumRow();
103         getMaximumRow();
104         getMedianRow();
105         getUniqueCount();
106         if ( TypeLib.isNumericType(m_table.getColumnType(m_field)) ) {
107             getMean();
108             getDeviation();
109             getSum();
110         }
111         getOrdinalArray();
112         getOrdinalMap();
113         m_init = true;
114         m_dynamic = dyn;
115     }
116     
117     private void accessCheck() {
118         if ( m_init ) return;
119         
120         if ( m_dynamic ) {
121           clearCachedValues();
122           m_table.getColumn(m_field).addColumnListener(this);
123         } else {
124           calculateValues();
125         }
126         m_init = true;
127     }
128     
129     // ------------------------------------------------------------------------
130

131     /**
132      * Returns the comparator used to determine column values' sort order.
133      * @return the Comparator
134      */

135     public Comparator JavaDoc getComparator() {
136         return m_cmp;
137     }
138     
139     /**
140      * Sets the comparator used to detemine column values' sort order.
141      * @param c the Comparator to use
142      */

143     public void setComparator(Comparator JavaDoc c) {
144         m_cmp = c;
145         clearCachedValues();
146     }
147     
148     /**
149      * Get the columns' default value.
150      * @return the column's default value
151      */

152     public Object JavaDoc getDefaultValue() {
153         return m_default;
154     }
155     
156     /**
157      * Get the row index of the minimum column value. If there are multiple
158      * minima, only one is returned.
159      * @return the row index of the minimum column value.
160      */

161     public int getMinimumRow() {
162         accessCheck();
163         if ( m_min == -1 && m_dynamic ) {
164             Index idx = m_table.getIndex(m_field);
165             if ( idx != null ) {
166                 m_min = idx.minimum();
167             } else {
168                 m_min = DataLib.min(m_table.tuples(), m_field, m_cmp).getRow();
169             }
170         }
171         return m_min;
172     }
173
174     /**
175      * Get the row index of the maximum column value. If there are multiple
176      * maxima, only one is returned.
177      * @return the row index of the maximum column value.
178      */

179     public int getMaximumRow() {
180         accessCheck();
181         if ( m_max == -1 && m_dynamic ) {
182             Index idx = m_table.getIndex(m_field);
183             if ( idx != null ) {
184                 m_max = idx.maximum();
185             } else {
186                 m_max = DataLib.max(m_table.tuples(), m_field, m_cmp).getRow();
187             }
188         }
189         return m_max;
190     }
191     
192     /**
193      * Get the row index of the median column value.
194      * @return the row index of the median column value
195      */

196     public int getMedianRow() {
197         accessCheck();
198         if ( m_median == -1 && m_dynamic ) {
199             Index idx = m_table.getIndex(m_field);
200             if ( idx != null ) {
201                 m_max = idx.median();
202             } else {
203                 m_median = DataLib.median(
204                                 m_table.tuples(), m_field, m_cmp).getRow();
205             }
206         }
207         return m_median;
208     }
209     
210     /**
211      * Get the number of unique values in the column.
212      * @return the number of unique values in the column
213      */

214     public int getUniqueCount() {
215         accessCheck();
216         if ( m_unique == -1 && m_dynamic ) {
217             Index idx = m_table.getIndex(m_field);
218             if ( idx != null ) {
219                 m_unique = idx.uniqueCount();
220             } else {
221                 m_unique = DataLib.uniqueCount(m_table.tuples(), m_field);
222             }
223         }
224         return m_unique;
225     }
226     
227     /**
228      * Get the mean value of numeric values in the column. If this column
229      * does not contain numeric values, this method will result in an
230      * exception being thrown.
231      * @return the mean of numeric values in the column
232      */

233     public double getMean() {
234         accessCheck();
235         if ( m_mean == null && m_dynamic ) {
236             m_mean = new Double JavaDoc(DataLib.mean(m_table.tuples(), m_field));
237         }
238         return m_mean.doubleValue();
239     }
240     
241     /**
242      * Get the standard deviation of numeric values in the column. If this column
243      * does not contain numeric values, this method will result in an
244      * exception being thrown.
245      * @return the standard deviation of numeric values in the column
246      */

247     public double getDeviation() {
248         accessCheck();
249         if ( m_stdev == null && m_dynamic ) {
250             m_stdev = new Double JavaDoc(
251                     DataLib.deviation(m_table.tuples(), m_field, getMean()));
252         }
253         return m_stdev.doubleValue();
254     }
255     
256     /**
257      * Get the sum of numeric values in the column. If this column
258      * does not contain numeric values, this method will result in an
259      * exception being thrown.
260      * @return the sum of numeric values in the column
261      */

262     public double getSum() {
263         accessCheck();
264         if ( m_sum == null && m_dynamic ) {
265             m_sum = new Double JavaDoc(DataLib.sum(m_table.tuples(), m_field));
266         }
267         return m_sum.doubleValue();
268     }
269     
270     /**
271      * Get an array of all unique column values, in sorted order.
272      * @return an array of all unique column values, in sorted order.
273      */

274     public Object JavaDoc[] getOrdinalArray() {
275         accessCheck();
276         if ( m_ordinalA == null && m_dynamic ) {
277             m_ordinalA = DataLib.ordinalArray(m_table.tuples(),m_field,m_cmp);
278         }
279         return m_ordinalA;
280     }
281     
282     /**
283      * Get a map between all unique column values and their integer index
284      * in the sort order of those values. For example, the minimum value
285      * maps to 0, the next greater value to 1, etc.
286      * @return a map between all unique column values and their integer index
287      * in the values' sort order
288      */

289     public Map JavaDoc getOrdinalMap() {
290         accessCheck();
291         if ( m_ordinalM == null && m_dynamic ) {
292             Object JavaDoc[] a = getOrdinalArray();
293             m_ordinalM = new HashMap JavaDoc();
294             for ( int i=0; i<a.length; ++i )
295                 m_ordinalM.put(a[i], new Integer JavaDoc(i));
296             //m_ordinalM = DataLib.ordinalMap(m_table.tuples(), m_field, m_cmp);
297
}
298         return m_ordinalM;
299     }
300     
301     // ------------------------------------------------------------------------
302

303     /**
304      * @see prefuse.data.event.ColumnListener#columnChanged(prefuse.data.column.Column, int, int, int)
305      */

306     public void columnChanged(Column src, int type, int start, int end) {
307         clearCachedValues();
308     }
309     
310     /**
311      * @see prefuse.data.event.ColumnListener#columnChanged(prefuse.data.column.Column, int, boolean)
312      */

313     public void columnChanged(Column src, int idx, boolean prev) {
314         columnChanged(src, 0, idx, idx);
315     }
316
317     /**
318      * @see prefuse.data.event.ColumnListener#columnChanged(prefuse.data.column.Column, int, double)
319      */

320     public void columnChanged(Column src, int idx, double prev) {
321         columnChanged(src, 0, idx, idx);
322     }
323
324     /**
325      * @see prefuse.data.event.ColumnListener#columnChanged(prefuse.data.column.Column, int, float)
326      */

327     public void columnChanged(Column src, int idx, float prev) {
328         columnChanged(src, 0, idx, idx);
329     }
330     
331     /**
332      * @see prefuse.data.event.ColumnListener#columnChanged(prefuse.data.column.Column, int, int)
333      */

334     public void columnChanged(Column src, int idx, int prev) {
335         columnChanged(src, 0, idx, idx);
336     }
337
338     /**
339      * @see prefuse.data.event.ColumnListener#columnChanged(prefuse.data.column.Column, int, long)
340      */

341     public void columnChanged(Column src, int idx, long prev) {
342         columnChanged(src, 0, idx, idx);
343     }
344
345     /**
346      * @see prefuse.data.event.ColumnListener#columnChanged(prefuse.data.column.Column, int, java.lang.Object)
347      */

348     public void columnChanged(Column src, int idx, Object JavaDoc prev) {
349         columnChanged(src, 0, idx, idx);
350     }
351     
352 } // end of class ColumnMetadata
353
Popular Tags