1 5 package prefuse.visual; 6 7 import java.util.HashSet ; 8 import java.util.Iterator ; 9 10 import prefuse.Visualization; 11 import prefuse.data.Schema; 12 import prefuse.data.Table; 13 import prefuse.data.Tuple; 14 import prefuse.data.event.EventConstants; 15 import prefuse.data.util.Index; 16 import prefuse.util.collections.IntIterator; 17 import prefuse.visual.tuple.TableAggregateItem; 18 19 27 public class AggregateTable extends VisualTable { 28 29 32 protected Table m_aggregated; 33 34 39 public AggregateTable(Visualization vis, String group) { 40 this(vis, group, VisualItem.SCHEMA); 41 } 42 43 49 public AggregateTable(Visualization vis, String group, Schema schema) { 50 super(vis, group, schema, TableAggregateItem.class); 51 m_aggregated = AGGREGATED_SCHEMA.instantiate(); 52 m_aggregated.index(AGGREGATE); 53 m_aggregated.index(MEMBER_HASH); 54 } 55 56 58 63 public int getAggregateSize(int row) { 64 int size = 0; 65 AggregatedIterator ati = new AggregatedIterator(row); 66 for ( ; ati.hasNext(); ++size, ati.next() ); 67 return size; 68 } 69 70 75 public void addToAggregate(int row, VisualItem member) { 76 validRowCheck(row, true); 77 if ( !aggregateContains(row, member) ) { 78 int ar = m_aggregated.addRow(); 79 m_aggregated.setInt(ar, AGGREGATE, row); 80 m_aggregated.setInt(ar, MEMBER_HASH, getHashCode(member)); 81 m_aggregated.set(ar, MEMBER, member); 82 fireTableEvent(row, row, 83 EventConstants.ALL_COLUMNS, EventConstants.UPDATE); 84 } 85 } 86 87 92 public void removeFromAggregate(int row, VisualItem member) { 93 validRowCheck(row, true); 94 int ar = getAggregatedRow(row, member); 95 if ( ar >= 0 ) { 96 m_aggregated.removeRow(ar); 97 fireTableEvent(row, row, 98 EventConstants.ALL_COLUMNS, EventConstants.UPDATE); 99 } 100 } 101 102 106 public void removeAllFromAggregate(int row) { 107 clearAggregateMappings(row, true); 108 } 109 110 116 protected void clearAggregateMappings(int row, boolean update) { 117 Index index = m_aggregated.index(AGGREGATE); 118 boolean fire = false; 119 for ( IntIterator rows = index.rows(row); rows.hasNext(); ) { 120 int r = rows.nextInt(); 121 rows.remove(); 125 m_aggregated.removeRow(r); 126 fire = true; 127 } 128 if ( update && fire ) 129 fireTableEvent(row, row, 130 EventConstants.ALL_COLUMNS, EventConstants.UPDATE); 131 } 132 133 139 public boolean aggregateContains(int row, VisualItem member) { 140 return getAggregatedRow(row, member) >= 0; 141 } 142 143 151 protected int getAggregatedRow(int row, VisualItem member) { 152 Index index = m_aggregated.index(MEMBER_HASH); 153 int hash = getHashCode(member); 154 int ar = index.get(hash); 155 if ( ar < 0 ) { 156 return -1; 157 } else if ( m_aggregated.getInt(ar, AGGREGATE) == row ) { 158 return ar; 159 } else { 160 for ( IntIterator rows = index.rows(hash); rows.hasNext(); ) { 161 ar = rows.nextInt(); 162 if ( m_aggregated.getInt(ar, AGGREGATE) == row ) 163 return ar; 164 } 165 return -1; 166 } 167 } 168 169 174 public Iterator aggregatedTuples(int row) { 175 return new AggregatedIterator(row); 176 } 177 178 183 public Iterator getAggregates(Tuple t) { 184 int hash = getHashCode(t); 185 IntIterator iit = m_aggregated.getIndex(MEMBER_HASH).rows(hash); 186 HashSet set = new HashSet (); 187 while ( iit.hasNext() ) { 188 int r = iit.nextInt(); 189 set.add(getTuple(m_aggregated.getInt(r, AGGREGATE))); 190 } 191 return set.iterator(); 192 } 193 194 199 protected int getHashCode(Tuple t) { 200 return t.hashCode(); 203 } 204 205 213 protected boolean validRowCheck(int row, boolean throwException) { 214 if ( isValidRow(row) ) { 215 return true; 216 } else if ( throwException ) { 217 throw new IllegalArgumentException ("Invalid row value: "+row); 218 } else { 219 return false; 220 } 221 } 222 223 226 229 protected void fireTableEvent(int row0, int row1, int col, int type) { 230 if ( col==EventConstants.ALL_COLUMNS && type==EventConstants.DELETE ) { 231 for ( int r=row0; r<=row1; ++r ) 232 clearAggregateMappings(r, false); 233 } 234 super.fireTableEvent(row0, row1, col, type); 235 } 236 237 238 241 244 protected class AggregatedIterator implements Iterator { 245 private IntIterator m_rows; 246 private Tuple m_next = null; 247 248 public AggregatedIterator(int row) { 249 Index index = m_aggregated.index(AGGREGATE); 250 m_rows = index.rows(row); 251 advance(); 252 } 253 public boolean hasNext() { 254 return m_next != null; 255 } 256 public Object next() { 257 Tuple retval = m_next; 258 advance(); 259 return retval; 260 } 261 private void advance() { 262 while ( m_rows.hasNext() ) { 263 int ar = m_rows.nextInt(); 264 Tuple t = (Tuple)m_aggregated.get(ar, MEMBER); 265 if ( t.isValid() ) { 266 m_next = t; 267 return; 268 } else { 269 m_aggregated.removeRow(ar); 270 } 271 } 272 m_next = null; 273 } 274 public void remove() { 275 throw new UnsupportedOperationException (); 276 } 277 } 278 279 282 protected static final String AGGREGATE = "aggregate"; 283 protected static final String MEMBER_HASH = "hash"; 284 protected static final String MEMBER = "member"; 285 protected static final Schema AGGREGATED_SCHEMA = new Schema(); 286 static { 287 AGGREGATED_SCHEMA.addColumn(AGGREGATE, int.class); 288 AGGREGATED_SCHEMA.addColumn(MEMBER_HASH, int.class); 289 AGGREGATED_SCHEMA.addColumn(MEMBER, Tuple.class); 290 } 291 292 } | Popular Tags |