package org.codefx.libfx.control.properties;
import java.util.Objects;
import java.util.function.Consumer;
import javafx.collections.ObservableMap;
/**
* Implementation of {@link ControlPropertyListenerHandle} which optimistically casts all values to the expected type.
* If that does not work, the {@link ClassCastException} is caught and ignored.
*
* @param <T>
* the type of values which the listener processes
*/
final class CastingControlPropertyListenerHandle<T> extends AbstractControlPropertyListenerHandle {
/**
* The user specified processor for values.
*/
private final Consumer<? super T> valueProcessor;
/**
* Creates a new listener handle. Initially detached.
*
* @param properties
* the {@link ObservableMap} holding the properties
* @param key
* the key to which the listener will listen
* @param valueProcessor
* the {@link Consumer} for the key's values
*/
CastingControlPropertyListenerHandle(
ObservableMap<Object, Object> properties, Object key, Consumer<? super T> valueProcessor) {
super(properties, key);
Objects.requireNonNull(valueProcessor, "The argument 'valueProcessor' must not be null.");
this.valueProcessor = valueProcessor;
}
@Override
protected boolean processValueIfPossible(Object value) {
// give the value to the consumer if it has the correct type
try {
// note that this cast does nothing except to calm the compiler
@SuppressWarnings("unchecked")
T convertedValue = (T) value;
// this is where the exception might actually be created
valueProcessor.accept(convertedValue);
return true;
} catch (ClassCastException e) {
// the value was of the wrong type so it can't be processed by the consumer
return false;
}
}
}