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   * @(#)ProtocolDb.java 1.00
26   */
27  
28  package zeus.actors;
29  
30  import java.io.*;
31  import java.util.*;
32  
33  import zeus.util.*;
34  import zeus.concepts.*;
35  import zeus.actors.event.*;
36  import zeus.actors.event.ProtocolDbNode;
37  
38  
39  /***
40   * The Protocol Database is a simple storage component that holds references
41   * to the social interaction protocols known by the agent. Note, although there
42   * is a class constructor () here it should never be used .
43   */
44  public class ProtocolDb extends Tree
45  {
46    protected Hashtable factIndex;
47    private HSet[] eventMonitor = new HSet[4];
48  
49    private static final int ADD    = 0;
50    private static final int MODIFY = 1;
51    private static final int DELETE = 2;
52    private static final int ACCESS = 3;
53  
54    private static final int FAIL     = 0;
55    private static final int ANY      = 1;
56    private static final int RELATION = 2;
57    private static final int AGENT    = 4;
58  
59    Hashtable protocolInfoList;
60    AgentContext context;
61  
62    /***
63    *this init really is for architectural purposes only. I think
64     *instantiation without a parameter here could be bad!
65    */
66    public ProtocolDb () {
67    super (new ProtocolDbNode ("dummy"));
68    }
69  
70  //----------------------------------------------------------------------------
71    public ProtocolDb(OntologyDb model) {
72       super(new ProtocolDbNode(model.getRoot().toString()));
73       String rootName = model.getRoot().toString();
74       factIndex = new Hashtable();
75       factIndex.put(rootName, root);
76       createTree(getRoot(),model.getRoot());
77  
78       for(int i = 0; i < eventMonitor.length; i++ )
79          eventMonitor[i] = new HSet();
80  
81       protocolInfoList = new Hashtable();
82    }
83  //----------------------------------------------------------------------------
84     public ProtocolDb(AgentContext context) {
85       super(new ProtocolDbNode(context.OntologyDb().getRoot().toString()));
86       this.context = context;
87       context.set(this);
88       String rootName = context.OntologyDb().getRoot().toString();
89       factIndex = new Hashtable();
90       factIndex.put(rootName, root);
91       createTree(getRoot(),context.OntologyDb().getRoot());
92  
93       for(int i = 0; i < eventMonitor.length; i++ )
94          eventMonitor[i] = new HSet();
95  
96       protocolInfoList = new Hashtable();
97    }
98  //----------------------------------------------------------------------------
99    protected void createTree(TreeNode m_node,TreeNode a_node) {
100 
101     // takes contents of model and inserts them into the tree
102 
103     Vector children = a_node.getChildren();
104     TreeNode b_node;
105     TreeNode n_node;
106 
107     for(int i = 0; i < children.size(); i++ ) {
108        b_node = (TreeNode)children.elementAt(i);
109        n_node = new TreeNode( new ProtocolDbNode(b_node.toString()) );
110        m_node.addChild(n_node);
111        factIndex.put(b_node.toString(),n_node);
112        createTree(n_node,b_node);
113     }
114   }
115 //----------------------------------------------------------------------------
116   public void addProtocol(ProtocolInfo info) {
117      addProtocol(info,false);
118   }
119   public void addProtocol(Vector info) {
120     for(int i = 0; i < info.size(); i++ )
121        addProtocol((ProtocolInfo)info.elementAt(i),false);
122   }
123 
124 //----------------------------------------------------------------------------
125   private void addProtocol(ProtocolInfo info, boolean onlyLocal){
126      String factType;
127      ProtocolDbNode pDbNode;
128      TreeNode a_node;
129 
130      Core.DEBUG(3,"addProtocol");
131      Core.DEBUG(3,info);
132      StrategyInfo[] strategies = info.getConstraints();
133      for(int i = 0; i < strategies.length; i++ ){
134         factType = strategies[i].getFact().getType();
135         a_node = (TreeNode) factIndex.get(factType);
136         Core.DEBUG(3,"a_node = " + a_node);
137         pDbNode = (ProtocolDbNode) a_node.getValue();
138         pDbNode.addProtocol(info.getName(),strategies[i]);
139      }
140      protocolInfoList.put(info.getName(),info);
141      if (!onlyLocal) {
142         notifyMonitors(info,ADD);
143         notifyMonitors(info,ACCESS);
144      }
145   }
146 //----------------------------------------------------------------------------
147   public void removeProtocol(ProtocolInfo info){
148      removeProtocol(info, false);
149   }
150   public void removeProtocol(Vector info) {
151     for(int i = 0; i < info.size(); i++ )
152        removeProtocol((ProtocolInfo)info.elementAt(i),false);
153   }
154 //----------------------------------------------------------------------------
155   private void removeProtocol(ProtocolInfo info, boolean onlyLocal){
156        String protocol = info.getName();
157        Enumeration enum = values();
158        ProtocolDbNode node;
159        while( enum.hasMoreElements() ) {
160            node = (ProtocolDbNode)enum.nextElement();
161            node.deleteProtocol(protocol);
162        }
163        protocolInfoList.remove(protocol);
164        if ( !onlyLocal ) {
165           notifyMonitors(info,DELETE);
166           notifyMonitors(info,ACCESS);
167       }
168   }
169 //----------------------------------------------------------------------------
170 // Refers to a protocol name, not a particular protocol info.
171   public void modifyProtocol(ProtocolInfo info){
172      removeProtocol(info,true);
173      addProtocol(info,true);
174      notifyMonitors(info,MODIFY);
175      notifyMonitors(info,ACCESS);
176   }
177 
178 //----------------------------------------------------------------------------
179   public Vector getProtocols(Fact fact, String[] agents, String type) {
180       Core.DEBUG(3, "getProtocols");
181       Core.DEBUG(3, fact);
182       Core.DEBUG(3, agents);
183       Core.DEBUG(3, type);
184       TreeNode a_node = (TreeNode) factIndex.get(fact.getType());
185       ProtocolDbNode node;
186       Vector protocols;
187       Vector strategies;
188       StrategyInfo info;
189       String protocol;
190       ProtocolInfo protocolInfo;
191       int value;
192       Hashtable resultSet = new Hashtable();
193       
194       Core.DEBUG(3, "a_node0 = " + a_node);
195       while (a_node != null) {
196         Core.DEBUG(3, "a_node = " + a_node);
197         node = (ProtocolDbNode)a_node.getValue();
198         protocols = node.getProtocols();
199         Core.DEBUG(3, protocols);
200         for(int i = 0; i < protocols.size(); i++) {
201            protocol = (String) protocols.elementAt(i);
202            strategies = node.getStrategy(protocol);
203            Core.DEBUG(3, strategies);
204            for(int j = 0; j < strategies.size(); j++) {
205               info = (StrategyInfo)strategies.elementAt(j);
206               Core.DEBUG(3, info);
207               for(int k = 0; k < agents.length; k++) {
208                  protocolInfo = (ProtocolInfo)protocolInfoList.get(protocol);
209                  if ( protocolInfo.getType().equals(type) &&
210                       (value = constraintsOK(fact,agents[k],info)) != FAIL ) {
211                     if (info.getType() == StrategyInfo.USE)
212                        addToResultSet(new ProtocolDbResult(agents[k],
213                           protocol,info.getStrategy(),info.getParameters()),
214                           value,resultSet);
215                     else
216                        removeFromResultSet(agents[k],protocol,resultSet);
217                  }
218               }
219            }
220         }
221         a_node = a_node.getParent();
222       }
223       return sortResultSet(resultSet);
224   }
225 //----------------------------------------------------------------------------
226   private int constraintsOK(Fact fact, String agent, StrategyInfo info) {
227      Core.DEBUG(3, "constraintsOK");
228      Core.DEBUG(3, fact);
229      Core.DEBUG(3, agent);
230      Core.DEBUG(3, info);
231 
232      OrganisationDb organisationDb = context.OrganisationDb();
233      Bindings b;
234 
235      if ( context != null )
236         b = new Bindings(context.whoami());
237      else
238         b = new Bindings();
239 
240      Fact f1 = info.getFact();
241      if ( !f1.unifiesWithChild(fact,b) ) {
242         Core.DEBUG(3, "unifiesWithChild failed");
243         Core.DEBUG(3, f1);
244         return FAIL;
245      }
246 
247      int result = ANY;
248 
249      String[] agents = info.getAgents();
250      if ( agents.length > 0 ) {
251         if ( !Misc.member(agent,agents) )
252            return FAIL;
253         else
254            result *= AGENT;
255      }
256 
257      String[] relations = info.getRelations();
258      if ( relations.length > 0 ) {
259         boolean found = false;
260         for(int i = 0; !found && i < relations.length; i++ )
261   	   found |= organisationDb.hasRelation(agent,relations[i]);
262         if ( !found )
263            return FAIL;
264         else
265            result *= RELATION;
266      }
267      return result;
268   }
269 //----------------------------------------------------------------------------
270   private void removeFromResultSet(String agent, String protocol,
271                                    Hashtable resultSet) {
272      ProtocolDbResult item;
273      Vector List;
274      Enumeration enum = resultSet.elements();
275      while( enum.hasMoreElements() ) {
276         List = (Vector)enum.nextElement();
277         for(int i = 0; i< List.size(); i++) {
278            item = (ProtocolDbResult) List.elementAt(i);
279            if ( item.agent.equals(agent) && item.protocol.equals(protocol) )
280               List.removeElementAt(i--);
281         }
282      }
283   }
284   private void addToResultSet(ProtocolDbResult result, int grade,
285                               Hashtable resultSet) {
286      String Id = Integer.toString(grade);
287      Vector List = (Vector)resultSet.get(Id);
288      if ( List == null ) {
289         List = new Vector();
290         resultSet.put(Id,List);
291      }
292      List.addElement(result);
293   }
294 
295   private Vector sortResultSet(Hashtable resultSet) {
296      /* Possible value of result set keys are 1, 2, 4, 8 only,
297         corresponding to ANY, RELATION, AGENT, RELATION & AGENT */
298 
299      String Id;
300      Vector List;
301      Vector output = new Vector();
302 
303      for(int i = 8; i > 0; i /= 2 ) {
304         Id = Integer.toString(i);
305         List = (Vector)resultSet.get(Id);
306         if ( List != null )
307         output = Misc.union(output,List);
308      }
309      return output;
310    }
311 
312 
313    public void addProtocolMonitor(ProtocolMonitor monitor, long event_type,
314                                    boolean notify_previous)  {
315       addProtocolMonitor(monitor,event_type);
316       if ( !notify_previous ) return;
317 
318       Enumeration enum = protocolInfoList.elements();
319       ProtocolInfo info;
320       ProtocolEvent event;
321 
322       while( enum.hasMoreElements() ) {
323         info = (ProtocolInfo)enum.nextElement();
324         event = new ProtocolEvent(this,info,ProtocolEvent.ACCESS_MASK);
325         monitor.protocolAccessedEvent(event);
326         event = new ProtocolEvent(this,info,ProtocolEvent.ADD_MASK);
327         monitor.protocolAddedEvent(event);
328       }
329    }
330 
331    /***
332     * If your code needs to react to changes in the agent's stored protocols
333     * use this method to add a ProtocolMonitor.
334     */
335    public void addProtocolMonitor(ProtocolMonitor monitor, long event_type) {
336       if ( (event_type & ProtocolEvent.ADD_MASK) != 0 )
337          eventMonitor[ADD].add(monitor);
338       if ( (event_type & ProtocolEvent.MODIFY_MASK) != 0 )
339          eventMonitor[MODIFY].add(monitor);
340       if ( (event_type & ProtocolEvent.DELETE_MASK) != 0 )
341          eventMonitor[DELETE].add(monitor);
342       if ( (event_type & ProtocolEvent.ACCESS_MASK) != 0 )
343          eventMonitor[ACCESS].add(monitor);
344    }
345 
346    public void removeProtocolMonitor(ProtocolMonitor monitor,
347                                      long event_type) {
348       if ( (event_type & ProtocolEvent.ADD_MASK) != 0 )
349          eventMonitor[ADD].remove(monitor);
350       if ( (event_type & ProtocolEvent.MODIFY_MASK) != 0 )
351          eventMonitor[MODIFY].remove(monitor);
352       if ( (event_type & ProtocolEvent.DELETE_MASK) != 0 )
353          eventMonitor[DELETE].remove(monitor);
354       if ( (event_type & ProtocolEvent.ACCESS_MASK) != 0 )
355          eventMonitor[ACCESS].remove(monitor);
356    }
357 
358    private void notifyMonitors(ProtocolInfo info, int type) {
359       if ( eventMonitor[type].isEmpty() ) return;
360 
361       ProtocolMonitor monitor;
362       ProtocolEvent event;
363       Enumeration enum = eventMonitor[type].elements();
364 
365       switch(type) {
366          case ADD:
367               event = new ProtocolEvent(this,info,ProtocolEvent.ADD_MASK);
368               while( enum.hasMoreElements() ) {
369                  monitor = (ProtocolMonitor)enum.nextElement();
370                  monitor.protocolAddedEvent(event);
371               }
372               break;
373          case MODIFY:
374               event = new ProtocolEvent(this,info,ProtocolEvent.MODIFY_MASK);
375               while( enum.hasMoreElements() ) {
376                  monitor = (ProtocolMonitor)enum.nextElement();
377                  monitor.protocolModifiedEvent(event);
378               }
379               break;
380          case DELETE:
381               event = new ProtocolEvent(this,info,ProtocolEvent.DELETE_MASK);
382               while( enum.hasMoreElements() ) {
383                  monitor = (ProtocolMonitor)enum.nextElement();
384                  monitor.protocolDeletedEvent(event);
385               }
386               break;
387          case ACCESS:
388               event = new ProtocolEvent(this,info,ProtocolEvent.ACCESS_MASK);
389               while( enum.hasMoreElements() ) {
390                  monitor = (ProtocolMonitor)enum.nextElement();
391                  monitor.protocolAccessedEvent(event);
392               }
393               break;
394       }
395    }
396 }
397