📄 dfservice.java
字号:
/*****************************************************************
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 + -