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

📄 dfservice.java

📁 java实现的P2P多agent中间件
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************
 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.domain;

import jade.util.leap.*;

import jade.domain.FIPAAgentManagement.*;
import jade.core.Agent;
import jade.core.AID;
import jade.core.behaviours.WakerBehaviour;

import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.ISO8601;

import jade.content.lang.sl.SimpleSLTokenizer;
import jade.content.lang.sl.SL0Vocabulary;

import java.util.Date;

/**
 * This class provides a set of static methods to communicate with
 * a DF Service that complies with FIPA specifications.
 * It includes methods to register, deregister, modify and search with a DF. 
 * Each of this method has version with all the needed parameters, or with a 
 * subset of them where, those parameters that can be omitted have been 
 * defaulted to the default DF of the platform, the AID of the sending agent,
 * the default Search Constraints.
 * <p>
 * Notice that all these methods block every activity of the agent until 
 * the action (i.e. register/deregister/modify/search) has been successfully 
 * executed or a jade.domain.FIPAException exception has been thrown 
 * (e.g. because a FAILURE message has been received from the DF). 
 * <p>
 * In some cases, instead, it is more convenient to execute these tasks in a 
 * non-blocking way. In these cases a <code>jade.proto.AchieveREInitiator</code>
 * or <code>jade.proto.SubscriptionInitiator</code> should be used in 
 * conjunction with the <code>createRequestMessage(), createSubscriptionMessage(), 
 * decodeDone(), decodeResult() and decodeNotification()</code> methods 
 * that facilitate the preparation and decoding of messages to be sent/received
 * to/from the DF. The following piece of code exemplifies that in the case 
 * of an agent subscribing to the default DF.
 
 <pr><hr><blockquote><pre>
 DFAgentDescription template = // fill the template
 Behaviour b = new SubscriptionInitiator(
 this, 
 DFService.createSubscriptionMessage(this, getDefaultDF(), template, null)) 
 {
 protected void handleInform(ACLMessage inform) {
 try {
 DFAgentDescription[] dfds = DFService.decodeNotification(inform.getContent());
 // do something
  }
  catch (FIPAException fe) {
  fe.printStackTrace();
  }
  }
  };
  addBehaviour(b);
  </pre></blockquote><hr>
  
  * @author Fabio Bellifemine (CSELT S.p.A.)
  * @author Elisabetta Cortese (TiLab S.p.A.)
  * @author Giovanni Caire (TiLab S.p.A.)
  @version $Date: 2007-10-08 15:39:37 +0200 (lun, 08 ott 2007) $ $Revision: 6000 $ 
  * 
  **/
public class DFService extends FIPAService {
	private static final long OFFSET = 10000; // 10 sec
	private static final String SPACE_COLON = " :";
	private static final String SPACE_BRACKET = " (";
	
	/**
	 * check that the <code>DFAgentDescription</code> contains the mandatory
	 * slots, i.e. the agent name and, for each servicedescription, the
	 * service name and the service type
	 * @exception a MissingParameter exception is it is not valid
	 */
	static void checkIsValid(DFAgentDescription dfd, boolean checkServices) throws MissingParameter {
		try {
			if (dfd.getName().getName().length() == 0) {
				throw new MissingParameter(FIPAManagementVocabulary.DFAGENTDESCRIPTION, FIPAManagementVocabulary.DFAGENTDESCRIPTION_NAME);
			}
		}
		catch (NullPointerException npe) {
			throw new MissingParameter(FIPAManagementVocabulary.DFAGENTDESCRIPTION, FIPAManagementVocabulary.DFAGENTDESCRIPTION_NAME);
		}
		
		if (checkServices) {
			Iterator i = dfd.getAllServices();
			ServiceDescription sd;
			while (i.hasNext()) {
				sd = (ServiceDescription)i.next();
				if (sd.getName() == null)
					throw new MissingParameter(FIPAManagementVocabulary.SERVICEDESCRIPTION, FIPAManagementVocabulary.SERVICEDESCRIPTION_NAME);
				if (sd.getType() == null)
					throw new MissingParameter(FIPAManagementVocabulary.SERVICEDESCRIPTION, FIPAManagementVocabulary.SERVICEDESCRIPTION_TYPE);
			}
		}
	}
	
	
	/**
	 Register a new DF-Description with a <b>DF</b> agent.
	 <p> 
	 It should be noted that, depending on the policy adopted by 
	 the DF, the granted lease time for the registration can be 
	 shorter than the requested one. This can be checked by looking 
	 at the DF-Description actually registered by the DF that is made 
	 available as the return value of this method. 
	 The <code>keepRegistered()</code> method can be used to keep
	 the registration valid until a given time.
	 @param a is the Agent performing the registration (it is needed in order
	 to send/receive messages)
	 @param dfName The AID of the <b>DF</b> agent to register with.
	 @param dfd A <code>DFAgentDescription</code> object containing all
	 data necessary to the registration. If the Agent name is empty, than
	 it is set according to the <code>a</code> parameter.
	 @return the <code>DFAgentDescription</code> actually registered 
	 by the DF
	 @exception FIPAException If a <code>REFUSE</code>, 
	 <code>FAILURE</code> or <code>NOT_UNDERSTOOD</code>
	 message is received from the DF (to indicate some error condition) 
	 or if the supplied DF-Description is not valid.
	 @see #keepRegistered(Agent, AID, DFAgentDescription, Date)
	 */
	public static DFAgentDescription register(Agent a, AID dfName, DFAgentDescription dfd) throws FIPAException {
		if (dfd == null) {
			dfd = new DFAgentDescription();
		}
		if (dfd.getName() == null) {
			dfd.setName(a.getAID());
		}
		checkIsValid(dfd, true);
		
		ACLMessage request = createRequestMessage(a, dfName, FIPAManagementVocabulary.REGISTER, dfd, null);
		ACLMessage reply = doFipaRequestClient(a,request);
		if (reply == null) {
			throw new FIPAException("Missing reply");
		}
		return decodeDone(reply.getContent());
	}
	
	
	/**
	 * Registers a <code>DFAgentDescription</code> with the default DF
	 @exception FIPAException  
	 * @see #register(Agent,AID,DFAgentDescription)
	 **/
	public static DFAgentDescription register(Agent a, DFAgentDescription dfd) throws FIPAException {
		return register(a,a.getDefaultDF(),dfd);
	}
	
