Component.java
package neureka.common.composition;
import neureka.Tensor;
import neureka.backend.api.BackendContext;
/**
* This interface alongside the {@link AbstractComponentOwner} class define a simple component system.
* The component type defined by this interface is used to create components for the {@link Tensor} class
* as well as the {@link BackendContext} class which both directly or indirectly
* extend the {@link AbstractComponentOwner} class.
* The type parameter of this interface represents the "owner" of the {@link Component}.
*
* @param <O> The owner type of which an implementation of this interface is a component.
*/
public interface Component<O>
{
/**
* Entries of this enum represent events describing updates to the state
* of the owner of a given {@link Component} instance.
*/
enum IsBeing { REMOVED, ADDED, REPLACED, UPDATED }
/**
* {@link OwnerChangeRequest} implementation instances will be passed to
* the {@link Component#update(OwnerChangeRequest)} method which inform a
* given component about a state change related to said component.
* They are used by component owners to communicate and
* negotiate update events to their components using the {@link IsBeing} enum and
* some useful methods providing both a context for a component and the ability
* for the component to trigger the state change itself.
*
* @param <O> The type parameter representing the concrete type of the component owner.
*/
interface OwnerChangeRequest<O>
{
/**
* @return The previous owner type instance or null if the component is being added to the owner.
*/
O getOldOwner();
/**
* @return The new owner type instance.
*/
O getNewOwner();
/**
* This method will trigger the actual state change identified by the {@link IsBeing}
* constant returned by the {@link #type()} method.
* It exists so that a component can decide when the change should occur.
* If the change type is set to {@link IsBeing#ADDED} for example then this would
* mean that after calling this method, the current component will now be a
* component of the current component owner.
*
* @return The truth value determining if the state change was successfully executed.
*/
boolean executeChange();
/**
* This method will return one of the following states:
* {@link IsBeing#ADDED}, {@link IsBeing#REMOVED}, {@link IsBeing#REPLACED}, {@link IsBeing#UPDATED}
*
* @return The type of change that is about to happen to the component receiving this.
*/
default IsBeing type() {
if ( getOldOwner() != null && getNewOwner() != null ) return IsBeing.REPLACED;
if ( getOldOwner() != null && getNewOwner() == null ) return IsBeing.REMOVED;
if ( getOldOwner() == null && getNewOwner() != null ) return IsBeing.ADDED;
return IsBeing.UPDATED;
}
}
/**
* Components are not the slaves of their owners.
* If the owner registers any state changes related to a given component, then
* said component will be informed by the owner about the change as well as receive
* the ability to decide when the change should occur or if the change should occur at all.
* This method informs the component about state changes within the owner
* A typical state change would be an owner switch or simply that this component
* is being added to, or removed from, its current owner.
* If components hold references to their owners then this method gives them
* the ability to update said reference when a new owner takes over the components of an old one.
* The {@link OwnerChangeRequest} implementation instance passed to this method
* informs this component about the current state change and its type ({@link OwnerChangeRequest#type()}).
* If this method returns false then this means that this component rejects the proposed update.
* The component owner will then abort the proposed change.
*
* @param changeRequest An {@link OwnerChangeRequest} implementation instance used to communicate the type of change, context information and the ability to execute the change directly.
* @return The truth value determining if the state change should be aborted or not.
*/
default boolean update( OwnerChangeRequest<O> changeRequest ) {
changeRequest.executeChange(); // This can be an 'add', 'remove' or 'transfer' of this component!
return true;
}
}