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  
24  package zeus.actors.rtn;
25  
26  import java.util.*;
27  import zeus.util.*;
28  import zeus.concepts.*;
29  import zeus.actors.rtn.util.*;
30  import zeus.actors.*;
31  
32  public class AuditTable {
33     public static final int CHILD = 0;
34     public static final int ROOT = 1;
35  
36     protected static final int GOAL = 0;
37     protected static final int KEY = 1;
38  
39     protected Hashtable contracts = new Hashtable();
40     protected Hashtable auxiliary = new Hashtable();
41     protected Hashtable router    = new Hashtable();
42     protected Engine    engine    = null;
43  
44  
45     AuditTable(Engine engine) {
46        Assert.notNull(engine);
47        this.engine = engine;
48     }
49  
50  /***
51    ProducerRecord/ConsumerRecord
52    -----------------------------
53  
54    says to agent <c>
55         expect data from agent <p>
56         with comms ref <comms_key> and internal ref <cid/uid>
57         do action
58            allocate data to record <cid>
59            at precondition slot <pid/uid>
60  
61  
62    says to agent <p>
63         expect data from yourself record <pid>
64         with internal ref <cid/uid> [at time <s>, amount <a>, consumed <b>]
65         do action
66            1. send data to agent <c>
67               with ref <comms_key>
68            2. Request payment
69  */
70  
71     public void addProducerRecords(Vector records) {
72        Core.DEBUG(2,"AddProducerRecords " + records);
73        if ( records == null ) return;
74        for(int i = 0; i < records.size(); i++ )
75           addRoutingRecord((RoutingRecord)records.elementAt(i));
76     }
77     
78     
79     public void addConsumerRecords(Vector records) {
80        Core.DEBUG(2,"AddConsumerRecords " + records);
81        if ( records == null ) return;
82        for(int i = 0; i < records.size(); i++ )
83           addRoutingRecord((RoutingRecord)records.elementAt(i));
84     }
85  
86  
87     protected void addRoutingRecord(RoutingRecord rec) {
88        String myself = engine.getAgentContext().whoami();
89        if ( rec.producer.equals(myself) || rec.consumer.equals(myself) ){
90           String key = rec.consumer_id + "/" + rec.use_ref;
91           Object ob = router.put(key,rec);
92           if ( ob != null )
93              Core.ERROR(rec.equals(ob),2001,this);
94        }
95     }
96     
97  
98     public synchronized void add(Contract entry) {
99        Core.DEBUG(2,"AddContract " + entry);
100       Object ob;
101       ob = contracts.put(entry.goal.getId(),entry);
102       Core.ERROR(ob == null,2002,this);
103    }
104    
105    
106    public synchronized void add(Goal goal, String key, double cost,
107                                 boolean delivered, boolean paid, String agent,
108                                 String owner, double timeout) {
109       add(new Contract(goal,key,cost,delivered,paid,agent,owner,timeout));
110    }
111    
112    
113    public synchronized void del(Goal goal) {
114       Core.DEBUG(2,"Del goal " + goal);
115 /*
116       String goalId = goal.getId();
117       this.remove(goalId);
118       Contract aux = (Contract)auxiliary.remove(goalId);
119       String myself = engine.getAgentContext().whoami();
120       if ( aux != null && !aux.owner.equals(myself) ) {
121          MsgHandler hd = engine.getAgentContext().MsgHandler();
122          Vector goals = new Vector();
123          goals.addElement(aux.goal);
124          hd.send_message(aux.owner,aux.key,"exception",goals);
125       }
126 */
127    }
128    
129    
130    public synchronized void goodsReceived(DelegationStruct ds) {
131       Core.DEBUG(2,"GoodsReceived\n" + ds);
132       Core.DEBUG(2,this);
133 
134       Planner table = engine.getAgentContext().Planner();
135       MsgHandler handler = engine.getAgentContext().MsgHandler();
136       ResourceDb db = engine.getAgentContext().ResourceDb();
137       OntologyDb ontology = engine.getAgentContext().OntologyDb();
138       String myself = engine.getAgentContext().whoami();
139 
140       String agent;
141       RoutingRecord rec = null;
142       Contract entry;
143       Fact item, money;
144 
145       if ( (rec = (RoutingRecord)router.remove(ds.key)) != null ) {
146          if ( ds.agent.equals(myself) ) {
147             Core.ERROR(rec.producer.equals(myself),1001,this);
148             // send result to customer
149             engine.continue_dialogue(rec.comms_key,rec.consumer,"inform",
150 				     "result", ds.key, ds.goals);
151 
152 	        // mark as delivered
153             entry = (Contract)contracts.get(rec.producer_id);
154             entry.delivered = true;
155             // INVOICE customer
156             money = ontology.getFact(Fact.VARIABLE,OntologyDb.MONEY);
157             money.setValue(OntologyDb.AMOUNT,Double.toString(entry.cost));
158             Vector data = new Vector();
159             data.addElement(money);
160             engine.continue_dialogue(entry.key,entry.owner,"inform",
161 				     "invoice", rec.producer_id, data);
162          }
163          else {
164             Core.ERROR(rec.consumer.equals(myself),1002,this);
165             entry = (Contract)contracts.get(rec.producer_id);
166             item = (Fact)ds.goals.elementAt(0);
167 	        // set unit cost
168 	        if ( item.isa(OntologyDb.ENTITY) ) {
169                double unit_cost = entry.cost/item.getNumber();
170                item.setValue(OntologyDb.COST,Double.toString(unit_cost));
171             }
172             String goal_id = rec.consumer_id;
173             String subgoal_id = rec.producer_id + "/" + rec.use_ref;
174             table.notifyReceived(item,goal_id,subgoal_id);
175             handler.removeRule(ds.key);
176             // mark DELIVERED
177             if ( entry != null )
178                entry.delivered = true;
179             }
180         }
181       else {
182         debug ("toString" + ds.toString()); 
183         debug ("key " + ds.key); 
184         debug ("contracts " + contracts.toString()); 
185          entry = (Contract)contracts.get(ds.key);
186          if ( ds.agent.equals(myself) ) {
187             if ( entry.owner.equals(myself) ) {
188                // goods for myself by myself
189    	       // set unit cost
190                contracts.remove(ds.key);
191                item = (Fact)ds.goals.elementAt(0);
192    	       if ( item.isa(OntologyDb.ENTITY) ) {
193                   double unit_cost = entry.cost/item.getNumber();
194                   item.setValue(OntologyDb.COST,Double.toString(unit_cost));
195                }
196 	       db.add(ds.goals);
197             }
198             else {
199 	       // goods by myself for someone else; selling my service
200                // send result to customer
201                engine.continue_dialogue(entry.key,entry.owner,"inform",
202 	          "result", ds.key, ds.goals);
203 
204 	       // mark as delivered
205                entry.delivered = true;
206                // INVOICE customer
207                money = ontology.getFact(Fact.VARIABLE,OntologyDb.MONEY);
208                money.setValue(OntologyDb.AMOUNT,Double.toString(entry.cost));
209                Vector data = new Vector();
210                data.addElement(money);
211                engine.continue_dialogue(entry.key,entry.owner,"inform",
212 	          "invoice", ds.key, data);
213             }
214          }
215          else {
216             // goods from someone for me
217             Core.DEBUG (3, entry.toString()); 
218             Core.DEBUG (3, entry.owner); 
219             
220             Core.ERROR(entry.owner.equals(myself),1075,this);
221    	    // set unit cost
222             entry.delivered = true;
223             item = (Fact)ds.goals.elementAt(0);
224    	    if ( item.isa(OntologyDb.ENTITY) ) {
225                double unit_cost = entry.cost/item.getNumber();
226                item.setValue(OntologyDb.COST,Double.toString(unit_cost));
227             }
228 	    db.add(ds.goals);
229          }
230       }
231       Core.DEBUG(2,"GoodsReceived - post\n" + this);
232    }
233 
234 
235     //synchronized 
236    public  void invoiceReceived(DelegationStruct ds) {
237       Core.DEBUG(2,"AuditTable invoiceReceived:\n" + ds);
238       Core.DEBUG(2,this);
239 
240       ResourceDb db = engine.getAgentContext().ResourceDb();
241       MsgHandler handler = engine.getAgentContext().MsgHandler();
242       String myself = engine.getAgentContext().whoami();
243 
244       Contract entry = (Contract)contracts.remove(ds.key);
245       Core.DEBUG(3,"InvoiceReceived: contract\n\t" + entry);
246       Assert.notFalse(entry.agent.equals(ds.agent));
247       Assert.notFalse(entry.owner.equals(myself));
248       entry.paid = true;
249 
250       Core.DEBUG(3,"InvoiceReceived: about to debit");
251       Fact money = db.debit(entry.cost);
252       Core.DEBUG(3,"InvoiceReceived: debit = " + money);
253 
254       Vector data = new Vector();
255       data.addElement(money);
256 
257       engine.continue_dialogue(entry.key,entry.agent,"inform",
258          "payment", ds.key, data);
259       handler.removeRule(entry.key);
260       Core.DEBUG(2,"AuditTable invoiceReceived - post:\n" + this);
261    }
262 
263    public synchronized void paymentReceived(DelegationStruct ds) {
264       Core.DEBUG(2,"AuditTable paymentReceived:\n" + ds);
265       Core.DEBUG(2,this);
266 
267       ResourceDb db = engine.getAgentContext().ResourceDb();
268       String myself = engine.getAgentContext().whoami();
269 
270       Contract entry = (Contract)contracts.remove(ds.key);
271       Assert.notFalse(entry.owner.equals(ds.agent));
272       Assert.notFalse(entry.agent.equals(myself));
273       entry.paid = true;
274 
275       // Payment for a job I did
276       Fact money = (Fact)ds.goals.elementAt(0);
277       db.add(money);
278       Core.DEBUG(2,"AuditTable paymentReceived - post\n" + this);
279    }
280 
281 
282    public synchronized int exception(DelegationStruct ds) {
283       Core.DEBUG(2,"AuditTable exception:\n" + ds);
284 /*
285       Core.DEBUG(2,this);
286 
287       Contract entry = getEntry(KEY,ds.key);
288       this.remove(entry.goal.getId());
289 
290       Planner table = engine.getAgentContext().Planner();
291       Goal g = table.recreateSubgoal(entry.goal);
292 
293       ds.goals.removeAllElements();
294       ds.goals.addElement(g);
295       String myself = engine.getAgentContext().whoami();
296 
297       if ( ds.agent.equals(myself) ) {
298          auxiliary.put(g.getId(),entry);
299          if ( entry.owner.equals(myself) )
300             entry.cost = 0;
301          return ROOT;
302       }
303       else {
304          Contract aux;
305          aux = (Contract)auxiliary.get(entry.goal.getId());
306          if ( aux != null ) {
307             auxiliary.remove(entry.goal.getId());
308             Assert.notFalse(auxiliary.put(g.getId(),aux) == null);
309             return ROOT;
310          }
311          return CHILD;
312       }
313 */
314          return CHILD;
315    }
316 
317 
318    public synchronized void cancel(DelegationStruct ds) {
319       Core.DEBUG(2,"AuditTable cancel:\n" + ds);
320 /*
321       Core.DEBUG(2,this);
322 
323       String myself = engine.getAgentContext().whoami();
324       Contract entry = getEntry(KEY,ds.key);
325 
326       Assert.notFalse(entry.agent.equals(myself));
327       Assert.notFalse(ds.agent.equals(entry.owner));
328 
329       this.remove(entry.goal.getId()); // remove entry
330       auxiliary.remove(entry.goal.getId()); // remove entry
331       redirection.remove(entry.goal.getId()); // remove entry
332 
333       engine.getAgentContext().Planner().reject(ds.goals, new Vector());
334 */
335    }
336    public synchronized void cancel(String goal_id) {
337       Core.DEBUG(2,"AuditTable cancel: " + goal_id);
338 /*
339       MsgHandler handler = engine.getAgentContext().MsgHandler();
340       String myself = engine.getAgentContext().whoami();
341       Core.DEBUG(2,this);
342 
343       if ( entry == null ) return;
344 
345       this.remove(goal_id);
346       redirection.remove(goal_id);
347       if ( !entry.agent.equals(myself) ) {
348          Vector goals = new Vector();
349          goals.addElement(entry.goal);
350          handler.send_message(entry.agent,entry.key,"cancel",goals);
351       }
352 */
353 
354 
355    }
356    public synchronized void enact(DelegationStruct ds) {
357       Core.DEBUG(2,"AuditTable enact:\n" + ds);
358       
359       /*
360       Planner table = engine.getAgentContext().Planner();
361       MsgHandler handler = engine.getAgentContext().MsgHandler();
362       String myself = engine.getAgentContext().whoami();
363 
364       Core.DEBUG(2,this);
365 
366       Contract entry = contracts.get(KEY,ds.key);
367       Assert.notFalse(entry.owner.equals(ds.agent));
368       Assert.notFalse(entry.agent.equals(myself));
369 
370       Goal g = (Goal)ds.goals.elementAt(0);
371       PlannerEnactStruct es = table.enact(g,entry.goal);
372       if ( !es.ok ) return;
373 
374       // add entries referring to self
375       add(g, g.getId(), entry.cost, false, false, entry.agent,
376           entry.owner, g.getEndTime());
377       if ( !entry.owner.equals(entry.agent) )
378          router.add(g.getId(),"coordination_dialog");
379 
380       // add entries for children
381       String goal_id;
382       Vector goals;
383       for(int i = 0; i < es.external.size(); i++ ) {
384          g = (Goal)es.external.elementAt(i);
385          goal_id = (String)es.table.get(g.getId());
386          entry = getEntry(GOAL,goal_id);
387          Assert.notFalse(entry.owner.equals(myself));
388          add(g, g.getId(), entry.cost, false, false, entry.agent,
389              entry.owner, g.getEndTime());
390          router.add(g.getId(),"coordination_dialog");
391 
392          goals = new Vector();
393          goals.addElement(g);
394          handler.send_message(entry.agent,entry.key,"enact",goals);
395       }
396       */
397    }
398    
399    
400    protected synchronized boolean cleanup(Contract entry) {
401 /*
402       if ( entry.delivered && entry.paid ) {
403          if ( entry.goal != null )
404             this.remove(entry.goal.getId());
405          else
406             this.remove(entry.key);
407 
408          return true;
409       }
410       else
411          return false;
412 */
413       return false;
414    }
415    public Object remove(Object key) {
416 /*
417       Contract entry = (Contract)super.remove(key);
418       if ( entry != null ) {
419          MContext msgContext = engine.getAgentContext().MsgContext();
420          msgContext.del(entry.key);
421       }
422       return entry;
423 */
424       return null;
425    }
426 
427    public String toString() {
428       String output = "Audit Table Entries\n";
429       String key;
430       Enumeration keys = contracts.keys();
431       Contract entry;
432       RoutingRecord record;
433 
434       output += "...Contracts...\n";
435       while( keys.hasMoreElements() ) {
436          key = (String)keys.nextElement();
437          entry = (Contract)contracts.get(key);
438          output += "Table-key = " + key + "\n" + entry + "\n";
439       }
440 
441       output += "...Routing...\n";
442       keys = router.keys();
443       while( keys.hasMoreElements() ) {
444          key = (String)keys.nextElement();
445          record = (RoutingRecord)router.get(key);
446          output += "Table-key = " + key + "\n" + record + "\n";
447       }
448 
449       output += "\n**************\n";
450       return output;
451    }
452    
453    
454    public void debug (String str) { 
455     //System.out.println("audittable >> " + str);
456     }
457 
458 }