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 + -
显示快捷键?