📄 behaviour.java
字号:
<b>must not</b> enter in an endless loop and should return as
soon as possible to preserve agent responsiveness. To split a
long and slow task into smaller section, recursive behaviour
aggregation may be used.
@see jade.core.behaviours.CompositeBehaviour
*/
public abstract void action();
/**
Check if this behaviour is done. The agent scheduler calls this
method to see whether a <code>Behaviour</code> still need to be
run or it has completed its task. Concrete behaviours must
implement this method to return their completion state. Finished
behaviours are removed from the scheduling queue, while others
are kept within to be run again when their turn comes again.
@return <code>true</code> if the behaviour has completely executed.
*/
public abstract boolean done();
/**
This method is just an empty placeholder for subclasses. It is
invoked just once after this behaviour has ended. Therefore,
it acts as an epilog for the task represented by this
<code>Behaviour</code>.
<br>
Note that <code>onEnd</code> is called after the behaviour has been
removed from the pool of behaviours to be executed by an agent.
Therefore calling
<code>reset()</code> is not sufficient to cyclically repeat the task
represented by this <code>Behaviour</code>. In order to achieve that,
this <code>Behaviour</code> must be added again to the agent
(using <code>myAgent.addBehaviour(this)</code>). The same applies to
in the case of a <code>Behaviour</code> that is a child of a
<code>ParallelBehaviour</code>.
@return an integer code representing the termination value of
the behaviour.
*/
public int onEnd() {
return 0;
}
/**
This method is just an empty placeholders for subclasses. It is
executed just once before starting behaviour execution.
Therefore, it acts as a prolog to the task
represented by this <code>Behaviour</code>.
*/
public void onStart() {
}
//#APIDOC_EXCLUDE_BEGIN
/**
This method is called internally by the JADE framework
and should not be called by the user.
*/
public final void actionWrapper() {
if (startFlag) {
onStart();
startFlag = false;
}
//#MIDP_EXCLUDE_BEGIN
// Maybe the behaviour was removed from another thread
if (myAgent != null) {
myAgent.notifyChangeBehaviourState(this, Behaviour.STATE_READY, Behaviour.STATE_RUNNING);
}
//#MIDP_EXCLUDE_END
action();
//#MIDP_EXCLUDE_BEGIN
if (myAgent != null) {
myAgent.notifyChangeBehaviourState(this, Behaviour.STATE_RUNNING, Behaviour.STATE_READY);
}
//#MIDP_EXCLUDE_END
}
public final void setExecutionState(String s) {
executionState = s;
}
public final String getExecutionState() {
return executionState;
}
//#APIDOC_EXCLUDE_END
/**
Restores behaviour initial state. This method must be implemented
by concrete subclasses in such a way that calling
<code>reset()</code> on a behaviour object is equivalent to
destroying it and recreating it back. The main purpose for this
method is to realize multistep cyclic behaviours without needing
expensive constructions an deletion of objects at each loop
iteration.
Remind to call super.reset() from the sub-classes.
*/
public void reset() {
startFlag = true;
restart();
}
//#APIDOC_EXCLUDE_BEGIN
/**
Handler for block/restart events. This method handles
notification by copying its runnable state and then by simply
forwarding the event when it is travelling upwards and by doing
nothing when it is travelling downwards, since an ordinary
behaviour has no children.
@param rce The event to handle
*/
protected void handle(RunnableChangedEvent rce) {
// Set the new runnable state
setRunnable(rce.isRunnable());
//#CUSTOM_EXCLUDE_BEGIN
// If the notification is upwords and a parent exists -->
// Notify the parent
if( (parent != null) && (rce.isUpwards()) ) {
parent.handle(rce);
}
//#CUSTOM_EXCLUDE_END
}
//#APIDOC_EXCLUDE_END
/**
Returns the root for this <code>Behaviour</code> object. That is,
the top-level behaviour this one is a part of. Agents apply
scheduling only to top-level behaviour objects, so they just call
<code>restart()</code> on root behaviours.
@return The top-level behaviour this behaviour is a part of. If
this one is a top level behaviour itself, then simply
<code>this</code> is returned.
@see jade.core.behaviours.Behaviour#restart()
*/
public Behaviour root() {
//#CUSTOM_EXCLUDE_BEGIN
Behaviour p = getParent();
if (p != null) {
return p.root();
}
//#CUSTOM_EXCLUDE_END
return this;
}
// Sets the runnable/not-runnable state
void setRunnable(boolean runnable) {
runnableState = runnable;
}
/**
Returns whether this <code>Behaviour</code> object is blocked or
not.
@return <code>true</code> when this behaviour is not blocked,
<code>false</code> when it is.
*/
public boolean isRunnable() {
return runnableState;
}
/**
Blocks this behaviour. When this method is called, the behaviour
state is set to <em>Blocked</em> and a suitable event is fired to
notify its parent behaviour. Then the behaviour is put into a
blocked behaviours queue by the agent scheduler. If this method
is called from within <code>action()</code> method, behaviour
suspension occurs as soon as <code>action()</code> returns.
@see jade.core.behaviours.Behaviour#restart()
*/
public void block() {
myEvent.init(false, NOTIFY_UP);
handle(myEvent);
}
/**
Blocks this behaviour for a specified amount of time. The
behaviour will be restarted when among the three following
events happens.
<ul>
<li> <em>A time of <code>millis</code> milliseconds has passed
since the call to <code>block()</code>.</em>
<li> <em>An ACL message is received by the agent this behaviour
belongs to.</em>
<li> <em>Method <code>restart()</code> is called explicitly on
this behaviour object.</em>
</ul>
@param millis The amount of time to block, in
milliseconds. <em><b>Notice:</b> a value of 0 for
<code>millis</code> is equivalent to a call to
<code>block()</code> without arguments.</em>
@see jade.core.behaviours.Behaviour#block()
*/
public void block(long millis) {
// Note that it is important to block the behaviour before
// adding a Timer to restart it in a millis time. In fact if
// the two operations are cerried out the other way around, it
// could happen that the Timer expires before the block()
// operation is executed --> The TimerDispatcher thread restarts
// the behaviour (that has not blocked yet) and just after the
// behaviour blocks.
block();
if (myAgent != null) {
myAgent.restartLater(this, millis);
}
}
/**
Restarts a blocked behaviour. This method fires a suitable event
to notify this behaviour's parent. When the agent scheduler
inserts a blocked event back into the agent ready queue, it
restarts it automatically. When this method is called, any timer
associated with this behaviour object is cleared.
@see jade.core.behaviours.Behaviour#block()
*/
public void restart() {
myEvent.init(true, NOTIFY_UP);
if(myAgent != null) {
myAgent.removeTimer(this);
}
handle(myEvent);
if(myAgent != null) {
myAgent.notifyRestarted(this);
}
}
/**
Associates this behaviour with the agent it belongs to. There is
no need to call this method explicitly, since the
<code>addBehaviour()</code> call takes care of the association
transparently.
@param a The agent this behaviour belongs to.
@see jade.core.Agent#addBehaviour(Behaviour b)
*/
public void setAgent(Agent a) {
myAgent = a;
}
// For persistence service
private Agent getAgent() {
return myAgent;
}
//#CUSTOM_EXCLUDE_BEGIN
/**
Return the private data store of this <code>Behaviour</code>.
If it was null, a new DataStore is created and returned.
@return The private data store of this <code>Behaviour</code>
*/
public DataStore getDataStore() {
if (myStore == null) {
myStore = new DataStore();
}
return myStore;
}
/**
Set the private data store of this <code>Behaviour</code>
@param ds the <code>DataStore</code> that this <code>Behaviour</code>
will use as its private data store
*/
public void setDataStore(DataStore ds) {
myStore = ds;
}
//#CUSTOM_EXCLUDE_END
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -