I'm new to JADE and have recently created a Service agent that looks up the definition of words from two dictionaries (WordNet(r) 3.0 (2006) and Easton's 1897 Bible Dictionary). I want to merge all services and behaviors of ServiceAgent into one. My goal is to end up having one agent class and one behavior class capable of handling requests to any dictionary from dict.org but I'm not sure how to do that.
I'm using Linux Red Hat and have downloaded Apache ANT 1.9.2 and Java JDK 1.5.0 if that helps.
Here is ServiceAgent.java code:
package jadelab1;
import jade.core.*;
import jade.core.behaviours.*;
import jade.lang.acl.*;
import jade.domain.*;
import jade.domain.FIPAAgentManagement.*;
import java.net.*;
import java.io.*;
public class ServiceAgent extends Agent {
protected void setup () {
//services registration at DF
DFAgentDescription dfad = new DFAgentDescription();
dfad.setName(getAID());
//service no 1
ServiceDescription sd1 = new ServiceDescription();
sd1.setType("answers");
sd1.setName("wordnet");
//Serive no 2
ServiceDescription sd2 = new ServiceDescription();
sd2.setType("answers");
sd2.setName("Easton's 1897 Bible Dictionary");
//add them all
dfad.addServices(sd1);
dfad.addServices(sd2);
try {
DFService.register(this,dfad);
} catch (FIPAException ex) {
ex.printStackTrace();
}
addBehaviour(new AnotherDictionaryCyclicBehaviour(this));
addBehaviour(new WordnetCyclicBehaviour(this));
//doDelete();
}
protected void takeDown() {
//services deregistration before termination
try {
DFService.deregister(this);
} catch (FIPAException ex) {
ex.printStackTrace();
}
}
public String makeRequest(String serviceName, String word)
{
StringBuffer response = new StringBuffer();
try
{
URL url;
URLConnection urlConn;
DataOutputStream printout;
DataInputStream input;
url = new URL("http://dict.org/bin/Dict");
urlConn = url.openConnection();
urlConn.setDoInput(true);
urlConn.setDoOutput(true);
urlConn.setUseCaches(false);
urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String content = "Form=Dict1&Strategy=*&Database=" + URLEncoder.encode(serviceName) + "&Query=" + URLEncoder.encode(word) + "&submit=Submit+query";
//forth
printout = new DataOutputStream(urlConn.getOutputStream());
printout.writeBytes(content);
printout.flush();
printout.close();
//back
input = new DataInputStream(urlConn.getInputStream());
String str;
while (null != ((str = input.readLine())))
{
response.append(str);
}
input.close();
}
catch (Exception ex)
{
System.out.println(ex.getMessage());
}
//cut what is unnecessary
return response.substring(response.indexOf("<hr>")+4, response.lastIndexOf("<hr>"));
}
}
class AnotherDictionaryCyclicBehaviour extends CyclicBehaviour {
ServiceAgent agent;
public AnotherDictionaryCyclicBehaviour(ServiceAgent agent) {
this.agent = agent;
}
public void action() {
MessageTemplate template = MessageTemplate.MatchOntology("Easton's 1897 Bible Dictionary");
ACLMessage message = agent.receive(template);
if (message == null) {
block();
}
else {
// Process the incoming message and handle the request for the new dictionary service
String content = message.getContent();
ACLMessage reply = message.createReply();
reply.setPerformative(ACLMessage.INFORM);
String response = "";
try
{
// Call the makeRequest method for the new dictionary service
response = agent.makeRequest("easton", content);
}
catch (NumberFormatException ex)
{
response = ex.getMessage();
}
reply.setContent(response);
agent.send(reply);
}
}
}
class WordnetCyclicBehaviour extends CyclicBehaviour
{
ServiceAgent agent;
public WordnetCyclicBehaviour(ServiceAgent agent)
{
this.agent = agent;
}
public void action()
{
MessageTemplate template = MessageTemplate.MatchOntology("wordnet");
ACLMessage message = agent.receive(template);
if (message == null)
{
block();
}
else
{
//process the incoming message
String content = message.getContent();
ACLMessage reply = message.createReply();
reply.setPerformative(ACLMessage.INFORM);
String response = "";
try
{
response = agent.makeRequest("wn",content);
}
catch (NumberFormatException ex)
{
response = ex.getMessage();
}
reply.setContent(response);
agent.send(reply);
}
}
}
I'm also including MyAgent.java code (just in case):
package jadelab1;
import jade.core.*;
import jade.core.behaviours.*;
import jade.lang.acl.*;
import jade.domain.*;
import jade.domain.FIPAAgentManagement.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MyAgent extends Agent {
protected void setup () {
displayResponse("Hello, I am " + getAID().getLocalName());
addBehaviour(new MyCyclicBehaviour(this));
//doDelete();
}
protected void takeDown() {
displayResponse("See you");
}
public void displayResponse(String message) {
JOptionPane.showMessageDialog(null,message,"Message",JOptionPane.PLAIN_MESSAGE);
}
public void displayHtmlResponse(String html) {
JTextPane tp = new JTextPane();
JScrollPane js = new JScrollPane();
js.getViewport().add(tp);
JFrame jf = new JFrame();
jf.getContentPane().add(js);
jf.pack();
jf.setSize(400,500);
jf.setVisible(true);
tp.setContentType("text/html");
tp.setEditable(false);
tp.setText(html);
}
}
class MyCyclicBehaviour extends CyclicBehaviour {
MyAgent myAgent;
public MyCyclicBehaviour(MyAgent myAgent) {
this.myAgent = myAgent;
}
public void action() {
ACLMessage message = myAgent.receive();
if (message == null) {
block();
} else {
String ontology = message.getOntology();
String content = message.getContent();
int performative = message.getPerformative();
if (performative == ACLMessage.REQUEST)
{
//I cannot answer but I will search for someone who can
DFAgentDescription dfad = new DFAgentDescription();
ServiceDescription sd = new ServiceDescription();
sd.setName(ontology);
dfad.addServices(sd);
try
{
DFAgentDescription[] result = DFService.search(myAgent, dfad);
if (result.length == 0) myAgent.displayResponse("No service has been found ...");
else
{
String foundAgent = result[0].getName().getLocalName();
myAgent.displayResponse("Agent " + foundAgent + " is a service provider. Sending message to " + foundAgent);
ACLMessage forward = new ACLMessage(ACLMessage.REQUEST);
forward.addReceiver(new AID(foundAgent, AID.ISLOCALNAME));
forward.setContent(content);
forward.setOntology(ontology);
myAgent.send(forward);
}
}
catch (FIPAException ex)
{
ex.printStackTrace();
myAgent.displayResponse("Problem occured while searching for a service ...");
}
}
else
{ //when it is an answer
myAgent.displayHtmlResponse(content);
}
}
}
}
I noticed that the following lines in the ServiceAgent are the most important: sd2.setName("Easton's 1897 Bible Dictionary"); MessageTemplate template = MessageTemplate.MatchOntology("Easton's 1897 Bible Dictionary"); response = agent.makeRequest("easton", content);
Here's what I've already tried:
Modfied ServiceAgent class:
public class ServiceAgent extends Agent {
private String dictionaryName;
protected void setup() {
// This should Get dictionary name from the arguments passed during agent creation
Object[] args = getArguments();
if (args != null && args.length > 0) {
dictionaryName = (String) args[0];
// rest of the original code here
} else {
System.out.println("No dictionary name provided. Agent will not provide any service.");
doDelete();
}
}
// rest of the original code here
public String makeRequest(String word) {
// rest of the original code here
response = agent.makeRequest(dictionaryName, content);
// rest of the original code here
}
}
and the modified AnotherDictionaryCyclicBehaviour class:
class AnotherDictionaryCyclicBehaviour extends CyclicBehaviour {
private String dictionaryName;
ServiceAgent agent;
public AnotherDictionaryCyclicBehaviour (ServiceAgent agent, String dictionaryName) {
this.agent = agent;
this.dictionaryName = dictionaryName;
}
public void action() {
MessageTemplate template = MessageTemplate.MatchOntology(dictionaryName);
// rest of the original code here
response = agent.makeRequest(content);
// rest of the original code here.
}
}
By making these changes, the agent and its behavior should become more versatile. The dictionary name is no longer hard-coded, so users should be able to dynamically specify it during agent configuration. The problem is that after the changes, the agent stil did not recognize other dictionaries. I guess this problem is extremely simple, but I would still appreciate any help.
That's my single class which can achieve what you wanted:
package jadelab1;
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.domain.FIPAAgentManagement.*;
import jade.domain.DFService;
import jade.domain.FIPAException;
import java.net.*;
import java.io.*;
import javax.swing.*;
public class NewDictionaryAgent extends Agent {
protected void setup() {
// Agent registration with the DF
DFAgentDescription dfd = new DFAgentDescription();
dfd.setName(getAID());
ServiceDescription sd = new ServiceDescription();
sd.setType("dictionary-lookup");
sd.setName("dict-org-lookup");
dfd.addServices(sd);
try {
DFService.register(this, dfd);
} catch (FIPAException fe) {
fe.printStackTrace();
}
addBehaviour(new LookupBehaviour(this));
}
// Add the behaviour to process lookup requests
protected void takeDown() {
// Deregister from the DF
try {
DFService.deregister(this);
} catch (FIPAException fe) {
fe.printStackTrace();
}
}
// Similar to makeRequest but processing the response
public String makeDictionaryRequest(String serviceName, String
word) {
StringBuffer response = new StringBuffer();
try
{
URL url;
URLConnection urlConn;
DataOutputStream printout;
DataInputStream input;
url = new URL("http://dict.org/bin/Dict");
urlConn = url.openConnection();
urlConn.setDoInput(true);
urlConn.setDoOutput(true);
urlConn.setUseCaches(false);
urlConn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
String content = "Form=Dict1&Strategy=*&Database=" +
URLEncoder.encode(serviceName) + "&Query=" +
URLEncoder.encode(word) + "&submit=Submit+query";
//forth
printout = new
DataOutputStream(urlConn.getOutputStream());
printout.writeBytes(content);
printout.flush();
printout.close();
//back
input = new DataInputStream(urlConn.getInputStream());
String str;
while (null != ((str = input.readLine())))
{
response.append(str);
}
input.close();
}
catch (Exception ex)
{
System.out.println(ex.getMessage());
}
//cut what is unnecessary
return response.substring(response.indexOf("<hr>")+4,
response.lastIndexOf("<hr>"));
}
class LookupBehaviour extends CyclicBehaviour {
NewDictionaryAgent agent;
public LookupBehaviour(NewDictionaryAgent agent) {
this.agent = agent; }
public void action() {
// MessageTemplate template = MessageTemplate.MatchPerformative(ACLMessage.REQUEST);
ACLMessage message = agent.receive();
if (message == null) {
block();
} else {
String content = message.getContent();
String ontology = message.getOntology();
ACLMessage reply = message.createReply();
reply.setPerformative(ACLMessage.INFORM);
String response = "";
try {
response = agent.makeDictionaryRequest(ontology, content);
} catch (Exception ex) {
response = ex.getMessage();
}
reply.setContent(response);
agent.send(reply);
}
}
}
}
And MyAgentClass:
package jadelab1;
import jade.core.*;
import jade.core.behaviours.*;
import jade.lang.acl.*;
import jade.domain.*;
import jade.domain.FIPAAgentManagement.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MyAgent extends Agent {
protected void setup () {
displayResponse("Hello, I am " + getAID().getLocalName());
addBehaviour(new MyCyclicBehaviour(this));
//doDelete();
}
protected void takeDown() {
displayResponse("See you");
}
public void displayResponse(String message) {
JOptionPane.showMessageDialog(null,message,"Message",JOptionPane.PLAIN_MESSAGE);
}
public void displayHtmlResponse(String html) {
JTextPane tp = new JTextPane();
JScrollPane js = new JScrollPane();
js.getViewport().add(tp);
JFrame jf = new JFrame();
jf.getContentPane().add(js);
jf.pack();
jf.setSize(400,500);
jf.setVisible(true);
tp.setContentType("text/html");
tp.setEditable(false);
tp.setText(html);
}
}
class MyCyclicBehaviour extends CyclicBehaviour {
MyAgent myAgent;
public MyCyclicBehaviour(MyAgent myAgent) {
this.myAgent = myAgent;
}
public void action() {
ACLMessage message = myAgent.receive();
if (message == null) {
block();
} else {
String ontology = message.getOntology();
String content = message.getContent();
int performative = message.getPerformative();
if (performative == ACLMessage.REQUEST)
{
//I cannot answer but I will search for someone who can
DFAgentDescription dfad = new DFAgentDescription();
ServiceDescription sd = new ServiceDescription();
sd.setName("dict-org-lookup");
dfad.addServices(sd);
try
{
DFAgentDescription[] result = DFService.search(myAgent, dfad);
if (result.length == 0) myAgent.displayResponse("No service has been found ...");
else
{
String foundAgent = result[0].getName().getLocalName();
myAgent.displayResponse("Agent " + foundAgent + " is a service provider. Sending message to " + foundAgent);
ACLMessage forward = new ACLMessage(ACLMessage.REQUEST);
forward.addReceiver(new AID(foundAgent, AID.ISLOCALNAME));
forward.setContent(content);
forward.setOntology(ontology);
myAgent.send(forward);
}
}
catch (FIPAException ex)
{
ex.printStackTrace();
myAgent.displayResponse("Problem occured while searching for a service ...");
}
}
else
{ //when it is an answer
myAgent.displayHtmlResponse(content);
}
}
}
}