blob: 0f88a5676f3fd78b8cfac8d29b36beba98515140 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2012 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 org.eclipse.jpt.common.utility.Filter;
import org.eclipse.jpt.common.utility.model.event.CollectionChangeEvent;
import org.eclipse.jpt.common.utility.model.event.CollectionClearEvent;
import org.eclipse.jpt.common.utility.model.value.CollectionValueModel;
/**
* Adapt an element in a collection value model to a property value model.
* The property model's value is determined by whether the collection model
* contains the value: If the collection model contains the value,
* the property model's value is <em>that</em> element; otherwise, the property
* model's value is <code>null</code>. A {@link #predicate} is used to determine
* whether the collection model contains the relevant value.
* <p>
* This is useful for a client (e.g. a UI widget) that is longer-living than its
* underlying model. Obviously, the client must be prepared to handle a value of
* <code>null</code>.
*
* @param <V> the type of the both the model's value and
* the wrapped collection value model's elements
*/
public class ElementPropertyValueModelAdapter<V>
extends CollectionPropertyValueModelAdapter<V, V>
{
/**
* A predicate used to determine whether an element in the wrapped
* collection model is the model's value.
*/
protected final Filter<V> predicate;
/**
* Construct a property value model whose value depends on whether the
* specified collection value model contains the value. The specified
* filter is used to determine whether an element in the specified
* collection model is the property value.
*/
public ElementPropertyValueModelAdapter(CollectionValueModel<? extends V> collectionModel, Filter<V> predicate) {
super(collectionModel);
if (predicate == null) {
throw new NullPointerException();
}
this.predicate = predicate;
}
/**
* If the collection model contains the property model's {@link #value},
* return that element; otherwise return <code>null</code>.
*/
@Override
protected V buildValue() {
for (V each : this.collectionModel) {
if (this.predicate.accept(each)) {
return each;
}
}
return null;
}
/**
* Check whether the wrapped collection model now contains the
* {@link #value}.
*/
@Override
protected void itemsAdded(Iterable<V> items) {
if (this.value == null) {
this.itemsAdded_(items);
}
}
protected void itemsAdded_(Iterable<V> items) {
for (V each : items) {
if (this.predicate.accept(each)) {
this.firePropertyChanged(VALUE, null, this.value = each);
return;
}
}
}
/**
* Check whether the wrapped collection model no longer contains the
* {@link #value}.
*/
@Override
protected void itemsRemoved(Iterable<V> items) {
if (this.value != null) {
this.itemsRemoved_(items);
}
}
protected void itemsRemoved_(Iterable<V> items) {
for (V each : items) {
if (this.valuesAreEqual(each, this.value)) {
V old = this.value;
this.firePropertyChanged(VALUE, old, this.value = null);
return;
}
}
}
/**
* The {@link #value} must now be <code>null</code>.
*/
@Override
protected void collectionCleared(CollectionClearEvent event) {
if (this.value != null) {
V old = this.value;
this.firePropertyChanged(VALUE, old, this.value = null);
}
}
/**
* Re-calculate the {@link #value}.
*/
@Override
protected void collectionChanged(CollectionChangeEvent event) {
V old = this.value;
this.firePropertyChanged(VALUE, old, this.value = this.buildValue());
}
}