	/**
	 Deregister a DFAgentDescription from a <b>DF</b> agent. 
	 @param dfName The AID of the <b>DF</b> agent to deregister from.
	 @param dfd A <code>DFAgentDescription</code> object containing all
	 data necessary to the deregistration.
	 @exception FIPAException If a <code>REFUSE</code>, 
	 <code>FAILURE</code> or <code>NOT_UNDERSTOOD</code>
	 message is received from the DF (to indicate some error condition) 
	 or if the supplied DF-Description is not valid.
	 */
	public static void deregister(Agent a, AID dfName, DFAgentDescription dfd) throws FIPAException {
		if (dfd == null) {
			dfd = new DFAgentDescription();
		}
		if (dfd.getName() == null) {
			dfd.setName(a.getAID());
		}
		
		ACLMessage request = createRequestMessage(a, dfName, FIPAManagementVocabulary.DEREGISTER, dfd, null);
		ACLMessage reply = doFipaRequestClient(a,request);
		if (reply == null) {
			throw new FIPAException("Missing reply");
		}
	}
	
	/**
	 * Deregisters a <code>DFAgentDescription</code> from the default DF
	 @exception FIPAException  
	 @see #deregister(Agent a, AID dfName, DFAgentDescription dfd) 
	 **/
	public static void deregister(Agent a, DFAgentDescription dfd) throws FIPAException {
		deregister(a,a.getDefaultDF(),dfd);
	}
	
	/**
	 * A default Agent Description is used which contains only the AID
	 * of this agent.
	 @exception FIPAException  
	 @see #deregister(Agent a, AID dfName, DFAgentDescription dfd) 
	 **/
	public static void deregister(Agent a, AID dfName) throws FIPAException {
		deregister(a,dfName,null);
	}
	
	/**
	 * Deregisters a <code>DFAgentDescription</code> from the default DF.
	 * A default DF-Description is used which contains only the AID
	 * of this agent.
	 @exception FIPAException  
	 @see #deregister(Agent a, AID dfName, DFAgentDescription dfd) 
	 **/
	public static void deregister(Agent a) throws FIPAException {
		deregister(a,a.getDefaultDF());
	}
	
	
	/**
	 Modifies a previously registered DF-Description within a <b>DF</b>
	 agent. 
	 <p>
	 It should be noted that, depending on the policy adopted by 
	 the DF, the granted lease time for the modified registration can be 
	 shorter than the requested one. This can be checked by looking 
	 at the DF-Description actually registered by the DF that is made 
	 available as the return value of this method.
	 The <code>keepRegistered()</code> method can be used to keep
	 the registration valid until a given time.
	 @param a is the Agent performing the request of modification 
	 @param dfName The AID of the <b>DF</b> agent holding the data
	 to be changed.
	 @param dfd A <code>DFAgentDescription</code> object containing all
	 new data values; 
	 @return the <code>DFAgentDescription</code> actually registered 
	 (after the modification) by the DF
	 @exception FIPAException If a <code>REFUSE</code>, 
	 <code>FAILURE</code> or <code>NOT_UNDERSTOOD</code>
	 message is received from the DF (to indicate some error condition) 
	 or if the supplied DF-Description is not valid.
	 @see #keepRegistered(Agent, AID, DFAgentDescription, Date)
	 */
	public static DFAgentDescription modify(Agent a, AID dfName, DFAgentDescription dfd) throws FIPAException {
		if (dfd == null) {
			dfd = new DFAgentDescription();
		}
		if (dfd.getName() == null) {
			dfd.setName(a.getAID());
		}      
		checkIsValid(dfd, true);
		
		ACLMessage request = createRequestMessage(a, dfName, FIPAManagementVocabulary.MODIFY, dfd, null);
		ACLMessage reply = doFipaRequestClient(a,request);
		if (reply == null) {
			throw new FIPAException("Missing reply");
		}
		
		return decodeDone(reply.getContent());
	}
	
