⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subscriptionresponder.java

📁 java实现的P2P多agent中间件
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************
 JADE - Java Agent DEvelopment Framework is a framework to develop
 multi-agent systems in compliance with the FIPA specifications.
 Copyright (C) 2000 CSELT S.p.A.
 
 GNU Lesser General Public License
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation, 
 version 2.1 of the License. 
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the
 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA  02111-1307, USA.
 *****************************************************************/

package jade.proto;

//#CUSTOM_EXCLUDE_FILE

import jade.core.*;
import jade.core.behaviours.*;
import jade.lang.acl.*;
import jade.domain.FIPAAgentManagement.NotUnderstoodException;
import jade.domain.FIPAAgentManagement.RefuseException;
import jade.domain.FIPAAgentManagement.FailureException;
import jade.domain.FIPANames;
import jade.proto.states.*;
import jade.util.leap.*;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;


/**
 * This is a single homogeneous and effective implementation of the responder role in 
 * all the FIPA-Subscribe-like interaction protocols defined by FIPA,
 * that is all those protocols 
 * where the initiator sends a single "subscription" message
 * and receives notifications each time a given condition becomes true. 
 * @see SubscriptionInitiator
 * @author Elisabetta Cortese - TILAB
 * @author Giovanni Caire - TILAB
 */
public class SubscriptionResponder extends FSMBehaviour implements FIPANames.InteractionProtocol {
	
	/** 
	 *  key to retrieve from the DataStore of the behaviour the ACLMessage 
	 *	object sent by the initiator as a subscription.
	 **/
	public final String SUBSCRIPTION_KEY = "__subs_canc" + hashCode();
	/** 
	 *  key to retrieve from the DataStore of the behaviour the ACLMessage 
	 *	object sent by the initiator to cancel a subscription.
	 **/
	public final String CANCEL_KEY = SUBSCRIPTION_KEY;
	/** 
	 *  key to retrieve from the DataStore of the behaviour the ACLMessage 
	 *	object sent as a response to the initiator.
	 **/
	public final String RESPONSE_KEY = "__response" + hashCode();
	
	// FSM states names
	private static final String RECEIVE_SUBSCRIPTION = "Receive-subscription";
	private static final String HANDLE_SUBSCRIPTION = "Handle-subscription";
	private static final String HANDLE_CANCEL = "Handle-cancel";
	private static final String SEND_RESPONSE = "Send-response";
	private static final String SEND_NOTIFICATIONS = "Send-notifications";
	
	// The MsgReceiver behaviour used to receive subscription messages
	private MsgReceiver msgRecBehaviour = null;
	
	private Hashtable subscriptions = new Hashtable();
	private List notifications = new ArrayList();
	
	/**
	 The <code>SubscriptionManager</code> used by this 
	 <code>SubscriptionResponder</code> to register subscriptions
	 */
	protected SubscriptionManager mySubscriptionManager = null;
	
	/**
	 This static method can be used 
	 to set the proper message Template (based on the performative of the
	 subscription message) into the constructor of this behaviour.
	 @param perf The performative of the subscription message
	 */
	public static MessageTemplate createMessageTemplate(int perf) {
		return MessageTemplate.and(
				MessageTemplate.MatchProtocol(FIPA_SUBSCRIBE),
				MessageTemplate.or(MessageTemplate.MatchPerformative(perf), MessageTemplate.MatchPerformative(ACLMessage.CANCEL)));
	}
	
	/**
	 * Construct a SubscriptionResponder behaviour that handles subscription messages matching a given template. 
	 * @see #SubscriptionResponder(Agent,MessageTemplate,SubscriptionResponder.SubscriptionManager,DataStore)	 
	 **/
	public SubscriptionResponder(Agent a, MessageTemplate mt){
		this(a, mt, null, new DataStore());
	}
	
	/**
	 * Construct a SubscriptionResponder behaviour that handles subscription messages matching a given template and
	 * notifies a given SubscriptionManager about subscription/un-subscription events. 
	 * @see #SubscriptionResponder(Agent,MessageTemplate,SubscriptionResponder.SubscriptionManager,DataStore)	 
	 **/
	public SubscriptionResponder(Agent a, MessageTemplate mt, SubscriptionManager sm){
		this(a, mt, sm, new DataStore());
	}
	
