WeakAction.java
package sprouts.impl;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import sprouts.Action;
import java.lang.ref.WeakReference;
import java.util.Optional;
import java.util.function.BiConsumer;
/**
* A weak action is an extension of the {@link Action} interface
* which defines a method for clearing the action
* and a method for retrieving the owner of the action. <br>
* The owner is weakly referenced and determines the
* lifetime of the action. A library internal cleaner
* is responsible for removing the action when the owner
* is garbage collected.
* <p>
* This class is marked as {@code final} and its constructor is private
* to enforce the use of the static factory method {@link #of(Object, BiConsumer)}.
* The factory method provides a controlled way to create instances
* and encapsulates any additional logic required during instantiation.
* This design ensures consistency and prevents misuse.
* <p><b>
* Note: This class is designed for internal use within the Sprouts library
* and should not be made public or used directly by external code.
* </b></p>
*
* @param <O> The type of the owner of this action.
* @param <D> The type of the delegate that will be passed to this event handler.
*/
final class WeakAction<O, D> implements Action<D>
{
/**
* Creates a new instance of {@link WeakAction} with the given owner and action.
* The owner is weakly referenced, meaning that the action will be cleared
* when the owner is garbage collected.
*
* @param owner The owner of this action, which will be weakly referenced.
* @param action The action to be executed when this event handler is invoked.
* @return A new instance of {@link WeakAction}.
*/
static <O, D> WeakAction<O, D> of(@NonNull O owner, @NonNull BiConsumer<O, D> action ) {
return new WeakAction<>(owner, action);
}
private @Nullable BiConsumer<O, D> _action;
private final WeakReference<O> _owner;
private WeakAction(@NonNull O owner, @NonNull BiConsumer<O, D> action ) {
_owner = new WeakReference<>(owner);
_action = action;
}
@Override
public void accept( D delegate ) {
if ( _action == null )
return;
O owner = _owner.get();
if ( owner != null )
_action.accept(owner, delegate);
else
_action = null;
}
/**
* Returns an {@link Optional} containing the owner of this action.
* If the owner is no longer available, then an empty {@link Optional}
* is returned.
*
* @return An {@link Optional} containing the owner of this action.
*/
public Optional<O> owner() {
return Optional.ofNullable(_owner.get());
}
/**
* Clears the action, making it no longer executable.
* This method is called by the library internal cleaner
* when the owner is garbage collected.<br>
* <b>
* It is not advised to call this method manually,
* as it may lead to unexpected behavior.
* </b>
*/
public void clear() {
_action = null;
}
}