/*******************************************************************************
 * Copyright (c) 2008, 2015 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 * 
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.common.utility.internal.model.value;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.jpt.common.utility.internal.ArrayTools;
import org.eclipse.jpt.common.utility.internal.ObjectTools;
import org.eclipse.jpt.common.utility.internal.StringBuilderTools;
import org.eclipse.jpt.common.utility.internal.collection.CollectionTools;
import org.eclipse.jpt.common.utility.internal.collection.ListTools;
import org.eclipse.jpt.common.utility.internal.iterable.IterableTools;
import org.eclipse.jpt.common.utility.internal.iterable.ReadOnlyCompositeListIterable;
import org.eclipse.jpt.common.utility.internal.iterable.SingleElementIterable;
import org.eclipse.jpt.common.utility.internal.transformer.TransformerAdapter;
import org.eclipse.jpt.common.utility.internal.transformer.TransformerTools;
import org.eclipse.jpt.common.utility.iterable.ListIterable;
import org.eclipse.jpt.common.utility.model.event.ListAddEvent;
import org.eclipse.jpt.common.utility.model.event.ListChangeEvent;
import org.eclipse.jpt.common.utility.model.event.ListClearEvent;
import org.eclipse.jpt.common.utility.model.event.ListEvent;
import org.eclipse.jpt.common.utility.model.event.ListMoveEvent;
import org.eclipse.jpt.common.utility.model.event.ListRemoveEvent;
import org.eclipse.jpt.common.utility.model.event.ListReplaceEvent;
import org.eclipse.jpt.common.utility.model.listener.ListChangeAdapter;
import org.eclipse.jpt.common.utility.model.listener.ListChangeListener;
import org.eclipse.jpt.common.utility.model.value.CollectionValueModel;
import org.eclipse.jpt.common.utility.model.value.ListValueModel;
import org.eclipse.jpt.common.utility.transformer.Transformer;

/**
 * A <code>CompositeListValueModel</code> wraps another
 * {@link ListValueModel} and uses a {@link Transformer}
 * to convert each item in the wrapped list to yet another
 * {@link ListValueModel}. This composite list contains
 * the combined items from all these component lists.
 * <p>
 * Terminology:<ul>
 * <li><em>sources</em> - the items in the wrapped list value model; these
 *    are converted into component LVMs by the transformer
 * <li><em>component LVMs</em> - the component list value models that are combined
 *    by this composite list value model
 * <li><em>items</em> - the items held by the component LVMs
 * </ul>
 * 
 * @param <E1> the type of items held by the wrapped list model;
 *     each of these is transformed (by the {@link #transformer}) into a
 *     list model of <code>E2</code>s
 * @param <E2> the type of items held by the composite list model
 */
