private int silentAdd(R record) { if (record == null) { throw new NullPointerException("Record is null passed into add() to store"); } Long id = record.getRecordId(); if (id == null) { id = ID_GENERATOR.next(); try { record.setRecordId(id); } catch (Exception e) { // this can't happen if we have exclusive access to the object (2 threads?) } } R existing = data.get(id); if (existing != null) { throw new RuntimeException("The store already contains this"); } // add it to our internal memory int index = data.add(id, record); // listen for change events. (null safe version) record.onChange().addObserver(this.onValueChanged); return index; }
@Override public void notify(Object observable, DataEventObject<Record> e) { if (e != null && e.getData() != null) { if (!contains(e.getData().getRecordId())) { throw new RuntimeException( "Assertion error. We've received an event for a record we do not know about. We probably didn't unregister a listener through the remove() event."); } } // one of our records changed! // the Observable here is the record. if (onChange != null) { @SuppressWarnings( value = "unchecked") // Guaranteed type safe as R is defined as <R extends Record> and e // is a Record which is an interface R record = (R) e.getData(); // we need to find the index for this. int index = data.indexOfValue(record); // rethrow but with an index. onChange.notifyObservers(this, getEventObject(record, index)); } }
@Override public void clearFilter() { data.clearFilter(); // announce that a full redraw is necessary if (onLoad != null) { onLoad.notifyObservers(this, new EventObject(this)); } }
public void sort(final Comparator<R> comparator) { // the 2 different data structures require different API's // let's wrap another comparator around to adapt between them. data.sort( new Comparator<KeyValuePair<Long, R>>() { public int compare(KeyValuePair<Long, R> o1, KeyValuePair<Long, R> o2) { return comparator.compare(o1.getValue(), o2.getValue()); } }); if (onLoad != null) { onLoad.notifyObservers(this, getEventObject()); } }
@Override public void setFilter(final Filter<R> filter) { // do the filter (NOTE: we ignore events from the MixedCollection) // so we have to throw our own event manually data.setFilter( new Filter<KeyValuePair<Long, R>>() { public boolean call(KeyValuePair<Long, R> item) throws Exception { return filter.call(item.getValue()); } }); // announce that a full redraw is necessary if (onLoad != null) { onLoad.notifyObservers(this, new EventObject(this)); } }
private void remove(R record) { if (record == null) { return; } Long id = record.getRecordId(); if (!contains(id)) { return; } // need to know where it is so we can update the GUI efficiently int index = indexOf(id); // kill from our data backing. // NOTE: this MUST pierce the veil of filtering data.remove(id); // stop listening for changes. record.onChange().removeObserver(this.onValueChanged); if (this.onRemove != null) { this.onRemove.notifyObservers(this, getEventObject(record, index)); } }
@Override public boolean isFiltered() { return data.isFiltered(); }
@Override public boolean contains(Long recordId) { return data.containsKey(recordId); }
@Override public int indexOf(Long id) { return data.indexOfKey(id); }
@Override public R getAt(int index) { return data.getAt(index); }
@Override public int size() { return data.size(); }
@Override public R get(Long id) { return data.get(id); }