All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ca.odell.glazedlists.calculation.AbstractEventListCalculation Maven / Gradle / Ivy

The newest version!
/* Glazed Lists                                                 (c) 2003-2007 */
/* http://publicobject.com/glazedlists/                      publicobject.com,*/
/*                                                     O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.calculation;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.event.ListEvent;
import ca.odell.glazedlists.event.ListEventListener;

import java.util.ArrayList;
import java.util.List;

/**
 * The transition between an EventList and a single calculated value based on
 * information from each element of the EventList happens in subclasses of this
 * class. To ease the job of maintaining the value of the Calculation when the
 * backing EventList changes, this abstract class provides three abstract
 * methods which must be implemented:
 *
 * 
    *
  • {@link #inserted} updates the value of this Calculation to include the inserted element
  • *
  • {@link #deleted} updates the value of this Calculation to exclude the deleted element
  • *
  • {@link #updated} updates the value of this Calculation to include the replacement element and exclude the prior element
  • *
* * @author James Lemieux */ public abstract class AbstractEventListCalculation extends AbstractCalculation implements ListEventListener { /** the List of elements from which this calculation is derived */ private final EventList source; /** a snapshot of the {@link #source} after the last ListEvent; used to retrieve deleted elements */ private final List snapshot; /** * @param initialValue the value that should immediately be reported as the * value of this Calculation * @param source the List of elements from which this calculation is derived */ protected AbstractEventListCalculation(N initialValue, EventList source) { super(initialValue); this.source = source; this.snapshot = new ArrayList(source); // compute the first value of this Calculation by simulating the entry // of all existing elements for (E element : this.snapshot) inserted(element); // begin listening to the source for changes this.source.addListEventListener(this); } /** * Releases the resources consumed by this {@link AbstractEventListCalculation} * so that it may eventually be garbage collected. * *

An {@link AbstractEventListCalculation} will be garbage collected * without a call to {@link #dispose()}, but not before its source * {@link EventList} is garbage collected. By calling {@link #dispose()}, * you allow the {@link AbstractEventListCalculation} to be garbage * collected before its source {@link EventList}. This is necessary for * situations where an {@link AbstractEventListCalculation} is short-lived * but its source {@link EventList} is long-lived. */ public void dispose() { this.source.removeListEventListener(this); } /** * Updates the value of this Calculation to include the information from * the newElement. * * @param newElement the new element within the EventList */ protected abstract void inserted(E newElement); /** * Updates the value of this Calculation to exclude the information from * the oldElement. * * @param oldElement the old element within the EventList */ protected abstract void deleted(E oldElement); /** * Updates the value of this Calculation to exclude the information from * the oldElement and include the information from the * newElement. * * @param oldElement the old element within the EventList * @param newElement the new element which replaced the oldElement */ protected abstract void updated(E oldElement, E newElement); /** * Updates the value of this Calculation in response to the * listChanges. * * @param listChanges describes the changes to the backing EventList */ public void listChanged(ListEvent listChanges) { // store the value for later when we fire a PropertyChangeEvent final N oldValue = getValue(); final List source = listChanges.getSourceList(); if (listChanges.isReordering()) { final int[] reorderMap = listChanges.getReorderMap(); for (int i = 0; i < reorderMap.length; i++) { final int oldIndex = reorderMap[i]; // if the element has changed indexes it must be processed like an update if (oldIndex != i) { final E newElement = source.get(i); final E oldElement = snapshot.set(i, newElement); updated(oldElement, newElement); } } } else { // update our snapshot and update the value of this Calculation by // delegating to the abstract methods which provide that updating logic while (listChanges.next()) { final int index = listChanges.getIndex(); switch (listChanges.getType()) { case ListEvent.INSERT: { final E element = source.get(index); snapshot.add(index, element); inserted(element); break; } case ListEvent.DELETE: { deleted(snapshot.remove(index)); break; } case ListEvent.UPDATE: { final E newElement = source.get(index); final E oldElement = snapshot.set(index, newElement); updated(oldElement, newElement); break; } } } } // fetch the new value of this Calculation and try to fire an event final N newValue = getValue(); fireValueChange(oldValue, newValue); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy