View Javadoc

1   /*
2    * The contents of this file are subject to the BT "ZEUS" Open Source
3    * Licence (L77741), Version 1.0 (the "Licence"); you may not use this file
4    * except in compliance with the Licence. You may obtain a copy of the Licence
5    * from $ZEUS_INSTALL/licence.html or alternatively from
6    * http://www.labs.bt.com/projects/agents/zeus/licence.htm
7    *
8    * Except as stated in Clause 7 of the Licence, software distributed under the
9    * Licence is distributed WITHOUT WARRANTY OF ANY KIND, either express or
10   * implied. See the Licence for the specific language governing rights and
11   * limitations under the Licence.
12   *
13   * The Original Code is within the package zeus.*.
14   * The Initial Developer of the Original Code is British Telecommunications
15   * public limited company, whose registered office is at 81 Newgate Street,
16   * London, EC1A 7AJ, England. Portions created by British Telecommunications
17   * public limited company are Copyright 1996-2001. All Rights Reserved.
18   *java
19   * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20   */
21  package zeus.agents;
22  import zeus.actors.*;
23  import zeus.concepts.*;
24  import zeus.util.GenSym;
25  import java.net.*;
26  import java.util.*;
27  import JADE_SL.*;
28  import JADE_SL.lang.sl.*;
29  import JADE_SL.abs.*;
30  import JADE_SL.onto.basic.*;
31  import zeus.util.*;
32  
33  /***
34   * FIPA_DF_Services is used by the ACC agent to wrap the Facilitator
35   * so that it can be accessed exernally.
36   *
37   *This class was tested against the Agentcities test suit, http://leap.crm-paris.com/agentcities/Services/Testsuite.jsp
38   *
39   */
40  public class FIPA_DF_Services extends FIPA_Services {
41      
42      private String NOT_AUTHORISED = "not authorised";
43      private String UNEXPECTED = "zeus didn't expect that";
44      private GenSym rand = new GenSym("df");
45      
46      // fear not, hack was just used to test the class, I left it in incase I wanted to try some more tests...
47      String hack = new String(" (set (df-agent-description :name (agent-identifier :name pingagent@adastralcity.agentcities.net) :services (set (service-description :name ping :type ping_acl_alpha_v1.0 ))  :protocol FIPA-Request  :ontology Agentcities   :language Ping   :ownership //\"Simon//\")   ");
48      
49      // registered_agents is used to store all normal agents
50      private Hashtable registered_agents = new Hashtable();
51      
52      // registered_dfs is used to store all the dfs that have registered themselves
53      private Hashtable registered_dfs = new Hashtable();
54      private SLCodec codec = new SLCodec();
55      String ABILITY_KEY = "ACC_FIPA_DF_KEY";
56      String SERVICE_KEY = "ACC_DAMLS_KEY";
57      public void exec(AgentContext context) {
58          this.context = context;
59          this.type = new String("df");
60          debug("trying registration");
61          registerAlias(this.type);
62          setName();
63          setRegister();
64          setDeregister();
65          setModify();
66          setSearch();
67          
68        /*  String[] pattern2 = { "type", "inform","in-reply-to", ABILITY_KEY };
69          context.MsgHandler().addRule(new MessageRuleImpl(context.newId("Rule"), pattern2,this,"abilityReceived") );*/
70          String[] serviceDesc = {"type","inform", "content","//A(.*)daml(.*)//Z","in-reply-to",SERVICE_KEY};
71          context.MsgHandler().addRule(new MessageRuleImpl(context.newId("Rule"), serviceDesc,this,"serviceDescriptionReceived"));
72      }
73      
74      
75      
76     
77      
78      private String getServiceName(Performative msg) {
79          
80          String type;
81          
82          String description = msg.getContent();
83          String serviceDir = SystemProps.getProperty("http_root");
84          
85          if(description.indexOf("<service:serviceProfile ") > 0) {
86              type = "Profile";
87          }
88          else if(description.indexOf("<service:Service") > 0 &&
89          description.indexOf("<service:presents") > 0) {
90              type = "Instance";
91          }
92          else {
93              System.out.println("Unknown type of description");
94              return ("unknown");
95          }
96          
97          int nameBegin = description.indexOf("service:serviceProfile ");
98          nameBegin = description.indexOf("rdf:ID", nameBegin);
99          nameBegin = description.indexOf("\"", nameBegin) + 1;
100         
101         int nameEnd = description.indexOf("\"", nameBegin);
102         
103         String name = description.substring(nameBegin, nameEnd);
104         return name;
105         
106     }
107     
108     /***
109      *this is a message that is likely to have the name of the task in it
110      */
111     public void serviceDescriptionReceived(Performative perf) {
112         System.out.println("GOT SERVICE DESCRIPTION!!!!");
113         //    Vector List = ZeusParser.abilitySpecList(context.OntologyDb(),perf.getContent());
114         String agent = perf.getSender();
115         DF_Description desc = new DF_Description();
116         Vector language = new Vector();
117         language.addElement("FIPA-SL");
118         language.addElement("Zeus");
119         desc.setLanguage(language);
120         Vector protocols = new Vector();
121         protocols.addElement("FIPA-Inform-Protocol");
122         protocols.addElement("FIPA-Request-Protocol");
123         protocols.addElement("FIPA-Iterated-ContractNet-Protocol");
124         desc.setProtocol(protocols);
125         Vector ontos = new Vector();
126         ontos.addElement("agentcities");
127         desc.setOntology(ontos);
128         Address addr = context.getMailBox().getAddress();
129         String host = addr.getHost(); 
130         desc.setName(new FIPA_AID_Address (perf.getSender(), host  ));
131         FIPA_Service_Description service = new FIPA_Service_Description();
132         service.setOwnership(agent);
133         service.setType("Backward-Chain-Task");
134         String sname = getServiceName(perf);
135         System.out.println("sname = " + sname);
136         if (!sname.equals("Profile")) {
137             service.setName(sname);
138             protocols = new Vector();
139             protocols.addElement("FIPA-Iterated-ContractNet-Protocol");
140             service.setProtocol(protocols);
141             service.setLanguage(language);
142             service.setOntology(ontos);
143             Vector props = new Vector();
144             String content = perf.getContent();
145             //classification, domain, scope
146             String classification = new String(); 
147             String domain = "Leisure";
148             String scope = "Local"; 
149             if (sname == "BookTable") classification ="Restaurant"; 
150             if (sname == "BookTicket") classification = "Entertainment"; 
151             if (sname == "BookRoom") classification = "Hotel";
152             service.setAgentcitiesProperties(classification,domain,scope);
153             if (!inServiceList(agent+sname)) {
154                 System.out.println("sname " + sname +" not in service list");
155                 desc.addService(service);
156                 addServiceList(agent+sname);
157                 System.out.println("sname "+ sname +" added to service list");
158                 String key = agent+sname;
159                 registered_agents.put(key,desc);
160             }
161             else{
162                 System.out.println("sname " + sname + "was in service list");
163 
164             }
165         }
166         
167     }
168         Hashtable serviceList = new Hashtable();
169         
170         private void addServiceList(String name) {
171             
172             serviceList.put(name,name);
173         }
174         
175         
176         private boolean inServiceList(String name) {
177             return (serviceList.containsValue(name));
178         }
179         
180         /***
181          *the problem is to get the name of the task and to register it
182          *here
183          *Perhaps we this should be triggered by the second message?
184          */
185         public void abilityReceived(Performative perf) {
186             System.out.println("ADDING SERVICES");
187             Vector List = ZeusParser.abilitySpecList(context.OntologyDb(),perf.getContent());
188             String agent = perf.getSender();
189             DF_Description desc = new DF_Description();
190             Vector language = new Vector();
191             language.addElement("FIPA-SL");
192             language.addElement("Zeus");
193             desc.setLanguage(language);
194             Vector protocols = new Vector();
195             protocols.addElement("FIPA-Inform-Protocol");
196             protocols.addElement("FIPA-Request-Protocol");
197             protocols.addElement("FIPA-Iterated-ContractNet-Protocol");
198             desc.setProtocol(protocols);
199             Vector ontos = new Vector();
200             ontos.addElement("agentcities");
201             desc.setOntology(ontos);
202             
203             FIPA_Service_Description service = new FIPA_Service_Description();
204             service.setOwnership(agent);
205             service.setType("Backward-Chain-Task");
206             service.setName(rand.newId(perf.getSender()));
207             protocols = new Vector();
208             protocols.addElement("FIPA-Iterated-ContractNet-Protocol");
209             service.setProtocol(protocols);
210             service.setLanguage(language);
211             service.setOntology(ontos);
212             Vector props = new Vector();
213             String content = perf.getContent();
214             AbilitySpec spec = ZeusParser.abilitySpec(context.getOntologyDb(), content);
215             props.addElement(spec.getFact().toSL());
216             
217             //   props.addElement(perf.getContent());
218             service.setAgentcitiesProperties("none","none","none");
219             desc.addService(service);
220             
221             String key = rand.newId();
222             registered_agents.put(key,desc);
223         }
224         
225         
226         /***
227          * method for handleing a registration message to the df
228          */
229         public void handleRegister(Performative perf) {
230             try {
231                 // parse the content
232                 String content = perf.getContent();
233                 String agreeCont = new String(content);
234                 AbsContentElement slcontent = codec.decode(SLOntology.getInstance(),content);
235                 AbsAgentAction act = (AbsAgentAction) slcontent.getAbsObject("ACTION");
236                 // check and see if it is a registration message, if it is then agree to register,
237                 // otherwise send a not understood
238                 if (act != null) {
239                     if (act.getTypeName().equalsIgnoreCase("register")) {
240                         sendAgree(perf);
241                     }
242                     else {
243                         simpleReply(perf,UNEXPECTED,"not_understood");
244                     }
245                 }
246                 AbsConcept absActor = (AbsConcept) slcontent.getAbsObject("ACTOR");
247                 AbsAggregate agentAddresses = (AbsAggregate) absActor.getAbsObject("addresses");
248                 AbsPrimitive agentName = (AbsPrimitive) absActor.getAbsObject("name");
249                 String addr = SL_Util.makeAddressString(agentName,agentAddresses);
250                 boolean proceed = checkAuthority("df", agentName, agentAddresses, perf);
251                 if (!proceed) {
252                     simpleReply(perf, NOT_AUTHORISED,"refuse");
253                 }
254                 //rand.newId("reg");
255                 if (agentName.getString().equals("df")) {
256                     registered_dfs.put(addr, makeDescription(act));
257                 }
258                 else {
259                     registered_agents.put(addr, makeDescription(act));}
260                 informDone(perf);
261             } catch (Exception e) {
262                 e.printStackTrace();
263             }
264         }
265         
266         
267         
268         
269         
270         public DF_Description makeDescription(AbsConcept act) {
271             try {
272                 AbsConcept target_descr = (AbsConcept) act.getAbsObject("_SL.UNNAMED0"); // dangerous?
273                 AbsConcept desName = (AbsConcept) target_descr.getAbsObject("name");
274                 AbsPrimitive targName = (AbsPrimitive) desName.getAbsObject("name");
275                 AbsAggregate targAddresses =  (AbsAggregate) desName.getAbsObject("addresses");
276                 FIPA_AID_Address agent = new FIPA_AID_Address(SL_Util.makeAddressString(targName, targAddresses));
277                 AbsAggregate targLanguage = (AbsAggregate) target_descr.getAbsObject("language");
278                 AbsAggregate targProtocol = (AbsAggregate) target_descr.getAbsObject("protocol");
279                 AbsAggregate targOntology = (AbsAggregate) target_descr.getAbsObject("ontology");
280                 AbsAggregate targServices = (AbsAggregate) target_descr.getAbsObject("services");
281                 DF_Description desc = new DF_Description();
282                 desc.setName(agent);
283                 desc.setLanguage(SL_Util.makeVector(targLanguage));
284                 desc.setProtocol(SL_Util.makeVector(targProtocol));
285                 desc.setOntology(SL_Util.makeVector(targOntology));
286                 //may be more than one service...
287                 Iterator iter = (targServices).iterator();
288                 while (iter.hasNext()) {
289                     AbsConcept current = (AbsConcept) iter.next();
290                     FIPA_Service_Description service = new FIPA_Service_Description(current);
291                     desc.addService(service);
292                 }
293                 return (desc);}
294             catch (Exception e) {
295                 // probably an empty param
296                 return (null);
297             }
298             
299         }
300         
301         
302         
303         public boolean checkAuthority(String agent, AbsPrimitive attempter, AbsAggregate attempterAddresses, Performative perf) {
304             return true; // v. poor!
305         }
306         
307         
308         public void handleDeregister(Performative perf) {
309             debug("handleDeregister in df called");
310             try {
311                 // parse the content
312                 String content = perf.getContent();
313                 String agreeCont = new String(content);
314                 AbsContentElement slcontent = codec.decode(SLOntology.getInstance(),content);
315                 AbsAgentAction act = (AbsAgentAction) slcontent.getAbsObject("ACTION");
316                 // check and see if it is a deregistration message, if it is then agree to register,
317                 // otherwise send a not understood
318                 if (act != null) {
319                     if (act.getTypeName().equalsIgnoreCase("deregister")) {
320                         sendAgree(perf);
321                     }
322                     else {
323                         simpleReply(perf,UNEXPECTED,"not_understood");
324                     }
325                 }
326                 String name = new String();
327                 AbsConcept absActor = (AbsConcept) slcontent.getAbsObject("ACTOR");
328                 AbsAggregate agentAddresses = (AbsAggregate) absActor.getAbsObject("addresses");
329                 AbsPrimitive agentName = (AbsPrimitive) absActor.getAbsObject("name");
330                 boolean proceed = checkAuthority("df", agentName, agentAddresses, perf);
331                 if (!proceed) {
332                     simpleReply(perf, NOT_AUTHORISED,"refuse");
333                 }
334                 String searchAddr = SL_Util.makeAddressString(agentName,agentAddresses);
335                 Enumeration allAddresses = registered_agents.keys();
336                 while (allAddresses.hasMoreElements()) {
337                     String current = (String) allAddresses.nextElement();
338                     if (current.equals(searchAddr)) {
339                         registered_agents.remove(current);
340                         informDone(perf);
341                         return;
342                     }
343                 }
344             } catch (Exception e) {
345                 e.printStackTrace();
346             }
347         }
348         
349         
350         
351         
352         
353         
354         public void handleModify(Performative perf) {
355             debug("handleModify in df called");
356             try {
357                 // always banned.
358                 String content = perf.getContent();
359                 String agreeCont = new String(content);
360                 AbsContentElement slcontent = codec.decode(SLOntology.getInstance(),content);
361                 AbsAgentAction act = (AbsAgentAction) slcontent.getAbsObject("ACTION");
362                 if (act != null) {
363                     if (act.getTypeName().equalsIgnoreCase("modify")) {
364                         AbsConcept absActor = (AbsConcept) slcontent.getAbsObject("ACTOR");
365                         AbsAggregate agentAddresses = (AbsAggregate) absActor.getAbsObject("addresses");
366                         AbsPrimitive agentName = (AbsPrimitive) absActor.getAbsObject("name");
367                         String searchAddr = SL_Util.makeAddressString(agentName,agentAddresses);
368                         Enumeration allAddresses = registered_agents.keys();
369                         while (allAddresses.hasMoreElements()) {
370                             String current = (String) allAddresses.nextElement();
371                             if (current.equals(searchAddr)) {
372                                 registered_agents.remove(current);
373                                 registered_agents.put(searchAddr, makeDescription(act));
374                                 informDone(perf);
375                                 return;
376                             }
377                         }}
378                     else {
379                         simpleReply(perf,UNEXPECTED,"not_understood");
380                     }
381                 }
382             } catch (Exception e ) {
383                 e.printStackTrace();
384             }
385         }
386         
387         
388         
389         
390         public void handleSearch(Performative perf) {
391             try {
392                 debug("In handle search");
393                 Enumeration members = registered_agents.elements();
394                 String content = perf.getContent();
395                 debug("content = " + content);
396                 AbsContentElement slcontent = codec.decode(SLOntology.getInstance(),content);
397                 AbsAgentAction act = (AbsAgentAction) slcontent.getAbsObject("ACTION");
398                 // should check policy
399                 if (act != null) {
400                     System.out.println("not a null action");
401                     if (act.getTypeName().equalsIgnoreCase("search")) {
402                         System.out.println("action is search");
403                         sendAgree(perf);
404                         // agree not sent in initail version
405                     }
406                     else {
407                         System.out.println("was not a search!");
408                         simpleReply(perf,UNEXPECTED,"not_understood");
409                     }
410                 }
411                 else {
412                     System.out.println("was a null action!"); }
413                 if (!registered_dfs.isEmpty()) {
414                     Enumeration allDfs = registered_dfs.keys();
415                     while (allDfs.hasMoreElements()) {
416                         // set thread timeout
417                         // set handling rules
418                         // go, go
419                     }
420                 }
421                 DF_Description toMatch = makeDescription(act);
422                 String results = getDescriptions(toMatch);
423                 Performative inform = new Performative("inform");
424                 inform.setSender("df");
425                 inform.setReceiver(perf.getSender());
426                 inform.setLanguage("FIPA-SL0");
427                 inform.setProtocol("FIPA-Request");
428                 inform.setOntology("FIPA-Agent-Management");
429                 inform.setConversationId(perf.getConversationId());
430                 inform.setInReplyTo(perf.getReplyWith());
431                 String in = perf.getContent();
432                 String rcontent = new String("((result "+ in.substring(1,in.length()-1) + " (set " );
433                 rcontent += results;
434                 rcontent+= ")))";
435                 inform.setContent(rcontent);
436                 inform.send(context);
437             }
438             catch (Exception e) {
439                 e.printStackTrace() ;// for now
440             }
441         }
442         
443         /***
444          *returns a string that contains the df_descriptions that are matches for this df_description.
445          */
446         public String getDescriptions(DF_Description toMatch) {
447             Enumeration allDescriptions = registered_agents.elements();
448             String results = new String();
449             // case one : the description is constrained
450             if (toMatch != null) {
451                 while (allDescriptions.hasMoreElements()) {
452                     DF_Description desc = (DF_Description) allDescriptions.nextElement();
453                     if (toMatch.match(desc)) {
454                         results+=desc.toString() +" ";
455                     }}
456             }
457             // no constraints : avoid a null pointer
458             else {
459                 while (allDescriptions.hasMoreElements()) {
460                     DF_Description desc = (DF_Description) allDescriptions.nextElement();
461                     results+=desc.toString() +" ";
462                 }
463             }
464             return results;
465         }
466         
467         
468         
469         
470         public String agentDescToSL(Fact fact) {
471             return new String();
472         }
473         
474         
475         public void informDone(Performative perf) {
476             String content = perf.getContent();
477             Performative inform = new Performative("inform");
478             inform.setSender("df");
479             inform.setReceiver(perf.getSender());
480             inform.setLanguage("FIPA-SL0");
481             inform.setProtocol("FIPA-Request");
482             inform.setOntology("FIPA-Agent-Management");
483             inform.setConversationId(perf.getConversationId());
484             inform.setInReplyTo(perf.getReplyWith());
485             inform.setContent("(done" + content + ")");
486             send(inform);
487         }
488         
489         /***
490          *  simpleReply lets you reply to a message using the result convention of FIPA
491          * what I mean is: in FIPA there are alot of messages like "refuse original reason"
492          * or "not_understood original reason", and this method lets you send them
493          * pretty simply
494          **/
495         public void simpleReply(Performative inPerf, String reason, String replyType) {
496             Performative outPerf = new Performative(replyType);
497             outPerf.setReceiver(inPerf.getSender());
498             outPerf.setSender("df");
499             outPerf.setLanguage("FIPA-SL0");
500             outPerf.setProtocol("FIPA-Request");
501             outPerf.setOntology("FIPA-Agent-Management");
502             outPerf.setConversationId(inPerf.getConversationId());
503             outPerf.setInReplyTo(inPerf.getReplyWith());
504             String content = inPerf.getContent();
505             
506             // needs rewriting with SLParser
507             FIPA_DF_Management_Content cont = ZeusParser.FIPA_DF_Management_Content(content);
508             cont.setResult(reason);
509             outPerf.setContent(cont.toString());
510         }
511         
512         
513         /***
514          *make an "agree" response in SL
515          **/
516         public void sendAgree(Performative perf) {
517             Performative agree = new Performative("agree");
518             agree.setContent( perf.getContent().substring(0,perf.getContent().length() -1)+"true)");
519             agree.setLanguage("FIPA-SL0");
520             agree.setProtocol("FIPA-Request");
521             agree.setOntology("FIPA-Agent-Management");
522             agree.setConversationId(perf.getConversationId());
523             agree.setInReplyTo(perf.getReplyWith());
524             agree.setReceiver(perf.getSender());
525             agree.setSender("df");
526             agree.send(context);
527         }
528         
529         
530         
531         void debug(String str) {
532             System.out.println(str);
533         }
534         
535         
536         public static void main(String param[]) {
537             Performative perf = new Performative("request");
538             perf.setContent( "((action      (agent-identifier        :name df@foo.com        :addresses (sequence iiop://foo.com/acc))      (search        (df-agent-description          :ontology (set meeting-scheduler)          :language (set FIPA-SL0 KIF)          :services (set  (service-description   :name profiling     :type meeting-scheduler-service)))        (search-constraints          :min-depth 2))))");
539             perf.setSender("Ion");
540             perf.setReceiver("me");
541             FIPA_DF_Services df = new FIPA_DF_Services();
542             df.handleSearch(perf);
543             
544         }
545     }