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  /*
25   * @(#)OrganisationDb.java 1.00
26   */
27  
28  package zeus.actors;
29  
30  import java.util.*;
31  import zeus.util.*;
32  import zeus.concepts.*;
33  import zeus.actors.event.*;
34  
35  /***
36   * The Organisation Database stores the agent's beliefs about its organisational
37   * relationships with other agents. Each relationship will be of one of the
38   * following types:
39   * <ul>
40   * <li> Peer	- which is the default relationship which entails no restrictions
41   *              or assumptions about agent interaction
42   * <li> Superior - here the acquaintance is believed to possess higher authority
43   *                 than this agent, and can issue orders that this agent must obey
44   * <li> Subordinate	- the acquaintance is believed to have less authority than
45   *                    this agent, and can be issued orders that it must obey
46   * <li> Co-worker	- the acquaintance belongs to the same 'community' as this
47   *                  agent, and will be asked before peers when any resources are required
48   * </ul>
49   */
50  
51  
52  public class OrganisationDb extends AbilityDb {
53    protected HSet[]  eventMonitor = new HSet[4];
54  
55    private static final int ADD    = 0;
56    private static final int MODIFY = 1;
57    private static final int DELETE = 2;
58    private static final int ACCESS = 3;
59  
60    protected Hashtable relations = new Hashtable();
61    protected String agentName = "null"; 
62  
63  // meaningless init  to allow rearch
64    public OrganisationDb () {
65     super(); 
66     for(int i = 0; i < eventMonitor.length; i++ )
67          eventMonitor[i] = new HSet();
68    }
69  
70    public OrganisationDb(AgentContext context) {
71       super(context);
72       agentName = context.whoami();
73       context.set(this);
74  
75       for(int i = 0; i < eventMonitor.length; i++ )
76          eventMonitor[i] = new HSet();
77    }
78  
79    public void addRelation(Vector List) {
80      for(int i = 0; i < List.size(); i++ ) {
81        String agent = (String) List.elementAt(i++);
82        String relation = (String) List.elementAt(i);
83        this.addRelation(agent,relation);
84      }
85    }
86  
87    
88    public void modifyAgentRelation(String agent, String oldRelation,
89                                    String newRelation) {
90        removeRelation(agent,oldRelation);
91        addRelation(agent,newRelation);
92    }
93  
94    
95    public Vector allRelations() {
96      Vector result = new Vector();
97  
98      Vector peers = getPeers();
99      String agent;
100     for(int i = 0; i < peers.size(); i++ ) {
101        agent = (String)peers.elementAt(i);
102        result.addElement(new Relationship(agent,"peer"));
103     }
104 
105     Enumeration enum = relations.keys();
106     String relation;
107     Vector List;
108     while( enum.hasMoreElements() ) {
109       relation = (String)enum.nextElement();
110       List = (Vector)relations.get(relation);
111 
112       for(int i = 0; i < List.size(); i++ ) {
113          agent = (String)List.elementAt(i);
114          notifyMonitors(agent,relation,ACCESS);
115          result.addElement(new Relationship(agent,relation));
116       }
117     }
118     return result;
119   }
120 
121 
122   public void addRelation(String agent, String relation) {
123     addItem(agent,knownAgents);
124     Vector List = (Vector)relations.get(relation);
125     if ( List == null ) {
126        List = new Vector();
127        relations.put(relation,List);
128     }
129     if ( !List.contains(agent) ) {
130        List.addElement(agent);
131        notifyMonitors(agent,relation,ADD);
132     }
133   }
134 
135   
136   public void removeRelation(String agent, String relation) {
137     Vector List = (Vector)relations.get(relation);
138     if ( List == null ) return;
139     if ( List.contains(agent) ) {
140        List.removeElement(agent);
141        notifyMonitors(agent,relation,DELETE);
142     }
143   }
144   
145   
146   public boolean hasRelation(String agent, String relation) {
147     boolean result = false;
148     if ( relation.equals("peer") ) {
149        Vector peers = getPeers();
150        result = peers.contains(agent);
151        notifyMonitors(agent,"peer",ACCESS);
152     }
153     else {
154        Vector List = (Vector)relations.get(relation);
155        if ( List == null ) return false;
156        result = List.contains(agent);
157        notifyMonitors(agent,"relation",ACCESS);
158     }
159     return result;
160   }
161   
162 
163   public boolean hasRelation(String relation) {
164     boolean result = false;
165     if ( relation.equals("peer") ) {
166        Vector peers = getPeers();
167        result = !peers.isEmpty();
168     }
169     else {
170        Vector List = (Vector)relations.get(relation);
171        result = List != null && !List.isEmpty();
172     }
173     return result;
174   }
175 
176   
177   public Vector anyAgent(Goal goal, Vector ignore) {
178     Core.DEBUG(4,"anyAgent() = " + goal );
179 
180     if ( ignore == null )
181        ignore = new Vector();
182 
183     Vector agents = Misc.difference(knownAgents,ignore);
184     agents.removeElement(agentName);
185     return _anyAgent(agents,goal);
186   }
187 
188   
189   private Vector getPeers() {
190     Vector peers;
191     Vector others = new Vector();
192     Enumeration enum = relations.elements();
193     while( enum.hasMoreElements() )
194        others = Misc.union(others,(Vector)enum.nextElement());
195     peers = Misc.difference(knownAgents,others);
196     peers.removeElement(agentName);
197     return peers;
198   }
199 
200   
201   protected  Vector _anyAgent(Vector agents, Goal goal) {
202     AbilitySpec ability;
203     Vector can_do = null;
204     String name;
205     AbilityDbItem item;
206     String key = null;
207     Vector result = new Vector();
208 
209     ability = goal.getAbility();
210     if ( (can_do = findAll(ability)) != null ) {
211        Core.DEBUG(4,"anyAgent: " + ability + "\nwith\n" + can_do);
212        for( int j = 0; j < can_do.size(); j++ ) {
213           item = (AbilityDbItem)can_do.elementAt(j);
214           name = item.getAgent();
215           Core.DEBUG(4,"anyAgent considering: " + name);
216           if ( agents.contains(name) && !result.contains(name) ) {
217              result.addElement(name);
218              Core.DEBUG(4,"t" + name + " selected");
219           }
220           else {
221             Core.DEBUG(4,"t" + name + " not selected");
222           }
223        }
224     }
225     Core.DEBUG(4,"anyAgent result = " + result);
226     return result;
227   }
228 
229 
230   /***
231    * If your code needs to react to changes in the agent's organisational beliefs
232    * use this method to add a RelationMonitor to this component.
233    */
234   public void addRelationMonitor(RelationMonitor monitor, long event_type,
235                                  boolean notify_previous)  {
236       addRelationMonitor(monitor,event_type);
237       if ( !notify_previous ) return;
238 
239       RelationEvent event;
240       Relationship data;
241       Vector peers = getPeers();
242       String agent;
243       for(int i = 0; i < peers.size(); i++ ) {
244          agent = (String)peers.elementAt(i);
245          data = new Relationship(agent,"peer");
246          event = new RelationEvent(this,data,RelationEvent.ACCESS_MASK);
247          monitor.relationAccessedEvent(event);
248          event = new RelationEvent(this,data,RelationEvent.ADD_MASK);
249          monitor.relationAddedEvent(event);
250       }
251 
252       Enumeration enum = relations.keys();
253       Vector List;
254       String relation;
255       while( enum.hasMoreElements() ) {
256          relation = (String)enum.nextElement();
257          List = (Vector)relations.get(relation);
258          for(int i = 0; i < List.size(); i++ ) {
259             agent = (String)List.elementAt(i);
260             data = new Relationship(agent,relation);
261             event = new RelationEvent(this,data,RelationEvent.ACCESS_MASK);
262             monitor.relationAccessedEvent(event);
263             event = new RelationEvent(this,data,RelationEvent.ADD_MASK);
264             monitor.relationAddedEvent(event);
265          }
266       }
267    }
268 
269    public void addRelationMonitor(RelationMonitor monitor, long type) {
270       if ( (type & RelationEvent.ADD_MASK) != 0 )
271          eventMonitor[ADD].add(monitor);
272       if ( (type & RelationEvent.MODIFY_MASK) != 0 )
273          eventMonitor[MODIFY].add(monitor);
274       if ( (type & RelationEvent.DELETE_MASK) != 0 )
275          eventMonitor[DELETE].add(monitor);
276       if ( (type & RelationEvent.ACCESS_MASK) != 0 )
277          eventMonitor[ACCESS].add(monitor);
278    }
279 
280    public void removeRelationMonitor(RelationMonitor monitor, long type) {
281       if ( (type & RelationEvent.ADD_MASK) != 0 )
282          eventMonitor[ADD].remove(monitor);
283       if ( (type & RelationEvent.MODIFY_MASK) != 0 )
284          eventMonitor[MODIFY].remove(monitor);
285       if ( (type & RelationEvent.DELETE_MASK) != 0 )
286          eventMonitor[DELETE].remove(monitor);
287       if ( (type & RelationEvent.ACCESS_MASK) != 0 )
288          eventMonitor[ACCESS].remove(monitor);
289    }
290 
291    private void notifyMonitors(String agent, String relation, int type) {
292       if ( eventMonitor[type].isEmpty() ) return;
293 
294       Enumeration enum = eventMonitor[type].elements();
295       Relationship data = new Relationship(agent,relation);
296       RelationMonitor monitor;
297       RelationEvent event;
298       switch(type) {
299          case ADD:
300               event = new RelationEvent(this,data,RelationEvent.ADD_MASK);
301               while( enum.hasMoreElements() ) {
302                  monitor = (RelationMonitor)enum.nextElement();
303                  monitor.relationAddedEvent(event);
304               }
305               break;
306          case MODIFY:
307               event = new RelationEvent(this,data,RelationEvent.MODIFY_MASK);
308               while( enum.hasMoreElements() ) {
309                  monitor = (RelationMonitor)enum.nextElement();
310                  monitor.relationModifiedEvent(event);
311               }
312               break;
313          case DELETE:
314               event = new RelationEvent(this,data,RelationEvent.DELETE_MASK);
315               while( enum.hasMoreElements() ) {
316                  monitor = (RelationMonitor)enum.nextElement();
317                  monitor.relationDeletedEvent(event);
318               }
319               break;
320          case ACCESS:
321               event = new RelationEvent(this,data,RelationEvent.ACCESS_MASK);
322               while( enum.hasMoreElements() ) {
323                  monitor = (RelationMonitor)enum.nextElement();
324                  monitor.relationAccessedEvent(event);
325               }
326               break;
327       }
328    }
329 }