	/**
	 * Modify a <code>DFAgentDescription</code> from the default DF.
	 @exception FIPAException  
	 @see #modify(Agent a, AID dfName, DFAgentDescription dfd)
	 **/
	public static DFAgentDescription modify(Agent a, DFAgentDescription dfd) throws FIPAException {
		return modify(a,a.getDefaultDF(),dfd);
	}
	
	/**
	 Add a suitable behaviour that ensures that a DF-Description currently
	 registered with a DF is kept registered until a given deadline. 
	 This method is particularly useful when dealing with a DF agent 
	 that grants limited lease time for agent registrations.
	 The following piece of code exemplifies how to use it.
	 
	 <pr><hr><blockquote><pre>
	 DFAgentDescription dfd = // fill DF-Description
	 try {
	 DFAgentDescription actualDfd = DFService.register(this, dfd);
	 DFService.keepRegistered(this, actualDfd, dfd.getLeaseTime());
	 }
	 catch (FIPAException fe) {
	 fe.printStackTarce();
	 }
	 </pre></blockquote><hr>
	 
	 @param a The agent that is registerd with the DF.
	 @param df The DF agent
	 @param dfd The DF-Description that is currently registered with the DF
	 @param deadline The time until which the currenlty registered 
	 DF-Description must be kept valid. Use null to indicate an infinite 
	 time
	 */
	public static void keepRegistered(Agent a, AID df, final DFAgentDescription dfd, Date deadline) {
		Date lease = dfd.getLeaseTime();
		final AID theDF = (df != null ? df : a.getDefaultDF());
		if (lease != null) {
			if (deadline == null || lease.getTime() < deadline.getTime()) {
				dfd.setLeaseTime(deadline);
				a.addBehaviour(new WakerBehaviour(a, new Date(lease.getTime() - OFFSET)) {
					protected void onWake() {
						try {
							DFAgentDescription newDfd = modify(myAgent, theDF, dfd);
							keepRegistered(myAgent, theDF, newDfd, dfd.getLeaseTime());
						}
						catch (FIPAException fe) {
							// There is nothing we can do
							fe.printStackTrace();
						}
					}
				} );
			}
		}
	}
	
	// constant used to set max results of SearchConstraints
	private static Long MINUSONE = new Long(-1);
	/**
	 Searches for data contained within a <b>DF</b> agent. 
	 @param a is the Agent requesting the search 
	 @param dfName The AID of the <b>DF</b> agent to start search from.
	 @param dfd A <code>DFAgentDescription</code> object containing
	 data to search for; this parameter is used as a template to match
	 data against.
	 @param constraints of the search 
	 @return An array of <code>DFAgentDescription</code> 
	 containing all found
	 items matching the given
	 descriptor, subject to given search constraints for search depth
	 and result size.
	 @exception FIPAException If a <code>REFUSE</code>, 
	 <code>FAILURE</code> or <code>NOT_UNDERSTOOD</code>
	 message is received from the DF (to indicate some error condition) 
	 */
	public static DFAgentDescription[] search(Agent a, AID dfName, DFAgentDescription dfd, SearchConstraints constraints) throws FIPAException {
		if (dfName == null) {
			dfName = a.getDefaultDF();
		}
		if (dfd == null) {
			dfd = new DFAgentDescription();
		}
		if (constraints == null) {
			constraints = new SearchConstraints();
			constraints.setMaxResults(MINUSONE);
		}
		
		ACLMessage request = createRequestMessage(a, dfName, FIPAManagementVocabulary.SEARCH, dfd, constraints);
		ACLMessage inform = doFipaRequestClient(a,request);
		if (inform == null) {
			throw new FIPAException("Missing reply");
		}
		
		return decodeResult(inform.getContent());
	}
	
	/**
	 * The default DF is used.
	 @exception FIPAException  

⌨️ 快捷键说明

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