public abstract class AbstractSimEntity extends Object implements SimEntity
SimEntity.
See SimEntity and the constructor documentation for more details.
For a more complete (though still partial) implementations of jobs and queues, see AbstractSimJQ.
Copyright (C) 2005-2017 Jan de Jongh, TNO
This file is covered by the LICENSE file in the root of this project.
AbstractSimJQ,
SimQueue,
SimJob| Modifier and Type | Class and Description |
|---|---|
static interface |
AbstractSimEntity.Notifier
A functional interface for a notification handler.
|
static interface |
AbstractSimEntity.PreNotificationHook
A functional interface for a hook to be called before notifications are sent (i.e., before a state change is advertised).
|
SimEntity.Action, SimEntity.UnknownNotificationTypePolicy, SimEntity.UnknownOperationPolicy| Modifier and Type | Field and Description |
|---|---|
protected static boolean |
USE_ARRAY_OPTIMIZATION
When
true, this class and some sub-classes maintain various array copies of collections
often iterated over, like listeners and hooks, and uses array iteration instead of Collection iteration. |
| Constructor and Description |
|---|
AbstractSimEntity(org.javades.jsimulation.r5.SimEventList eventList,
String name)
Creates a new
SimEntity with given event list and name. |
| Modifier and Type | Method and Description |
|---|---|
protected void |
addPendingNotification(Map<SimEntitySimpleEventType.Member,SimEntityEvent> notification)
Adds a notification to the pending notifications.
|
protected void |
addPendingNotification(SimEntitySimpleEventType.Member notificationType,
SimEntityEvent notification)
Adds a notification to the pending notifications.
|
protected boolean |
clearAndUnlockPendingNotificationsIfLocked()
Clears the pending notifications and unlocks them if needed (i.e., if currently locked).
|
protected void |
delegateOperation(SimEntityOperation operation,
SimEntityOperation delegateOperation)
Delegates a registered
SimEntityOperation at this entity to another operation. |
void |
doAfterNotifications(SimEntity.Action action)
Adds a (one-time) action to take immediately after firing pending notifications has ended.
|
<O extends SimEntityOperation,Req extends SimEntityOperation.Request,Rep extends SimEntityOperation.Reply> |
doOperation(double time,
Req request)
Performs the requested operation.
|
protected void |
fireAndLockPendingNotifications()
Fires and locks the pending notifications to listeners.
|
org.javades.jsimulation.r5.SimEventList |
getEventList()
Returns the underlying event list.
|
double |
getLastUpdateTime()
Gets the time of the last update of this entity.
|
Set<SimEntityOperation> |
getRegisteredDelegatedOperations()
Returns the registered delegated operations.
|
Set<SimEntitySimpleEventType.Member> |
getRegisteredNotificationTypes()
Gets the registered notification types of this entity.
|
Set<SimEntityOperation> |
getRegisteredOperations()
Gets the registered operations of this entity.
|
Set<SimEntityListener> |
getSimEntityListeners()
Gets the listeners to this entity.
|
SimEntity.UnknownNotificationTypePolicy |
getUnknownNotificationTypePolicy()
Returns the policy for unknown notifications types.
|
SimEntity.UnknownOperationPolicy |
getUnknownOperationPolicy()
Returns the policy for unknown operations.
|
boolean |
isIgnoreEventListReset()
Returns whether this entity ignores event-list resets.
|
void |
notifyEventListReset(org.javades.jsimulation.r5.SimEventList eventList)
Calls
resetEntity(), unless this entity ignores event-list reset notifications. |
protected void |
registerDelegatedOperation(SimEntityOperation operation,
SimEntityOperation delegateOperation)
Registers a
SimEntityOperation at this entity, but delegates it to another operation. |
protected void |
registerNotificationType(SimEntitySimpleEventType.Member notificationType,
AbstractSimEntity.Notifier notifier)
Registers a mapping between a notification type (reset, arrival, departures, etc.) and a
AbstractSimEntity.Notifier for it. |
protected void |
registerOperation(SimEntityOperation operation)
Registers a
SimEntityOperation at this entity. |
protected void |
registerPreEventHook(DoubleConsumer preEventHook)
Registers a pre-event hook (for sub-class use only).
|
protected void |
registerPreNotificationHook(AbstractSimEntity.PreNotificationHook preNotificationHook)
Registers a pre-notification hook.
|
protected void |
registerPreUpdateHook(DoubleConsumer preUpdateHook)
Registers a pre-update hook (for sub-class use only).
|
void |
registerSimEntityListener(SimEntityListener listener)
Registers a listener to event notifications related to this entity.
|
void |
registerStdOutSimEntityListener()
Registers the (private)
StdOutSimEntityListener as listener (convenience method). |
protected void |
removeDelegationForOperation(SimEntityOperation operation)
Removes the delegation for given
SimEntityOperation, but keeps the operation registered
(falling back onto its native behavior}. |
void |
resetEntity()
Copies the last-update time from the event list (if available),
invokes
resetEntitySubClass() and fires the event to listeners (as a state-change event and through a
separate reset indication). |
protected void |
resetEntitySubClass()
Does nothing.
|
void |
setIgnoreEventListReset(boolean ignoreEventListReset)
Sets whether this entity ignores future event-list resets.
|
void |
setName(String name)
Sets the name of this
SimEntity, to be returned by subsequent calls to Object.toString (). |
void |
setUnknownNotificationTypePolicy(SimEntity.UnknownNotificationTypePolicy unknownNotificationTypePolicy)
Sets the policy for unknown notifications types.
|
void |
setUnknownOperationPolicy(SimEntity.UnknownOperationPolicy unknownOperationPolicy)
Sets the policy for unknown operations.
|
String |
toString()
Returns the internally stored user-supplied name, if non-
null, or the type specific default. |
String |
toStringDefault()
Returns "AbstractSimEntity".
|
void |
unregisterSimEntityListener(SimEntityListener listener)
Unregisters a listener to event notifications related to this entity.
|
void |
unregisterStdOutSimEntityListener()
Unregisters the (private)
StdOutSimEntityListener as listener, if registered (convenience method). |
void |
update(double time)
Updates this entity.
|
protected static final boolean USE_ARRAY_OPTIMIZATION
true, this class and some sub-classes maintain various array copies of collections
often iterated over, like listeners and hooks, and uses array iteration instead of Collection iteration.public AbstractSimEntity(org.javades.jsimulation.r5.SimEventList eventList,
String name)
SimEntity with given event list and name.
The constructor registers the event list and the name (the latter can be set at any time, see setName(java.lang.String)).
It then registers the reset and update operations and notifications through registerOperation(org.javades.jqueues.r5.entity.SimEntityOperation)
and registerNotificationType(org.javades.jqueues.r5.entity.SimEntitySimpleEventType.Member, org.javades.jqueues.r5.entity.AbstractSimEntity.Notifier).
Finally, if available, it copies the time from the event list, and adds itself as (reset) listener to the event list.
(We are a SimEventListResetListener.)
eventList - The event list to use, may be null.name - The name of the entity, may be null.getEventList(),
toStringDefault(),
setName(java.lang.String),
registerOperation(org.javades.jqueues.r5.entity.SimEntityOperation),
SimEntityOperation.Reset,
SimEntityOperation.Update,
SimEntitySimpleEventType.RESET,
getLastUpdateTime(),
SimEventList.addListener(org.javades.jsimulation.r5.SimEventListResetListener),
SimEventListResetListenerpublic final org.javades.jsimulation.r5.SimEventList getEventList()
The event list is fixed and supplied in the constructor.
It is non-null for SimQueues; may be null for other subclasses.
getEventList in interface SimEntitynull for SimQueues; may be null for other subclasses.public final void setName(String name)
SimEntitySimEntity, to be returned by subsequent calls to Object.toString ().setName in interface SimEntityname - The new name of this job or queue; if non-null, the string will be returned by subsequent calls
to Object.toString () (recommended implementation!);
otherwise, the type-specific default SimEntity.toStringDefault() will be used for that.SimEntity.toStringDefault()public String toStringDefault()
toStringDefault in interface SimEntitySimEntity.setName(java.lang.String),
Object.toString()public String toString()
null, or the type specific default.toString in class Objectnull, or the type specific default.setName(java.lang.String),
toStringDefault()public final Set<SimEntityOperation> getRegisteredOperations()
SimEntitygetRegisteredOperations in interface SimEntitySimEntityOperationprotected final void registerOperation(SimEntityOperation operation)
SimEntityOperation at this entity.operation - The operation, non-null.IllegalArgumentException - If the operation is null or already registered.public final Set<SimEntityOperation> getRegisteredDelegatedOperations()
The set returned is always a subset of all registered operations.
getRegisteredOperations()protected final void registerDelegatedOperation(SimEntityOperation operation, SimEntityOperation delegateOperation)
SimEntityOperation at this entity, but delegates it to another operation.operation - The operation, non-null.delegateOperation - The delegate operation, non-null.IllegalArgumentException - If the operation is null or already registered,
or if the delegate operation is null.protected final void delegateOperation(SimEntityOperation operation, SimEntityOperation delegateOperation)
SimEntityOperation at this entity to another operation.operation - The operation, non-null.delegateOperation - The delegate operation, non-null.IllegalArgumentException - If the operation is null or not registered,
or if the delegate operation is null.protected final void removeDelegationForOperation(SimEntityOperation operation)
SimEntityOperation, but keeps the operation registered
(falling back onto its native behavior}.operation - The operation, non-null.IllegalArgumentException - If the operation is null or not registered or not delegated.public final SimEntity.UnknownOperationPolicy getUnknownOperationPolicy()
SimEntitygetUnknownOperationPolicy in interface SimEntitynull.SimEntityOperation,
SimEntity.doOperation(double, Req)public final void setUnknownOperationPolicy(SimEntity.UnknownOperationPolicy unknownOperationPolicy)
SimEntitysetUnknownOperationPolicy in interface SimEntityunknownOperationPolicy - The new policy for unknown operations, non-null.SimEntityOperation,
SimEntity.doOperation(double, Req)public final <O extends SimEntityOperation,Req extends SimEntityOperation.Request,Rep extends SimEntityOperation.Reply> Rep doOperation(double time, Req request)
doOperation in interface SimEntityO - The operation type.Req - The request type (corresponding to the operation type).Rep - The reply type (corresponding to the operation type).time - The time of the request.request - The request, non-null.IllegalArgumentException - If the entity or request is null, the operation is null,
time is in the past (except for the SimEntityOperation.Reset operation,
the request has target entity other than this,
the is of illegal type, or its parameter values are illegal.getRegisteredOperations(),
registerDelegatedOperation(org.javades.jqueues.r5.entity.SimEntityOperation, org.javades.jqueues.r5.entity.SimEntityOperation),
SimEntity.UnknownOperationPolicy,
getUnknownOperationPolicy()protected final void registerNotificationType(SimEntitySimpleEventType.Member notificationType, AbstractSimEntity.Notifier notifier)
AbstractSimEntity.Notifier for it.
The notifier may be null, meaning the notification type is (will be) known, and will be
reported through SimEntityListener.notifyStateChanged(double, org.javades.jqueues.r5.entity.SimEntity, java.util.List<java.util.Map<org.javades.jqueues.r5.entity.SimEntitySimpleEventType.Member, org.javades.jqueues.r5.entity.SimEntityEvent>>),
but no additional actions/notifications (through a AbstractSimEntity.Notifier) will be taken on listeners.
notificationType - The notification type; non-null and not yet registered.notifier - The AbstractSimEntity.Notifier for it, may be null.IllegalArgumentException - If the notification type is null or already registered.public final Set<SimEntitySimpleEventType.Member> getRegisteredNotificationTypes()
SimEntitygetRegisteredNotificationTypes in interface SimEntitypublic final SimEntity.UnknownNotificationTypePolicy getUnknownNotificationTypePolicy()
SimEntitygetUnknownNotificationTypePolicy in interface SimEntitynull.public final void setUnknownNotificationTypePolicy(SimEntity.UnknownNotificationTypePolicy unknownNotificationTypePolicy)
SimEntitysetUnknownNotificationTypePolicy in interface SimEntityunknownNotificationTypePolicy - The new policy for unknown notification types, non-null.protected final void registerPreNotificationHook(AbstractSimEntity.PreNotificationHook preNotificationHook)
preNotificationHook - The hook, non-null.IllegalArgumentException - If the hook is null or already registered.public final void doAfterNotifications(SimEntity.Action action)
If this entity is not firing notifications, the action is invoked immediately.
doAfterNotifications in interface SimEntityaction - The action to take, non-null.IllegalArgumentException - If the action is null.fireAndLockPendingNotifications()protected final void addPendingNotification(Map<SimEntitySimpleEventType.Member,SimEntityEvent> notification)
notification - The notification, non-null.IllegalArgumentException - If the notification is null,
if the map is of illegal size (other than unity), or has a null key,
if the notification is already present
or has time different from the pending-notifications time,
if this entity is locked for pending notifications mutations,
or is currently firing notifications.protected final void addPendingNotification(SimEntitySimpleEventType.Member notificationType, SimEntityEvent notification)
Convenience method to addPendingNotification(java.util.Map) creating a singleton map from the arguments on the fly.
notificationType - The notification type, non-null.notification - The notification event, non-null.IllegalArgumentException - If the notification type or event is null or if
addPendingNotification(java.util.Map) encounters an error in the arguments.protected final boolean clearAndUnlockPendingNotificationsIfLocked()
This method does nothing if the pending notifications are already locked.
IllegalStateException - If this entity is currently firing notifications.firingPendingNotificationsprotected final void fireAndLockPendingNotifications()
Fires, if present, pre-notification hooks and post-notification actions, even if the set of pending notifications is empty. The post-notification actions are cleared.
Note that listeners are not notified with empty notification sets!
IllegalStateException - If the time of pending notifications is not equal to getLastUpdateTime(),
or if this entity is currently firing notifications (already).registerPreNotificationHook(org.javades.jqueues.r5.entity.AbstractSimEntity.PreNotificationHook),
doAfterNotifications(org.javades.jqueues.r5.entity.SimEntity.Action)public final void registerSimEntityListener(SimEntityListener listener)
SimEntityImplementations are encouraged to consider the use of weak/soft references to registered listeners.
registerSimEntityListener in interface SimEntitylistener - The listener; ignored if already registered or null.SimEntityListener,
SimEntity.unregisterSimEntityListener(org.javades.jqueues.r5.entity.SimEntityListener),
SimEntity.getSimEntityListeners()public final void unregisterSimEntityListener(SimEntityListener listener)
SimEntityunregisterSimEntityListener in interface SimEntitylistener - The listener; ignored if not registered or null.SimEntityListener,
SimEntity.registerSimEntityListener(org.javades.jqueues.r5.entity.SimEntityListener),
SimEntity.getSimEntityListeners()public final Set<SimEntityListener> getSimEntityListeners()
SimEntityCallers must not attempt to change the returned set.
Implementations are encouraged to return read-only views.
getSimEntityListeners in interface SimEntitySimEntityListener,
SimEntity.registerSimEntityListener(org.javades.jqueues.r5.entity.SimEntityListener),
SimEntity.unregisterSimEntityListener(org.javades.jqueues.r5.entity.SimEntityListener),
SimEntity.getSimEntityListeners()public final void registerStdOutSimEntityListener()
StdOutSimEntityListener as listener (convenience method).public final void unregisterStdOutSimEntityListener()
StdOutSimEntityListener as listener, if registered (convenience method).protected void resetEntitySubClass()
Implementation of SimEntity.resetEntity() in subclasses without notifying listeners.
As it is essential to issue a single SimEntityListener.notifyStateChanged(double, org.javades.jqueues.r5.entity.SimEntity, java.util.List<java.util.Map<org.javades.jqueues.r5.entity.SimEntitySimpleEventType.Member, org.javades.jqueues.r5.entity.SimEntityEvent>>) and a single
SimEntityListener.notifyResetEntity(org.javades.jqueues.r5.entity.SimEntity) after the state has
been set to its initial setting.
The implementation of SimEntity.resetEntity() has been made final
in order to ensure this.
This current method is intended to be used by subclasses to perform the reset.
The last-update time (getLastUpdateTime()) has already been set to the new value,
but listeners have not been notified yet.
SimEntity.resetEntity(),
update(double),
getLastUpdateTime()public final void resetEntity()
resetEntitySubClass() and fires the event to listeners (as a state-change event and through a
separate reset indication).
If the reset is the result of an event-list reset, this takes the new "start time" from the event list,
which has been set already.
In the (more unlikely) case of an autonomous reset of the entity, copying the last update time from the
event list (before notifying listeners) assures that statistics-gathering listeners restart their jobs from
the current time.
If no event list is available, the last update time is set to Double.NEGATIVE_INFINITY.
This method is final; use resetEntitySubClass() to override/augment behavior.
resetEntity in interface SimEntitygetLastUpdateTime(),
resetEntitySubClass(),
SimEntityListener.notifyStateChanged(double, org.javades.jqueues.r5.entity.SimEntity, java.util.List<java.util.Map<org.javades.jqueues.r5.entity.SimEntitySimpleEventType.Member, org.javades.jqueues.r5.entity.SimEntityEvent>>),
SimEntityListener.notifyResetEntity(org.javades.jqueues.r5.entity.SimEntity)public final boolean isIgnoreEventListReset()
SimEntityisIgnoreEventListReset in interface SimEntitySimEntity.setIgnoreEventListReset(boolean)public final void setIgnoreEventListReset(boolean ignoreEventListReset)
SimEntity
By contract, a SimEntity must reset with SimEntity.resetEntity()
whenever the underlying event list (if present) is reset.
The normal procedure to achieve this is to register as a SimEventListResetListener,
and invoke SimEntity.resetEntity() upon SimEventListResetListener.notifyEventListReset(org.javades.jsimulation.r5.SimEventList).
There are cases, however, in which resetting this entity has to be delegated to another entity (or other type of object listening to the event list), for instance because the order in which entities are reset is important. Through this method, the automatic resetting of this entity upon an event-list reset can be disabled. Note, however, that the contract remains that the entity has to follow event-list resets.
setIgnoreEventListReset in interface SimEntityignoreEventListReset - Whether this entity ignores future event-list resets.SimEntity.isIgnoreEventListReset(),
SimEventListResetListener.notifyEventListReset(org.javades.jsimulation.r5.SimEventList)public final void notifyEventListReset(org.javades.jsimulation.r5.SimEventList eventList)
resetEntity(), unless this entity ignores event-list reset notifications.
This method is final; use resetEntitySubClass() to override/augment behavior.
notifyEventListReset in interface org.javades.jsimulation.r5.SimEventListResetListenerSimEntity.isIgnoreEventListReset(),
SimEntity.setIgnoreEventListReset(boolean)public final double getLastUpdateTime()
SimEntity
Upon construction, the last-update time must be set to minus infinity, mimicking the behavior of SimEventList.
Upon an explicit reset of this entity, the last-update time is to be copied from the event list, if available
(or reset to Double.NEGATIVE_INFINITY otherwise).
In all other cases, the time returned corresponds to the time argument of the last update of the entity,
see SimEntityListener.notifyUpdate(double, org.javades.jqueues.r5.entity.SimEntity) for more details.
getLastUpdateTime in interface SimEntityupdate(double),
SimEntityListener.notifyUpdate(double, org.javades.jqueues.r5.entity.SimEntity)public final void update(double time)
This final implementation invokes the pre-event hooks (always), and, if needed (i.e., we have a true update), invokes the pre-update hooks, notifies the entity listeners, and updates its internal time (in that order!).
update in interface SimEntitytime - The time of the update (the new time on the entity).getLastUpdateTime(),
registerPreEventHook(java.util.function.DoubleConsumer),
registerPreUpdateHook(java.util.function.DoubleConsumer),
SimEntityListener.notifyUpdate(double, org.javades.jqueues.r5.entity.SimEntity),
fireUpdate(double)protected final void registerPreUpdateHook(DoubleConsumer preUpdateHook)
A pre-update hook is a DoubleConsumer (typically, a method reference)
that is invoked by update(double) before anything else (i.c., notifying listeners)
except pre-event notifications
and if indeed there is an update (in view of the elapsed time since the last update).
It allows sub-class implementations to update internal administration as part of the update,
and gives them access to the "old time", i.e.,, the time of the previous update,
through getLastUpdateTime() (before it is overwritten by this method update(double)).
The hook should never initiate state-change events or notify listeners.
The argument passed to the DoubleConsumer is the new time,
see update(double), which obviously has not been set yet on the object.
The "old" time is available through getLastUpdateTime().
preUpdateHook - The pre-update hook, must be non-null.IllegalArgumentException - If the argument is null.update(double),
registerPreEventHook(java.util.function.DoubleConsumer)protected final void registerPreEventHook(DoubleConsumer preEventHook)
A pre-event hook is a DoubleConsumer (typically, a method reference)
that is invoked by update(double) before anything else (i.c., notifying listeners),
and even if indeed there is no update (in view of the elapsed time since the last update).
It allows sub-class implementations to update internal administration as part of the update,
and gives them access to the "old time", i.e., the time of the previous update,
through getLastUpdateTime() (before it is overwritten by this method update(double)).
The hook should never initiate state-change events or notify listeners.
Pre-event hooks are not invoked upon a reset.
The argument passed to the DoubleConsumer is the new time,
see update(double), which obviously has not been set yet on the object.
The "old" time is available through getLastUpdateTime().
preEventHook - The pre-event hook, must be non-null.IllegalArgumentException - If the argument is null.update(double),
registerPreUpdateHook(java.util.function.DoubleConsumer)Copyright © 2018. All rights reserved.