subscriptioninitiator.java
来自「java实现的P2P多agent中间件」· Java 代码 · 共 712 行 · 第 1/2 页
JAVA
712 行
**/
protected Vector prepareSubscriptions(ACLMessage subscription) {
Vector l = new Vector(1);
l.addElement(subscription);
return l;
}
/**
* This method is called every time an <code>agree</code>
* message is received, which is not out-of-sequence according
* to the protocol rules.
* This default implementation does nothing; programmers might
* wish to override the method in case they need to react to this event.
* @param agree the received agree message
**/
protected void handleAgree(ACLMessage agree) {
}
/**
* This method is called every time a <code>refuse</code>
* message is received, which is not out-of-sequence according
* to the protocol rules.
* This default implementation does nothing; programmers might
* wish to override the method in case they need to react to this event.
* @param refuse the received refuse message
**/
protected void handleRefuse(ACLMessage refuse) {
}
/**
* This method is called every time a <code>inform</code>
* message is received, which is not out-of-sequence according
* to the protocol rules.
* This default implementation does nothing; programmers might
* wish to override the method in case they need to react to this event.
* @param inform the received inform message
**/
protected void handleInform(ACLMessage inform) {
}
/**
* This method is called when all the responses have been
* collected or when the timeout is expired.
* The used timeout is the minimum value of the slot <code>replyBy</code>
* of all the sent messages.
* By response message we intend here all the <code>agree, not-understood,
* refuse, failure</code> received messages, which are
* not out-of-sequence according
* to the protocol rules.
* This default implementation does nothing; programmers might
* wish to override the method in case they need to react to this event
* by analysing all the messages in just one call.
* @param responses the Vector of ACLMessage objects that have been received
**/
protected void handleAllResponses(Vector responses) {
}
/**
This method allows to register a user defined <code>Behaviour</code>
in the PREPARE_SUBSCRIPTIONS state.
This behaviour would override the homonymous method.
This method also sets the
data store of the registered <code>Behaviour</code> to the
DataStore of this current behaviour.
It is responsibility of the registered behaviour to put the
Vector of ACLMessage objects to be sent
into the datastore at the <code>ALL_SUBSCRIPTIONS_KEY</code>
key.
The values of the slot
<code>reply-with</code> is ignored and a different value is assigned
automatically by this class for each receiver.
@param b the Behaviour that will handle this state
*/
public void registerPrepareSubscriptions(Behaviour b) {
registerPrepareInitiations(b);
}
/**
This method allows to register a user defined <code>Behaviour</code>
in the HANDLE_AGREE state.
This behaviour would override the homonymous method.
This method also sets the
data store of the registered <code>Behaviour</code> to the
DataStore of this current behaviour.
The registered behaviour can retrieve
the <code>agree</code> ACLMessage object received
from the datastore at the <code>REPLY_KEY</code>
key.
@param b the Behaviour that will handle this state
*/
public void registerHandleAgree(Behaviour b) {
registerState(b, HANDLE_AGREE);
b.setDataStore(getDataStore());
}
/**
This method allows to register a user defined <code>Behaviour</code>
in the HANDLE_INFORM state.
This behaviour would override the homonymous method.
This method also set the
data store of the registered <code>Behaviour</code> to the
DataStore of this current behaviour.
The registered behaviour can retrieve
the <code>inform</code> ACLMessage object received
from the datastore at the <code>REPLY_KEY</code>
key.
@param b the Behaviour that will handle this state
*/
public void registerHandleInform(Behaviour b) {
registerState(b, HANDLE_INFORM);
b.setDataStore(getDataStore());
}
/**
This method allows to register a user defined <code>Behaviour</code>
in the HANDLE_REFUSE state.
This behaviour would override the homonymous method.
This method also set the
data store of the registered <code>Behaviour</code> to the
DataStore of this current behaviour.
The registered behaviour can retrieve
the <code>refuse</code> ACLMessage object received
from the datastore at the <code>REPLY_KEY</code>
key.
@param b the Behaviour that will handle this state
*/
public void registerHandleRefuse(Behaviour b) {
registerState(b, HANDLE_REFUSE);
b.setDataStore(getDataStore());
}
/**
This method allows to register a user defined <code>Behaviour</code>
in the HANDLE_ALL_RESPONSES state.
This behaviour would override the homonymous method.
This method also sets the
data store of the registered <code>Behaviour</code> to the
DataStore of this current behaviour.
The registered behaviour can retrieve
the vector of ACLMessage objects, received as a response,
from the datastore at the <code>ALL_RESPONSES_KEY</code>
key.
@param b the Behaviour that will handle this state
*/
public void registerHandleAllResponses(Behaviour b) {
registerState(b, HANDLE_ALL_RESPONSES);
b.setDataStore(getDataStore());
}
/**
Cancel the subscription to agent <code>receiver</code>.
This method retrieves the subscription message sent to
<code>receiver</code> and sends a suitable CANCEL message with
the conversationID and all other protocol fields appropriately set.
The <code>:content</code> slot of this CANCEL message is filled
in by means of the <code>fillCancelContent()</code>
method. The way the CANCEL content is set in fact is application
specific.
@param receiver The agent to whom we are cancelling the subscription.
@param ignoreResponse When receiving a CANCEL, the responder may
send back a response to notify that the subscription has been
cancelled (INFORM) or not (FAILURE). If this parameter is set to
<code>true</code> this response is ignored and the session with
agent <code>receiver</code> is immediately terminated. When
<code>ignoreResponse</code> is set to <code>false</code>, on the
other hand, the session with agent <code>receiver</code> remains
active and the INFORM or FAILURE massage (if any) will be handled by the
<code>HANDLE_INFORM</code> and <code>HANDLE_FAILURE</code> states
as if they were normal notifications. It is responsibility of
the programmer to distinguish them and actually terminate the
session with agent <code>receiver</code> by calling the
<code>cancellationCompleted()</code> method.
@see #fillCancelContent(ACLMessage, ACLMessage)
@see #cancellationCompleted(AID)
*/
public void cancel(AID receiver, boolean ignoreResponse) {
ACLMessage subscription = (ACLMessage) getDataStore().get(receiver);
Session s = (Session) sessions.get(subscription.getReplyWith());
if (s != null) {
if (ignoreResponse) {
sessions.remove(subscription.getReplyWith());
}
else {
s.cancel();
}
// If the session was still active, send the CANCEL message
ACLMessage cancel = new ACLMessage(ACLMessage.CANCEL);
cancel.addReceiver(receiver);
cancel.setLanguage(subscription.getLanguage());
cancel.setOntology(subscription.getOntology());
cancel.setProtocol(subscription.getProtocol());
cancel.setConversationId(subscription.getConversationId());
fillCancelContent(subscription, cancel);
myAgent.send(cancel);
// Interrupt the ReplyReceiver to check if this SubscriptionInitiator
// should terminate
replyReceiver.interrupt();
}
}
/**
This method is used to fill the <code>:content</code> slot
of the CANCEL message that is being sent to an agent to cancel
the subscription previously activated by means of the
<code>subscription</code> message. Note that all other relevant
fields of the <code>cancel</code> message have already been
set appropriately and the programmer should not modify them.
The default implementation just sets a null content (the responder
should be able to identify the subscription that has to be
cancelled on the basis of the sender and conversationID fields
of the CANCEL message). Programmers may override this method to
create an appropriate content as exemplified in the code below.
<pr><hr><blockquote><pre>
try {
AID receiver = (AID) cancel.getAllReceiver().next();
Action a = new Action(receiver, OntoACLMessage.wrap(subscription));
getContentManager.fillContent(cancel, a);
}
catch (Exception e) {
e.printStackTrace();
}
</pre></blockquote><hr>
@see #cancel(AID, boolean)
*/
protected void fillCancelContent(ACLMessage subscription, ACLMessage cancel) {
cancel.setContent(null);
}
/**
This method should be called when the notification of a
successful subscription cancellation is received from agent
<code>receiver</code> to terminate the session with him.
This method has some effect only if a cancellation for
agent <code>receiver</code> was previously activated by
means of the <code>cancel()</code> method.
@see #cancel(AID, boolean)
*/
public void cancellationCompleted(AID receiver) {
ACLMessage subscription = (ACLMessage) getDataStore().get(receiver);
Session s = (Session) sessions.get(subscription.getReplyWith());
if (s != null && s.isCancelled()) {
sessions.remove(subscription.getReplyWith());
// Interrupt the ReplyReceiver to check if this SubscriptionInitiator
// should terminate
replyReceiver.interrupt();
}
}
/**
**/
protected void reinit(){
allResponsesReceived = false;
super.reinit();
}
//#APIDOC_EXCLUDE_BEGIN
/**
Initialize the data store.
This method is called internally by the framework and is not intended
to be called by the user
**/
protected void initializeDataStore(ACLMessage msg){
super.initializeDataStore(msg);
Vector l = new Vector();
getDataStore().put(ALL_RESPONSES_KEY, l);
}
protected ProtocolSession getSession(ACLMessage msg, int sessionIndex) {
// Store the subscription message actually sent. It can
// be useful to retrieve it to create the CANCEL message
getDataStore().put((AID) msg.getAllReceiver().next(), msg);
return new Session();
}
//#APIDOC_EXCLUDE_END
/**
Inner class Session
*/
private static class Session implements ProtocolSession, Serializable {
// Session states
static final int INIT = 0;
static final int POSITIVE_RESPONSE_RECEIVED = 1;
static final int NEGATIVE_RESPONSE_RECEIVED = 2;
static final int NOTIFICATION_RECEIVED = 3;
private int state = INIT;
private boolean cancelled = false;
public String getId() {
return null;
}
/**
return true if the received performative is valid with respect to
the current session state.
*/
public boolean update(int perf) {
switch (state) {
case INIT:
switch (perf) {
case ACLMessage.AGREE:
state = POSITIVE_RESPONSE_RECEIVED;
return true;
case ACLMessage.REFUSE:
case ACLMessage.NOT_UNDERSTOOD:
state = NEGATIVE_RESPONSE_RECEIVED;
return true;
case ACLMessage.INFORM:
case ACLMessage.FAILURE:
state = NOTIFICATION_RECEIVED;
return true;
default:
return false;
}
case POSITIVE_RESPONSE_RECEIVED:
case NOTIFICATION_RECEIVED:
switch (perf) {
case ACLMessage.INFORM:
case ACLMessage.FAILURE:
state = NOTIFICATION_RECEIVED;
return true;
default:
return false;
}
default:
return false;
}
}
public int getState() {
return state;
}
public boolean isCompleted() {
return (state == NEGATIVE_RESPONSE_RECEIVED);
}
void cancel() {
cancelled = true;
}
boolean isCancelled() {
return cancelled;
}
} // End of inner class Session
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?