public class CompositeListValueModel<E1, E2>
	extends ListValueModelWrapper<E1>
	implements ListValueModel<E2>
{
	/**
	 * This is the (optional) user-supplied object that transforms
	 * the items in the wrapped list to list value models.
	 */
	private final Transformer<E1, ? extends ListValueModel<? extends E2>> transformer;

	/**
	 * Cache of the sources, component LVMs, lists.
	 */
	private final ArrayList<Info> infoList = new ArrayList<Info>();
	protected class Info {
		// the object passed to the transformer
		final E1 source;
		// the list value model generated by the transformer
		final ListValueModel<? extends E2> componentLVM;
		// cache of the items held by the component LVM
		final ArrayList<E2> items;
		// the component LVM's beginning index within the composite LVM
		int begin;
		protected Info(E1 source, ListValueModel<? extends E2> componentLVM, ArrayList<E2> items, int begin) {
			super();
			this.source = source;
			this.componentLVM = componentLVM;
			this.items = items;
			this.begin = begin;
		}
	}

	/** Listener that listens to all the component list value models. */
	private final ListChangeListener componentLVMListener;

	/** Cache the size of the composite list. */
	private int size;


	// ********** constructors **********

	/**
	 * Construct a list value model with the specified wrapped
	 * collection value model. The specified collection model already contains other
	 * list value models.
	 */
	public static <E1 extends ListValueModel<? extends E2>, E2> CompositeListValueModel<E1, E2> forModels(CollectionValueModel<E1> collectionModel) {
		return forModels(new CollectionListValueModelAdapter<E1>(collectionModel));
	}

	/**
	 * Construct a list value model with the specified wrapped list.
	 */
	public static <E1 extends ListValueModel<? extends E2>, E2> CompositeListValueModel<E1, E2> forModels(List<E1> list) {
		return forModels(new StaticListValueModel<E1>(list));
	}

	/**
	 * Construct a list value model with the specified wrapped list.
	 */
	public static <E1 extends ListValueModel<? extends E2>, E2> CompositeListValueModel<E1, E2> forModels(E1... list) {
		return forModels(new StaticListValueModel<E1>(list));
	}

	/**
	 * Construct a list value model with the specified wrapped
	 * list value model. The specified list
	 * model already contains other list value models.
	 */
	public static <E1 extends ListValueModel<? extends E2>, E2> CompositeListValueModel<E1, E2> forModels(ListValueModel<E1> listModel) {
		return new CompositeListValueModel<E1, E2>(listModel, TransformerTools.<E1>passThruTransformer());
	}

	/**
	 * Construct a list value model with the specified wrapped
	 * collection value model and transformer.
	 */
	public CompositeListValueModel(CollectionValueModel<? extends E1> collectionModel, Transformer<E1, ? extends ListValueModel<? extends E2>> transformer) {
		this(new CollectionListValueModelAdapter<E1>(collectionModel), transformer);
	}

	/**
	 * Construct a list value model with the specified, unchanging, wrapped
	 * list and transformer.
	 */
	public CompositeListValueModel(List<? extends E1> list, Transformer<E1, ? extends ListValueModel<? extends E2>> transformer) {
		this(new StaticListValueModel<E1>(list), transformer);
	}

	/**
	 * Construct a list value model with the specified, unchanging, wrapped
	 * list and transformer.
	 */
	public CompositeListValueModel(E1[] list, Transformer<E1, ? extends ListValueModel<? extends E2>> transformer) {
		this(new StaticListValueModel<E1>(list), transformer);
	}

	/**
	 * Construct a list value model with the specified wrapped
	 * list value model and transformer.
	 */
	public CompositeListValueModel(ListValueModel<? extends E1> listModel, Transformer<E1, ? extends ListValueModel<? extends E2>> transformer) {
		super(listModel);
		if (transformer == null) {
			throw new NullPointerException();
		}
		this.transformer = transformer;
		this.componentLVMListener = this.buildComponentLVMListener();
		this.size = 0;
	}


	// ********** initialization **********

	protected ListChangeListener buildComponentLVMListener() {
		return new ComponentListener();
	}

	protected class ComponentListener
		extends ListChangeAdapter
	{
		@Override
		public void itemsAdded(ListAddEvent event) {
			CompositeListValueModel.this.componentItemsAdded(event);
		}		
		@Override
		public void itemsRemoved(ListRemoveEvent event) {
			CompositeListValueModel.this.componentItemsRemoved(event);
		}
		@Override
		public void itemsReplaced(ListReplaceEvent event) {
			CompositeListValueModel.this.componentItemsReplaced(event);
		}
		@Override
		public void itemsMoved(ListMoveEvent event) {
			CompositeListValueModel.this.componentItemsMoved(event);
		}
		@Override
		public void listCleared(ListClearEvent event) {
			CompositeListValueModel.this.componentListCleared(event);
		}
		@Override
		public void listChanged(ListChangeEvent event) {
			CompositeListValueModel.this.componentListChanged(event);
		}
	}


	// ********** ListValueModel implementation **********

	public E2 get(int index) {
		if ((index < 0) || (index >= this.size)) {
			throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + this.size); //$NON-NLS-1$ //$NON-NLS-2$
		}
		// move backwards through the info list
		for (int i = this.infoList.size(); i-- > 0; ) {
			Info info = this.infoList.get(i);
			if (index >= info.begin) {
				return info.items.get(index - info.begin);
			}
		}
		throw new IllegalStateException();  // something is wack
	}

	public Iterator<E2> iterator() {
		return this.listIterator();
	}

	public ListIterator<E2> listIterator() {
		return this.buildListIterable().iterator();
	}

	protected ListIterable<E2> buildListIterable() {
		return new ReadOnlyCompositeListIterable<E2>(this.buildListsIterables());
	}

	protected ListIterable<ListIterable<E2>> buildListsIterables() {
		return IterableTools.transform(IterableTools.listIterable(this.infoList), new InfoTransformer());
	}

	protected class InfoTransformer
		extends TransformerAdapter<Info, ListIterable<E2>>
	{
		@Override
		public ListIterable<E2> transform(Info info) {
			return IterableTools.listIterable(info.items);
		}
	}

	public int size() {
		return this.size;
	}

	public Object[] toArray() {
		return ArrayTools.array(this.listIterator(), this.size);
	}


	// ********** ListValueModelWrapper overrides/implementation **********

	@Override
	protected void engageModel() {
		super.engageModel();
		// sync our cache *after* we start listening to the wrapped list,
		// since its value might change when a listener is added
		this.addComponentSources(0, this.listModel, this.listModel.size(), false);  // false = do not fire event
	}

	@Override
	protected void disengageModel() {
		super.disengageModel();
		// stop listening to the component LVMs...
		for (Info info : this.infoList) {
			info.componentLVM.removeListChangeListener(LIST_VALUES, this.componentLVMListener);
		}
		// ...and clear the cache
		this.infoList.clear();
		this.size = 0;
	}

	/**
	 * Some component sources were added; update our cache.
	 */
	@Override
	protected void itemsAdded(ListAddEvent event) {
		this.addComponentSources(event.getIndex(), this.getItems(event), event.getItemsSize(), true);  // true = fire event
	}

	/**
	 * Add infos corresponding to the specified sources to our cache.
	 * Fire the appropriate event if requested.
	 */
	protected void addComponentSources(int addedSourcesIndex, Iterable<? extends E1> addedSources, int addedSourcesSize, boolean fireEvent) {
		ArrayList<Info> newInfoList = new ArrayList<Info>(addedSourcesSize);
		// the 'items' are either tacked on to the end or
		// at the 'begin' index of the first 'info' that is being pushed back
		int newItemsIndex = (addedSourcesIndex == this.infoList.size()) ? this.size : this.infoList.get(addedSourcesIndex).begin;

		int begin = newItemsIndex;
		for (E1 source : addedSources) {
			ListValueModel<? extends E2> componentLVM = this.transformer.transform(source);
			componentLVM.addListChangeListener(LIST_VALUES, this.componentLVMListener);
			ArrayList<E2> items = new ArrayList<E2>(componentLVM.size());
			CollectionTools.addAll(items, componentLVM.listIterator());
			newInfoList.add(new Info(source, componentLVM, items, begin));
			begin += items.size();
		}
		this.infoList.addAll(addedSourcesIndex, newInfoList);
		int newItemsSize = begin - newItemsIndex;
		this.size += newItemsSize;

		// bump the 'begin' index for all the infos that were pushed back by the insert
		int movedInfosIndex = addedSourcesIndex + addedSourcesSize;
		for (int i = movedInfosIndex; i < this.infoList.size(); i++) {
			this.infoList.get(i).begin += newItemsSize;
		}

		if (fireEvent) {
			ArrayList<E2> newItems = new ArrayList<E2>(newItemsSize);
			for (int i = addedSourcesIndex; i < movedInfosIndex; i++) {
				newItems.addAll(this.infoList.get(i).items);
			}
			this.fireItemsAdded(LIST_VALUES, newItemsIndex, newItems);
		}
	}

	/**
	 * Some component sources were removed; update our cache.
	 */
	@Override
	protected void itemsRemoved(ListRemoveEvent event) {
		this.removeComponentSources(event.getIndex(), event.getItemsSize(), true);  // true = fire event
	}

	/**
	 * Remove the infos corresponding to the specified sources from our cache.
	 */
	protected void removeComponentSources(int removedSourcesIndex, int removedSourcesSize, boolean fireEvent) {
		int removedItemsIndex = this.infoList.get(removedSourcesIndex).begin;
		int movedSourcesIndex = removedSourcesIndex + removedSourcesSize;
		int movedItemsIndex = (movedSourcesIndex == this.infoList.size()) ? this.size : this.infoList.get(movedSourcesIndex).begin;
		int removedItemsSize = movedItemsIndex - removedItemsIndex;
		this.size -= removedItemsSize;

		List<Info> subList = this.infoList.subList(removedSourcesIndex, removedSourcesIndex + removedSourcesSize);
		ArrayList<Info> removedInfoList = new ArrayList<Info>(subList);  // make a copy
		subList.clear();

		// decrement the 'begin' index for all the infos that were moved forward by the deletes
		for (int i = removedSourcesIndex; i < this.infoList.size(); i++) {
			this.infoList.get(i).begin -= removedItemsSize;
		}

		for (Info removedInfo : removedInfoList) {
			removedInfo.componentLVM.removeListChangeListener(LIST_VALUES, this.componentLVMListener);
		}

		if (fireEvent) {
			ArrayList<E2> removedItems = new ArrayList<E2>(removedItemsSize);
			for (Info removedInfo : removedInfoList) {
				removedItems.addAll(removedInfo.items);
			}
			this.fireItemsRemoved(LIST_VALUES, removedItemsIndex, removedItems);
		}
	}

	/**
	 * Some component sources were replaced; update our cache.
	 */
	@Override
	protected void itemsReplaced(ListReplaceEvent event) {
		this.replaceComponentSources(event.getIndex(), this.getNewItems(event), event.getItemsSize(), true);  // true = fire event
	}

	/**
	 * Replaced component sources will not (typically) map to a set of replaced
	 * items, so we remove and add the corresponding lists of items, resulting in
	 * two events.
	 */
	protected void replaceComponentSources(int replacedSourcesIndex, Iterable<? extends E1> newSources, int replacedSourcesSize, boolean fireEvent) {
		this.removeComponentSources(replacedSourcesIndex, replacedSourcesSize, fireEvent);
		this.addComponentSources(replacedSourcesIndex, newSources, replacedSourcesSize, fireEvent);
	}

	/**
	 * Some component sources were moved; update our cache.
	 */
	@Override
	protected void itemsMoved(ListMoveEvent event) {
		this.moveComponentSources(event.getTargetIndex(), event.getSourceIndex(), event.getLength(), true);  // true = fire event
	}

	protected void moveComponentSources(int targetSourcesIndex, int sourceSourcesIndex, int movedSourcesLength, boolean fireEvent) {
		int sourceItemsIndex = this.infoList.get(sourceSourcesIndex).begin;

		int nextSourceSourceIndex = sourceSourcesIndex + movedSourcesLength;
		int nextSourceItemIndex = (nextSourceSourceIndex == this.infoList.size()) ? this.size : this.infoList.get(nextSourceSourceIndex).begin;
		int moveItemsLength = nextSourceItemIndex - sourceItemsIndex;

		int targetItemsIndex = -1;
		if (sourceSourcesIndex > targetSourcesIndex) {
			// move from high to low index
			targetItemsIndex = this.infoList.get(targetSourcesIndex).begin;
		} else {
			// move from low to high index (higher items move down during move)
			int nextTargetSourceIndex = targetSourcesIndex + movedSourcesLength;
			targetItemsIndex = (nextTargetSourceIndex == this.infoList.size()) ? this.size : this.infoList.get(nextTargetSourceIndex).begin;
			targetItemsIndex = targetItemsIndex - moveItemsLength;
		}

		ListTools.move(this.infoList, targetSourcesIndex, sourceSourcesIndex, movedSourcesLength);

		// update the 'begin' indexes of all the affected 'infos'
		int min = Math.min(targetSourcesIndex, sourceSourcesIndex);
		int max = Math.max(targetSourcesIndex, sourceSourcesIndex) + movedSourcesLength;
		int begin = Math.min(targetItemsIndex, sourceItemsIndex);
		for (int i = min; i < max; i++) {
			Info info = this.infoList.get(i);
			info.begin = begin;
			begin += info.componentLVM.size();
		}

		if (fireEvent) {
			this.fireItemsMoved(LIST_VALUES, targetItemsIndex, sourceItemsIndex, moveItemsLength);
		}
	}

	/**
	 * The component sources were cleared; clear our cache.
	 */
	@Override
	protected void listCleared(ListClearEvent event) {
		this.clearComponentSources();
	}

	protected void clearComponentSources() {
		this.removeComponentSources(0, this.infoList.size(), false);  // false = do not fire event
		this.fireListCleared(LIST_VALUES);
	}

	/**
	 * The component sources changed; rebuild our cache.
	 */
	@Override
	protected void listChanged(ListChangeEvent event) {
		int newSize = this.listModel.size();
		if (newSize == 0) {
			this.clearComponentSources();
			return;
		}

		int oldSize = this.infoList.size();
		if (oldSize == 0) {
			this.addComponentSources(0, this.listModel, newSize, true);  // true = fire event
			return;
		}

		int min = Math.min(newSize, oldSize);
		// handle replaced sources individually so we don't fire events for unchanged sources
		for (int i = 0; i < min; i++) {
			E1 newSource = this.listModel.get(i);
			E1 oldSource = this.infoList.get(i).source;
			if (ObjectTools.notEquals(newSource, oldSource)) {
				this.replaceComponentSources(i, new SingleElementIterable<E1>(newSource), 1, true);  // true = fire event
			}
		}

		if (newSize == oldSize) {
			return;
		}

		if (newSize < oldSize) {
			this.removeComponentSources(min, oldSize - newSize, true);  // true = fire event
			return;
		}

		// newSize > oldSize
		this.addComponentSources(min, this.buildSubListHolder(min), newSize - oldSize, true);  // true = fire event
	}

	protected Iterable<? extends E1> buildSubListHolder(int fromIndex) {
		int listModelSize = this.listModel.size();
		return ListTools.arrayList(this.listModel, listModelSize).subList(fromIndex, listModelSize);
	}

	protected Iterable<? extends E1> buildSubListHolder(int fromIndex, int toIndex) {
		int listModelSize = this.listModel.size();
		return ((fromIndex == 0) && (toIndex == listModelSize)) ?
				this.listModel :
				ListTools.arrayList(this.listModel, listModelSize).subList(fromIndex, toIndex);
	}

	@Override
	public void toString(StringBuilder sb) {
		StringBuilderTools.append(sb, this);
	}


	// ********** internal methods **********

	/**
	 * Return the index of the specified component LVM.
	 */
	protected int indexOf(ListValueModel<E2> componentLVM) {
		for (int i = 0; i < this.infoList.size(); i++) {
			if (this.infoList.get(i).componentLVM == componentLVM) {
				return i;
			}
		}
		throw new IllegalArgumentException("invalid component LVM: " + componentLVM); //$NON-NLS-1$
	}

	/**
	 * Return the index of the specified event's component LVM.
	 */
	protected int indexFor(ListEvent event) {
		return this.indexOf(this.getComponentLVM(event));
	}

	/**
	 * Items were added to one of the component lists;
	 * synchronize our cache.
	 */
	protected void componentItemsAdded(ListAddEvent event) {
		int componentLVMIndex = this.indexFor(event);
		this.addComponentItems(componentLVMIndex, this.infoList.get(componentLVMIndex), event.getIndex(), this.getComponentItems(event), event.getItemsSize());
	}

	protected void addComponentItems(int componentLVMIndex, Info info, int addedItemsIndex, Iterable<? extends E2> addedItems, int addedItemsSize) {
		// update the affected 'begin' indices
		for (int i = componentLVMIndex + 1; i < this.infoList.size(); i++) {
			this.infoList.get(i).begin += addedItemsSize;
		}
		this.size += addedItemsSize;

		// synchronize the cached list
		ListTools.addAll(info.items, addedItemsIndex, addedItems, addedItemsSize);

		// translate the event
		this.fireItemsAdded(LIST_VALUES, info.begin + addedItemsIndex, info.items.subList(addedItemsIndex, addedItemsIndex + addedItemsSize));
	}

	/**
	 * Items were removed from one of the component lists;
	 * synchronize our cache.
	 */
	protected void componentItemsRemoved(ListRemoveEvent event) {
		// update the affected 'begin' indices
		int componentLVMIndex = this.indexFor(event);
		int removedItemsSize = event.getItemsSize();
		for (int i = componentLVMIndex + 1; i < this.infoList.size(); i++) {
			this.infoList.get(i).begin -= removedItemsSize;
		}
		this.size -= removedItemsSize;

		// synchronize the cached list
		Info info = this.infoList.get(componentLVMIndex);
		int itemIndex = event.getIndex();
		info.items.subList(itemIndex, itemIndex + event.getItemsSize()).clear();

		// translate the event
		this.fireItemsRemoved(event.clone(this, LIST_VALUES, info.begin));
	}

	/**
	 * Items were replaced in one of the component lists;
	 * synchronize our cache.
	 */
	protected void componentItemsReplaced(ListReplaceEvent event) {
		// no changes to the 'begin' indices or size

		// synchronize the cached list
		int componentLVMIndex = this.indexFor(event);
		Info info = this.infoList.get(componentLVMIndex);
		int i = event.getIndex();
		for (E2 item : this.getComponentItems(event)) {
			info.items.set(i++, item);
		}

		// translate the event
		this.fireItemsReplaced(event.clone(this, LIST_VALUES, info.begin));
	}

	/**
	 * Items were moved in one of the component lists;
	 * synchronize our cache.
	 */
	protected void componentItemsMoved(ListMoveEvent event) {
		// no changes to the 'begin' indices or size

		// synchronize the cached list
		int componentLVMIndex = this.indexFor(event);
		Info info = this.infoList.get(componentLVMIndex);
		ListTools.move(info.items, event.getTargetIndex(), event.getSourceIndex(), event.getLength());

		// translate the event
		this.fireItemsMoved(event.clone(this, LIST_VALUES, info.begin));
	}

	/**
	 * One of the component lists was cleared;
	 * synchronize our cache.
	 */
	protected void componentListCleared(ListClearEvent event) {
		int componentLVMIndex = this.indexFor(event);
		this.clearComponentList(componentLVMIndex, this.infoList.get(componentLVMIndex));
	}

	protected void clearComponentList(int componentLVMIndex, Info info) {
		// update the affected 'begin' indices
		int removedItemsSize = info.items.size();
		if (removedItemsSize == 0) {
			return;
		}

		for (int i = componentLVMIndex + 1; i < this.infoList.size(); i++) {
			this.infoList.get(i).begin -= removedItemsSize;
		}
		this.size -= removedItemsSize;

		// synchronize the cached list
		ArrayList<E2> items = new ArrayList<E2>(info.items);  // make a copy
		info.items.clear();

		// translate the event
		this.fireItemsRemoved(LIST_VALUES, info.begin, items);
	}

	/**
	 * One of the component lists changed;
	 * synchronize our cache by synchronizing the appropriate
	 * list and firing the appropriate events.
	 */
	protected void componentListChanged(ListChangeEvent event) {
		int componentLVMIndex = this.indexFor(event);
		Info info = this.infoList.get(componentLVMIndex);

		int newItemsSize = info.componentLVM.size();
		if (newItemsSize == 0) {
			this.clearComponentList(componentLVMIndex, info);
			return;
		}

		int oldItemsSize = info.items.size();
		if (oldItemsSize == 0) {
			this.addComponentItems(componentLVMIndex, info, 0, info.componentLVM, newItemsSize);
			return;
		}

		int min = Math.min(newItemsSize, oldItemsSize);
		// handle replaced items individually so we don't fire events for unchanged items
		for (int i = 0; i < min; i++) {
			E2 newItem = info.componentLVM.get(i);
			E2 oldItem = info.items.set(i, newItem);
			this.fireItemReplaced(LIST_VALUES, info.begin + i, newItem, oldItem);
		}

		int delta = newItemsSize - oldItemsSize;
		if (delta == 0) {  // newItemsSize == oldItemsSize
			return;
		}

		for (int i = componentLVMIndex + 1; i < this.infoList.size(); i++) {
			this.infoList.get(i).begin += delta;
		}
		this.size += delta;

		if (delta < 0) {  // newItemsSize < oldItemsSize
			List<E2> subList = info.items.subList(newItemsSize, oldItemsSize);
			ArrayList<E2> removedItems = new ArrayList<E2>(subList);  // make a copy
			subList.clear();
			this.fireItemsRemoved(LIST_VALUES, info.begin + newItemsSize, removedItems);
			return;
		}

		// newItemsSize > oldItemsSize
		ArrayList<E2> addedItems = new ArrayList<E2>(delta);
		for (int i = oldItemsSize; i < newItemsSize; i++) {
			addedItems.add(info.componentLVM.get(i));
		}
		info.items.addAll(addedItems);
		this.fireItemsAdded(LIST_VALUES, info.begin + oldItemsSize, addedItems);
	}

	// minimize scope of suppressed warnings
	@SuppressWarnings("unchecked")
	protected Iterable<E2> getComponentItems(ListAddEvent event) {
		return (Iterable<E2>) event.getItems();
	}

	// minimize scope of suppressed warnings
	@SuppressWarnings("unchecked")
	protected Iterable<E2> getComponentItems(ListReplaceEvent event) {
		return (Iterable<E2>) event.getNewItems();
	}

	// minimize scope of suppressed warnings
	@SuppressWarnings("unchecked")
	protected ListValueModel<E2> getComponentLVM(ListEvent event) {
		return (ListValueModel<E2>) event.getSource();
	}
}
