?? basicjessbehaviour.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.
*****************************************************************/
//////////////////////////////////////////////////////////////
//Kaveh Kamyab - Imperial College - 30/10/00
//General Changes
//
//* Replaced all 'ReteException' with 'JessException'
//* Instantiate Rete with 'new Rete()' instead of 'new Rete(NullDisplay ...)'
//* Line 193 - replaced 'FileInputStream fis = new FileInputStream(jessFile);'
// with 'FileReader fr = new FileReader(jessFile);'
//* Line 196 - replaced 'Jesp j = new Jesp(fis, jess);'
// with 'Jesp j = new Jesp(fr, jess);'
//* Replaced all 'stringValue()' with 'stringValue(context)'
//* Replaced '(jess.display()).stderr()'
// with 'System.err'
//* Updated getAIDListFromCache to take a ValueVector as parameter. It also requires Context as a parameter to
// resolve JESS variables
//////////////////////////////////////////////////////////////
//Kaveh Kamyab - Imperial College - 30/10/00
//Changes In JessSend
//
//* Replaced 'name()' with 'getName()'
//* Replaced 'engine()' with 'getEngine()'
//* Modified Method 'JessFact2ACL(jess.ValueVector vv)'
// changed to 'JessFact2ACL(Context context, jess.ValueVector vv)'
//* Replaced method call accordingly 'JessFact2ACL(vv)' with 'JessFact2ACL(context, vv)'
//* Replaced 'FunCall.TRUE()' with 'FunCall.TRUE'
//
//* Check for two cases, i.e. if send has a RU.VARIABLE as its first parameter (send ?m) and secondly if
//send has an RU.FUNCALL as its first parameter (send (assert (ACLMessage ...))).
//1) The first case is straight forward. Get the first parameter of the ValueVector, extract the Fact Id and find the fact
//by looking up the Fact Id. Pass the resulting ValueVector to JessFact2ACL(Context context, jess.ValueVector vv).
//2) The second case is a little more tricky. Get the first parameter of the ValueVector, extract the function call
//(assert). Get the first parameter again and extract the ACLMessage. Jess variables must be resolved with calls to
//Value.stringValue(context), Value.listValue(context), etc.
package examples.jess;
import jade.core.*;
import jade.core.behaviours.*;
import jade.lang.acl.ACLMessage;
import jess.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
/**
Javadoc documentation for the file
@author Fabio Bellifemine - CSELT S.p.A
@author Kaveh Kamyab - Imperial College of London (upgrade to JESS 5.1)
@version $Date: 2004-09-22 15:08:42 +0200 (mer, 22 set 2004) $ $Revision: 5374 $
*/
/**
* This is the basic class that implements a behaviour of JADE that allows
* to embed a Jess engine inside the agent code.
* <p>
* <a href="http://herzberg.ca.sandia.gov/jess">Jess</a>
* supports the development of rule-based expert systems.
* <p>
* This JADE implementation has been tested with version 6.0 of JESS.
* <p>
* The programmer can override this class.
* In particular, its methods <code>ACL2JessString</code> and
* <code>JessFact2ACL</code> to convert between ACLMessage JADE structure and
* Jess facts. Also the method <code>ACLJessTemplate</code> might need to
* be overide in order to change the deftemplate of the ACLMessage in Jess.
* <p>
* When this behaviour is added to the list of agent behaviours,
* it creates a Jess engine and initializes the engine by:
* <ul>
* <li> defining the template of an ACLMessage,
* <li> defining the userfuntion "send" to send ACLMessages,
* <li> asserting the fact <code>(MyAgent (name nameofthisagent))</code>,
* <li> parsing the Jess file passed as a parameter to the constructor.
* </ul>
* Then the behaviour loops infinitely by:
* <ul>
* <li> waiting that a message arrives,
* <li> calling the <code>ACL2JessString</code> method that returns the fact to be
* asserted in Jess,
* <li> asserting the fact in Jess,
* <li> running Jess.
* </ul>
* <p>
* Notice for programmers of the Jess .clp file:
* <ul>
* <li> the template of the ACLMessage contains the following slots:
<code>(deftemplate ACLMessage (slot communicative-act) (slot sender) (multislot receiver) (slot reply-with) (slot in-reply-to) (slot envelope) (slot conversation-id) (slot protocol) (slot language) (slot ontology) (slot content) (slot encoding) (multislot reply-to) (slot reply-by))</code>
* <li> match the fact <code>(MyAgent (name nameofthisagent))</code> to know the name of your agent;
* <li> use the userfunction <code>send</code> to send ACLMessages.
* The parameter of <code>send</code> must be a fact-id of type ACLMessage or
* an ACLMessage itself; There are two styles of usage:
* <p> <code> ?m <- (ACLMessage (communicative-act cfp) (sender ?s))
* <br>
* (send ?m) </code>
* <p> or, in alternative,
* <p> <code>(send (assert (ACLMessage (communicative-act cfp)
* (sender ?s))))</code>
* <li> remember to load all the Jess Packages you need because, by default,
* Jess just loads the built-in functions
* </ul>
* <p>
* Look at the sample file JadeAgent.clp that is shipped with this example.
* <p>
* WARNING:
* FIPA2000 standard has specified an AgentIdentifier to have a
* template
* composed of several slots, where the only mandatory one is the agent name,
* i.e. the globally unique identifier of the agent (GUID).
* In order to reduce the porting of the JESS user code, this basic
* behaviour automatically
* takes care of replacing the GUIDs with full-fledged AgentIdentifiers.
*/
public class BasicJessBehaviour extends CyclicBehaviour {
// class variables
Rete jess; // holds the pointer to jess
Agent myAgent; // holds the pointer to this agent
int m_maxJessPasses = 0; // holds the maximum number of Jess passes for each run
int executedPasses = -1; // to count the number of Jess passes in the previous run
Hashtable AIDCache; // holds a local cache to map agent names to AID
/**
* Creates a <code>BasicJessBehaviour</code> instance
*
* @param agent the agent that adds the behaviour
* @param jessFile the name of the Jess file to be executed
*/
public BasicJessBehaviour(Agent agent, String jessFile) {
myAgent = agent;
AIDCache = new Hashtable();
// See info about the Display classes in Section 5 of Jess 4.1b6 Readme.htm
//NullDisplay nd = new NullDisplay();
// Create a Jess engine
jess = new Rete();
// The jess.MiscFunctions is no more used since JESS 6.0 (see e-mail of Csaba Tenkes
//try {
//jess.addUserpackage((Userpackage)Class.forName("jess.MiscFunctions").newInstance());
// } catch (Throwable t) { System.out.println(t); }
try {
// First I define the ACLMessage template
jess.executeCommand(ACLJessTemplate());
// Then I define the myagent template
jess.executeCommand("(deftemplate MyAgent (slot name))");
// Then I add the send function
jess.addUserfunction(new JessSend(myAgent, this));
// Then I assert the fact (Myagent (name <my-name>))
jess.executeCommand(
"(deffacts MyAgent \"All facts about this agent\" (MyAgent (name " +
myAgent.getName() + ")))");
// Open the file test.clp
FileReader fr = new FileReader(jessFile);
// Create a parser for the file, telling it where to take input
// from and which engine to send the results to
Jesp j = new Jesp(fr, jess);
// parse and execute one construct, without printing a prompt
j.parse(false);
} catch (JessException re) {
System.out.println(re);
} catch (FileNotFoundException e) {
System.out.println(e);
}
}
/**
* Creates a <code>BasicJessBehaviour</code> instance that limits
* the reasoning time of Jess before looking again for arrival of messages.
*
* @param agent the agent that adds the behaviour
* @param jessFile the name of the Jess file to be executed
* @param maxJessPasses the maximum number of passes that every run of Jess
* can execute before giving again the control to this behaviour;
* put <code>0</code> if you do not ever want to stop Jess.
*/
public BasicJessBehaviour(Agent agent, String jessFile, int maxJessPasses) {
this(agent, jessFile);
m_maxJessPasses = maxJessPasses;
}
/**
* executes the behaviour
*/
public void action() {
ACLMessage msg; // to keep the ACLMessage
// wait a message
if (executedPasses < m_maxJessPasses) {
System.out.println(myAgent.getName() +
" is blocked to wait a message...");
msg = myAgent.blockingReceive();
// assert the fact message in Jess
makeassert(ACL2JessString(msg));
} else {
System.out.println(myAgent.getName() +
" is checking if there is a message...");
msg = myAgent.receive();
if (msg != null) {
// assert the fact message in Jess
makeassert(ACL2JessString(msg));
}
}
// run jess
try {
// jess.executeCommand("(facts)");
if (m_maxJessPasses > 0) {
executedPasses = jess.run(m_maxJessPasses);
System.out.println("Jess has executed " + executedPasses +
" passes");
} else {
jess.run();
}
} catch (JessException re) {
re.printStackTrace(System.err);
}
}
private boolean isEmpty(String string) {
return (string == null) || string.equals("");
}
/**
replace a char in a String with a String
It is used to convert all the quotation marks in backslash quote
before asserting the content of a message in Jess.
@return the new String
*/
private String stringReplace(String str, char oldChar, String s) {
int len = str.length();
int i = 0;
int j = 0;
int k = 0;
char[] val = new char[len];
str.getChars(0, len, val, 0); // put chars into val
char[] buf = new char[len * s.length()];
while (i < len) {
if (val[i] == oldChar) {
s.getChars(0, s.length(), buf, j);
j += s.length();
} else {
buf[j] = val[i];
j++;
}
i++;
}
return new String(buf, 0, j);
}
/**
* makeasserts a fact representing an ACLMessage in Jess. It is called after the arrival of a message.
*/
private void makeassert(String fact) {
try {
jess.executeCommand(fact);
} catch (JessException re) {
re.printStackTrace(System.err);
}
}
/**
* Remove the first and the last character of the string
* (if it is a quotation mark) and convert all backslash quote in quote
* It is used to convert a Jess content into an ACL message content.
*/
private String unquote(String str) {
String t1 = str.trim();
if (t1.startsWith("\"")) {
t1 = t1.substring(1);
}
if (t1.endsWith("\"")) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -