1 package prefuse.data.column; 2 3 import java.util.BitSet ; 4 import java.util.Iterator ; 5 import java.util.Set ; 6 7 import prefuse.data.DataTypeException; 8 import prefuse.data.Table; 9 import prefuse.data.event.ColumnListener; 10 import prefuse.data.event.EventConstants; 11 import prefuse.data.event.ExpressionListener; 12 import prefuse.data.expression.Expression; 13 import prefuse.data.expression.ExpressionAnalyzer; 14 15 35 public class ExpressionColumn extends AbstractColumn { 36 37 private Expression m_expr; 38 private Table m_table; 39 private Set m_columns; 40 41 private BitSet m_valid; 42 private Column m_cache; 43 private Listener m_lstnr; 44 45 50 public ExpressionColumn(Table table, Expression expr) { 51 super(expr.getType(table.getSchema())); 52 m_table = table; 53 m_expr = expr; 54 m_lstnr = new Listener(); 55 56 init(); 57 58 int nrows = m_table.getRowCount(); 59 m_cache = ColumnFactory.getColumn(getColumnType(), nrows); 60 m_valid = new BitSet (nrows); 61 m_expr.addExpressionListener(m_lstnr); 62 } 63 64 protected void init() { 65 if ( m_columns != null && m_columns.size() > 0 ) { 67 Iterator iter = m_columns.iterator(); 68 while ( iter.hasNext() ) { 69 String field = (String )iter.next(); 70 Column col = m_table.getColumn(field); 71 col.removeColumnListener(m_lstnr); 72 } 73 } 74 m_columns = ExpressionAnalyzer.getReferencedColumns(m_expr); 76 77 Iterator iter = m_columns.iterator(); 79 while ( iter.hasNext() ) { 80 String name = (String )iter.next(); 81 if ( m_table.getColumn(name) == null ) 82 throw new IllegalArgumentException ("Table must contain all " 83 + "columns referenced by the expression." 84 + " Bad column name: "+name); 85 86 } 87 88 iter = m_columns.iterator(); 90 while ( iter.hasNext() ) { 91 String field = (String )iter.next(); 92 Column col = m_table.getColumn(field); 93 col.addColumnListener(m_lstnr); 94 } 95 } 96 97 100 103 public int getRowCount() { 104 return m_cache.getRowCount(); 105 } 106 107 110 public void setMaximumRow(int nrows) { 111 m_cache.setMaximumRow(nrows); 112 } 113 114 117 123 public boolean isCacheValid(int row) { 124 return m_valid.get(row); 125 } 126 127 132 public void invalidateCache(int start, int end ) { 133 m_valid.clear(start, end+1); 134 } 135 136 139 143 public void revertToDefault(int row) { 144 } 146 147 150 public boolean canSet(Class type) { 151 return false; 152 } 153 154 157 public Object get(int row) { 158 rangeCheck(row); 159 if ( isCacheValid(row) ) { 160 return m_cache.get(row); 161 } 162 Object val = m_expr.get(m_table.getTuple(row)); 163 Class type = val==null ? Object .class : val.getClass(); 164 if ( m_cache.canSet(type) ) { 165 m_cache.set(val, row); 166 m_valid.set(row); 167 } 168 return val; 169 } 170 171 174 public void set(Object val, int row) throws DataTypeException { 175 throw new UnsupportedOperationException (); 176 } 177 178 private void rangeCheck(int row) { 179 if ( row < 0 || row >= getRowCount() ) 180 throw new IndexOutOfBoundsException (); 181 } 182 183 185 188 public boolean getBoolean(int row) throws DataTypeException { 189 if ( !canGetBoolean() ) 190 throw new DataTypeException(boolean.class); 191 rangeCheck(row); 192 193 if ( isCacheValid(row) ) { 194 return m_cache.getBoolean(row); 195 } else { 196 boolean value = m_expr.getBoolean(m_table.getTuple(row)); 197 m_cache.setBoolean(value, row); 198 m_valid.set(row); 199 return value; 200 } 201 } 202 203 private void computeNumber(int row) { 204 if ( m_columnType == int.class || m_columnType == byte.class ) { 205 m_cache.setInt(m_expr.getInt(m_table.getTuple(row)), row); 206 } else if ( m_columnType == long.class ) { 207 m_cache.setLong(m_expr.getLong(m_table.getTuple(row)), row); 208 } else if ( m_columnType == float.class ) { 209 m_cache.setFloat(m_expr.getFloat(m_table.getTuple(row)), row); 210 } else { 211 m_cache.setDouble(m_expr.getDouble(m_table.getTuple(row)), row); 212 } 213 m_valid.set(row); 214 } 215 216 219 public int getInt(int row) throws DataTypeException { 220 if ( !canGetInt() ) 221 throw new DataTypeException(int.class); 222 rangeCheck(row); 223 224 if ( !isCacheValid(row) ) 225 computeNumber(row); 226 return m_cache.getInt(row); 227 } 228 229 232 public double getDouble(int row) throws DataTypeException { 233 if ( !canGetDouble() ) 234 throw new DataTypeException(double.class); 235 rangeCheck(row); 236 237 if ( !isCacheValid(row) ) 238 computeNumber(row); 239 return m_cache.getDouble(row); 240 } 241 242 245 public float getFloat(int row) throws DataTypeException { 246 if ( !canGetFloat() ) 247 throw new DataTypeException(float.class); 248 rangeCheck(row); 249 250 if ( !isCacheValid(row) ) 251 computeNumber(row); 252 return m_cache.getFloat(row); 253 } 254 255 258 public long getLong(int row) throws DataTypeException { 259 if ( !canGetLong() ) 260 throw new DataTypeException(long.class); 261 rangeCheck(row); 262 263 if ( !isCacheValid(row) ) 264 computeNumber(row); 265 return m_cache.getLong(row); 266 } 267 268 271 private class Listener implements ColumnListener, ExpressionListener { 272 273 public void columnChanged(int start, int end) { 274 if ( start == end && isCacheValid(start) ) { 277 if ( !m_table.isValidRow(start) ) return; 278 279 invalidateCache(start, end); 281 Class type = getColumnType(); 283 if ( int.class == type ) { 284 fireColumnEvent(start, m_cache.getInt(start)); 285 } else if ( long.class == type ) { 286 fireColumnEvent(start, m_cache.getLong(start)); 287 } else if ( float.class == type ) { 288 fireColumnEvent(start, m_cache.getFloat(start)); 289 } else if ( double.class == type ) { 290 fireColumnEvent(start, m_cache.getDouble(start)); 291 } else if ( boolean.class == type ) { 292 fireColumnEvent(start, m_cache.getBoolean(start)); 293 } else { 294 fireColumnEvent(start, m_cache.get(start)); 295 } 296 297 } else { 299 invalidateCache(start, end); 301 fireColumnEvent(EventConstants.UPDATE, start, end); 303 } 304 } 305 306 public void columnChanged(Column src, int idx, boolean prev) { 307 columnChanged(idx, idx); 308 } 309 310 public void columnChanged(Column src, int idx, double prev) { 311 columnChanged(idx, idx); 312 } 313 314 public void columnChanged(Column src, int idx, float prev) { 315 columnChanged(idx, idx); 316 } 317 318 public void columnChanged(Column src, int type, int start, int end) { 319 columnChanged(start, end); 320 } 321 322 public void columnChanged(Column src, int idx, int prev) { 323 columnChanged(idx, idx); 324 } 325 326 public void columnChanged(Column src, int idx, long prev) { 327 columnChanged(idx, idx); 328 } 329 330 public void columnChanged(Column src, int idx, Object prev) { 331 columnChanged(idx, idx); 332 } 333 334 public void expressionChanged(Expression expr) { 335 columnChanged(0, m_cache.getRowCount()-1); 337 init(); 339 } 340 } 341 342 } | Popular Tags |