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-9. All Rights Reserved.
18  * 
19  * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20  */
21  
22  /*
23   * @(#)d1.java 1.03b
24   */
25  
26  package zeus.actors.graphs;
27  
28  import java.util.*;
29  import zeus.util.*;
30  import zeus.concepts.*;
31  import zeus.actors.*;
32  import zeus.actors.rtn.*;
33  import zeus.actors.rtn.util.*;
34  
35  public class d1 extends Node {
36  
37    protected static final int NOT_FOUND = 0;
38    protected static final int SEARCHING = 1;
39    protected static final int NOT_SOUGHT = 2;
40  
41  /***
42     Purpose: get all agents for given goal - if oragnisationDb
43     does not contain applicable agents, then contact registered
44     facilitators through the organisationDb
45  */
46  
47  // ST 050500 1.03bB node description due to CVB
48     private String node_desc = "do/find sellers; do/find service";
49     
50     
51     public final String getDesc()
52        {return node_desc;}
53     
54     
55     public final void setDesc(String node_desc) 
56        {this.node_desc = node_desc;}
57     // ST 050500 1.03bE
58     
59     public d1() {
60        super("d1");
61     }
62  
63     // memory useful for backtracking
64  
65     protected int abilitySought(String type) {
66        /***
67        First we should clear 'queryTable' of entries older the a predefined
68        age so that our agent should query known facilitators for the ability.
69        This way, our agent is periodically kept up-to-date
70        */
71  
72        String name;
73        KeyValue data;
74  
75        double now = context.now();
76        Hashtable queryTable = context.queryTable();
77        Enumeration enum = queryTable.keys();
78  
79        while( enum.hasMoreElements() ) {
80           name = (String) enum.nextElement();
81           data = (KeyValue)queryTable.get(name);
82           if ( data.value-now >= context.getFacilitatorRefresh() ) {
83              queryTable.remove(name);
84              context.MsgHandler().removeRule(data.key);
85           }
86        }
87  
88        data = (KeyValue)queryTable.get(type);
89        if ( data == null ) return NOT_SOUGHT;
90  
91        if ( data.value < context.now() )
92           return NOT_FOUND;
93        else
94           return SEARCHING;
95     }
96  
97     protected String findAgents(AbilitySpec a) {
98        if ( context.facilitators().isEmpty() ) return null;
99        AbilitySpec a1;
100       Hashtable queryTable = context.queryTable();
101 
102       String type = a.getType();
103       switch( abilitySought(type) ) {
104          case NOT_FOUND:
105               return null;
106 
107          case SEARCHING:
108               KeyValue struct = (KeyValue)queryTable.get(type);
109               return struct.key;
110 
111          case NOT_SOUGHT:
112               // try contacting known facilitators to find agents with
113               // required ability
114               OntologyDb ontology = context.OntologyDb();
115               a1 = new AbilitySpec(ontology.getFact(Fact.VARIABLE,type),0,0);
116 
117               Performative msg;
118               MailBox mbox = context.MailBox();
119               String key = context.newId();
120               String[] pattern = { "type", "inform", "in-reply-to", key };
121 
122               context.MsgHandler().addRule(new MessageRuleImpl(key, pattern,
123 	         MessageActionImpl.EXECUTE_ONCE,context.Engine(),
124 		 "agentWithAbilityFound")
125               );
126 
127               for(int i = 0; i < context.facilitators().size(); i++ ) {
128                  msg = new Performative("query-ref");
129                  msg.setReceiver((String)context.facilitators().elementAt(i));
130                  msg.setContent("has_ability " + a1);
131                  msg.setReplyWith(key);
132                  mbox.sendMsg(msg);
133               }
134               // add ability to list of abilities which are being sought
135               double t = context.now();
136               if ( !context.facilitators().isEmpty() )
137                  t += context.getFacilitatorTimeout();
138               queryTable.put(type,new KeyValue(key,t));
139               return key;
140       }
141       Assert.notNull(null);
142       return null;
143    }
144 
145    protected int exec() {
146       OrganisationDb db = context.OrganisationDb();
147 
148       DStruct ds = (DStruct)input;
149       // assume ds.goal has one element only
150       Goal goal = (Goal)ds.goal.elementAt(0);
151       ds.agents = db.anyAgent(goal,ds.ignore);
152 
153       Core.DEBUG(2, getDescription() + " anyAgent: " + ds.agents);
154 
155       if ( ds.agents.isEmpty() ) {
156          timeout = context.now() + context.getFacilitatorTimeout();
157 
158          // Adjust for confirm & reply times
159 	 Time t = goal.getConfirmTime();
160          if ( t != null )
161          timeout = Math.min(timeout,t.getTime());
162          t = goal.getReplyTime();
163          if ( t != null )
164          timeout = Math.min(timeout,t.getTime());
165 
166          msg_wait_key = findAgents(goal.getAbility());
167          Core.DEBUG(2, getDescription() + " msg_wait_key: " + msg_wait_key);
168          return (msg_wait_key != null) ? WAIT : FAIL;
169       }
170       output = ds;
171       return ds.agents.isEmpty() ? FAIL : OK;
172    }
173 
174    protected int continue_exec() {
175       OrganisationDb db = context.OrganisationDb();
176 
177       DStruct ds = (DStruct)input;
178       // assume ds.goal has one element only
179       Goal goal = (Goal)ds.goal.elementAt(0);
180       ds.agents = db.anyAgent(goal,ds.ignore);
181 
182       Core.DEBUG(2, getDescription() + " continue anyAgent: " + ds.agents);
183       output = ds;
184       return  ds.agents.isEmpty() ? FAIL : OK;
185    }
186 
187    protected void reset() {
188       // reset any state changed by exec()
189       DStruct ds = (DStruct) input;
190       ds.agents = null;
191    }
192 }