	/**
	 * Construct a SubscriptionResponder behaviour that handles subscription messages matching a given template,
	 * notifies a given SubscriptionManager about subscription/un-subscription events and uses a given DataStore. 
	 * @param a is the reference to the Agent performing this behaviour.
	 * @param mt is the MessageTemplate that must be used to match
	 * subscription messages sent by the initiators. Take care that 
	 * if mt is null every message is consumed by this protocol.
	 * @param sm The <code>SubscriptionManager</code> object that is notified about subscription/un-subscription events
	 * @param store the DataStore that will be used by protocol
	 **/
	public SubscriptionResponder(Agent a, MessageTemplate mt, SubscriptionManager sm, DataStore store) {
		super(a);
		setDataStore(store);
		mySubscriptionManager = sm;
		
		// Register the FSM transitions
		registerDefaultTransition(RECEIVE_SUBSCRIPTION, HANDLE_SUBSCRIPTION);
		registerTransition(RECEIVE_SUBSCRIPTION, HANDLE_CANCEL, ACLMessage.CANCEL);
		registerTransition(RECEIVE_SUBSCRIPTION, SEND_NOTIFICATIONS, MsgReceiver.INTERRUPTED);
		registerDefaultTransition(HANDLE_SUBSCRIPTION, SEND_RESPONSE);
		registerDefaultTransition(HANDLE_CANCEL, SEND_RESPONSE);
		registerDefaultTransition(SEND_RESPONSE, RECEIVE_SUBSCRIPTION, new String[] {HANDLE_SUBSCRIPTION, HANDLE_CANCEL}); 
		registerDefaultTransition(SEND_NOTIFICATIONS, RECEIVE_SUBSCRIPTION); 
		
		//***********************************************
		// For each state create and register a behaviour	
		//***********************************************
		Behaviour b = null;
		
		// RECEIVE_SUBSCRIPTION
		msgRecBehaviour = new MsgReceiver(myAgent, mt, MsgReceiver.INFINITE, getDataStore(), SUBSCRIPTION_KEY);
		registerFirstState(msgRecBehaviour, RECEIVE_SUBSCRIPTION);
		
		// HANDLE_SUBSCRIPTION
		b = new OneShotBehaviour(myAgent) {
			
			public void action() {
				DataStore ds = getDataStore();
				ACLMessage subscription = (ACLMessage) ds.get(SUBSCRIPTION_KEY);
				ACLMessage response = null;
				try {
					response = handleSubscription(subscription); 
				}
				catch (NotUnderstoodException nue) {
					response = nue.getACLMessage();
				}
				catch (RefuseException re) {
					response = re.getACLMessage();
				}
				ds.put(RESPONSE_KEY, response);
			}
		};
		b.setDataStore(getDataStore());		
		registerState(b, HANDLE_SUBSCRIPTION);
		
		// HANDLE_CANCEL 
		b = new OneShotBehaviour(myAgent) {
			public void action() {
				DataStore ds = getDataStore();
				ACLMessage cancel = (ACLMessage) ds.get(CANCEL_KEY);
				ACLMessage response = null;
				try {
					response = handleCancel(cancel); 
				}
				catch (FailureException fe) {
					response = fe.getACLMessage();
				}
				ds.put(RESPONSE_KEY, response);
			}
		};
		b.setDataStore(getDataStore());		
		registerState(b, HANDLE_CANCEL);	
		
		// SEND_RESPONSE 
		b = new ReplySender(myAgent, RESPONSE_KEY, SUBSCRIPTION_KEY);
		b.setDataStore(getDataStore());		
		registerState(b, SEND_RESPONSE);	
		
		// SEND_NOTIFICATIONS 
		b = new OneShotBehaviour(myAgent) {
			public void action() {
				sendNotifications();
			}
		};
		b.setDataStore(getDataStore());		
		registerState(b, SEND_NOTIFICATIONS);	
		
	} // End of Constructor
	
	
	/**
	 Reset this behaviour
	 */
	// FIXME: reset deve resettare anche le sottoscrizioni?
	public void reset() {
		super.reset();
		DataStore ds = getDataStore();
		ds.remove(SUBSCRIPTION_KEY);
		ds.remove(RESPONSE_KEY);
	}
	
	/**
	 This method resets the protocol and allows to change the 
	 <code>MessageTemplate</code>
	 that defines what messages this SubscriptionResponder 
	 will react to.
	 */
	public void reset(MessageTemplate mt) {
		this.reset();
		msgRecBehaviour.reset(mt, MsgReceiver.INFINITE, getDataStore(), SUBSCRIPTION_KEY);
	}
		
	/**   
	 * This method is called when a subscription
	 * message is received that matches the message template
	 * specified in the constructor. 
	 * The default implementation creates an new <code>Subscription</code>
	 * object, stores it internally and notify the <code>SubscriptionManager</code> 
	 * used by this responder if any. Then it returns null which has
	 * the effect of sending no response. Programmers in general do not need
	 * to override this method. In case they need to manage Subscription objects in an application specific
	 * way they should rather use a <code>SubscriptionManager</code> with the <code>register()</code> method properly implemented. 
	 * However they could override it in case they need to react to the reception of a 
	 * subscription message in a different way, e.g. by sending back an AGREE message.
	 * @param subscription the received message
	 * @return the ACLMessage to be sent as a response: typically one of
	 * <code>agree, refuse, not-understood</code> or null if no response must be sent back. 
	 */
	protected ACLMessage handleSubscription(ACLMessage subscription) throws NotUnderstoodException, RefuseException {
		// Call prepareResponse() for backward compatibility
		return prepareResponse(subscription);
	}
	
	/**
	 * @deprecated Use handleSubscription() instead   
	 */
	protected ACLMessage prepareResponse(ACLMessage subscription) throws NotUnderstoodException, RefuseException {
		Subscription subs = createSubscription(subscription);
		if (mySubscriptionManager != null) {
			mySubscriptionManager.register(subs);
		}
		return null;
	}
	
	/**   
	 * This method is called when a CANCEL message is received for a previous subscription. 
	 * The default implementation retrieves the <code>Subscription</code>
	 * object the received cancel message refers to, notifies the
	 * <code>SubscriptionManager</code> used by this responder if any and remove the Subscription from its internal structures. 
	 * Then it returns null which has the effect of sending no response. 
	 * Programmers in general do not need
	 * to override this method. In case they need to manage Subscription objects in an application specific
	 * way they should rather use a <code>SubscriptionManager</code> with the <code>deregister()</code> method properly implemented.
	 * However they could override it in case they need to react to the reception of a 
	 * cancel message in a different way, e.g. by sending back an INFORM.
	 * @param cancel the received CANCEL message
	 * @return the ACLMessage to be sent as a response to the 
	 * cancel operation: typically one of <code>inform</code> and <code>failure</code> or null if no response must be sent back. 
	 */
	protected ACLMessage handleCancel(ACLMessage cancel) throws FailureException {
		Subscription s = getSubscription(cancel);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -