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  * BasicTool.java - implements the core Visualiser functionality       *
26  *                - i.e. communication                                 *
27  **********************************************************************/
28  
29  package zeus.visualiser.basic;
30  
31  import java.util.*;
32  import java.awt.*;
33  import java.awt.event.*;
34  import javax.swing.*;
35  
36  import zeus.util.*;
37  import zeus.concepts.*;
38  import zeus.gui.*;
39  import zeus.gui.help.*;
40  import zeus.visualiser.*;
41  import zeus.actors.*;
42  import gnu.regexp.*;
43  
44  public abstract class BasicTool extends JFrame {
45    protected AgentContext    context = null;
46    protected VisualiserModel model   = null;
47    protected MsgFilter       filter  = null;
48  
49    private EditableMultipleSelectionDialog connect_dialog = null;
50    private MsgFilterEditor                 editor = null;
51  
52    public BasicTool(AgentContext context, VisualiserModel model)  {
53       this.context = context;
54       this.model = model;
55  
56       this.addWindowListener(
57          new WindowAdapter() {
58             public void windowClosing(WindowEvent evt) { Exit(); }
59          }
60       );
61    }
62  
63    public AgentContext    getAgentContext() { return context; }
64    public VisualiserModel getModel()        { return model; }
65  
66    public void Exit()  {
67       this.setVisible(false);
68       removeSubscriptions();
69       this.dispose();
70    }
71  
72    public void Connect(boolean mode) {
73      if ( !hubOK() ) return;
74  
75      String[] servers = model.getNameservers();
76      if ( connect_dialog == null ) {
77         connect_dialog = new EditableMultipleSelectionDialog(this,
78            "Select Servers", servers);
79         connect_dialog.setLocationRelativeTo(this);
80      }
81      else {
82        Object[] chosen = connect_dialog.getPriorSelection();
83        connect_dialog.setListData(servers);
84        connect_dialog.setSelection(chosen);
85      }
86  
87      Object[] data = connect_dialog.getSelection();
88      model.addNameservers(Misc.stringArray(connect_dialog.getListData()));
89      if ( data != null && data.length > 0 )
90         subscribe(mode,model.keys[VisualiserModel.ADDRESS_KEY],
91                   Misc.stringArray(data),"log_address");
92    }
93  
94    public void quickConnect() {
95      String[] servers = model.getNameservers();
96      if (servers != null && servers.length > 0 ) {
97         subscribe(true,model.keys[VisualiserModel.ADDRESS_KEY],servers,
98                   "log_address");
99      }
100   }
101 
102   protected void subscribe(boolean mode, String key, String agent,
103                            String method) {
104   /***
105      Note: for subscribe messages we do not want to ask the
106      agent twice to send the same data. Hence if 'isAlreadySubscribed()'
107      then do not send message. In the case of a query msg this check is
108      not made since the user might want to reissue a query.
109   */
110      Performative msg;
111      String ruleId = null;
112      String content = model.getSubscriptionContent(key);
113      if ( mode ) {
114         if ( (ruleId = model.getMessageRule(key,agent,this,method)) == null ) {
115            ruleId = context.newId("Rule");
116            String[] pattern = { "type", "inform", "in-reply-to", key, "sender", agent };
117            context.MsgHandler().addRule(
118               new MessageRuleImpl(ruleId,pattern,this,method)
119            );
120            model.addMessageRule(key,agent,this,method,ruleId);
121         }
122         if ( !model.isAlreadySubscribed(key,agent,ruleId) ) {
123            msg = new Performative("subscribe");
124            msg.setReceiver(agent);
125            msg.setReplyWith(key);
126            msg.setContent(content);
127            context.MailBox().sendMsg(msg);
128            model.subscribe(key,agent,ruleId);
129         }
130      }
131      else {
132         ruleId = model.removeMessageRule(key,agent,this,method);
133         context.MsgHandler().removeRule(ruleId);
134         switch( model.unsubscribe(key,agent,ruleId) ) {
135            case VisualiserModel.CANCEL_SUBSCRIPTION:
136                 msg = new Performative("cancel");
137                 msg.setReceiver(agent);
138                 msg.setReplyWith(key);
139                 msg.setContent(content);
140                 context.MailBox().sendMsg(msg);
141                 break;
142            default:
143                 break;
144         }
145      }
146   }
147 
148   protected void subscribe(boolean mode, String key, String[] agent,
149                            String method) {
150      for(int i = 0; i < agent.length; i++ )
151         subscribe(mode,key,agent[i],method);
152   }
153 
154   protected void query(String content, String agent, String method) {
155      String ruleId = context.newId("Rule");
156      String[] pattern = { "in-reply-to", ruleId, "sender", agent };
157      context.MsgHandler().addRule(
158         new MessageRuleImpl(ruleId,pattern,MessageActionImpl.EXECUTE_ONCE,this,method)
159      );
160      Performative msg = new Performative("query-ref");
161      msg.setReceiver(agent);
162      msg.setReplyWith(ruleId);
163      msg.setContent(content);
164      context.MailBox().sendMsg(msg);
165   }
166 
167   protected void query(String content, String[] agent, String method) {
168      for(int i = 0; i < agent.length; i++ )
169         query(content,agent[i],method);
170   }
171 
172   protected void request(String content, String agent, String method) {
173      String ruleId = context.newId("Rule");
174      String[] pattern = { "in-reply-to", ruleId, "sender", agent };
175      context.MsgHandler().addRule(
176         new MessageRuleImpl(ruleId,pattern,MessageActionImpl.EXECUTE_ONCE,this,method)
177      );
178      Performative msg = new Performative("request");
179      msg.setReceiver(agent);
180      msg.setReplyWith(ruleId);
181      msg.setContent(content);
182      context.MailBox().sendMsg(msg);
183   }
184 
185   protected void request(String content, String[] agent, String method) {
186      for(int i = 0; i < agent.length; i++ )
187         request(content,agent[i],method);
188   }
189 
190   protected boolean hubOK() {
191      if ( context == null || context.MailBox() == null ||
192           context.MsgHandler() == null || model == null ) {
193         JOptionPane.showMessageDialog(this, "Error",
194            "Not connected to a visualiser hub", JOptionPane.ERROR_MESSAGE);
195         return false;
196      }
197      return true;
198   }
199 
200   public void log_address(Performative msg) {
201     Vector List = ZeusParser.addressList(msg.getContent());
202     context.MailBox().add(List);
203     for(int i = 0; i < List.size(); i++ ) {
204        Address a = (Address)List.elementAt(i);
205        String name = a.getName();
206        String type = a.getType();
207        model.addAgent(name, type);
208        registerAgent(name,type);
209     }
210   }
211 
212   public void Filter() {
213     if ( !hubOK() ) return;
214 
215     String[] agents = model.getAgents();
216     if ( editor == null ) {
217        editor = new MsgFilterEditor(this,"Edit Message Filter");
218        editor.setLocationRelativeTo(this);
219     }
220 
221     editor.setListData(agents);
222     editor.setFilter(filter);
223     filter = editor.getFilter();
224 
225     if ( filter != null ) {
226        if (filter.from != null)
227           model.addAgents(filter.from);
228        if (filter.to != null)
229           model.addAgents(filter.to);
230        if ( filter.about != null ) {
231           try {
232              filter.regexp = new RE(filter.about,RE.REG_DOT_NEWLINE);// was REG_DOT_NEWLINE
233 
234           }
235           catch(REException e) { // was REException
236              Core.USER_ERROR("Illegal 'about' filter: " + filter.about);
237              filter.about = null;
238              filter.regexp = null;
239           }
240        }
241     }
242   }
243 
244   public void About()  {
245     Point pt = getLocation();
246     HelpWindow helpWin = new HelpWindow(this, pt, "visualiser", "About");
247     helpWin.setSize(new Dimension(440, 440));
248     helpWin.setTitle("About ZEUS ...");
249     helpWin.validate();
250   }
251 
252   protected boolean filterMsg(Performative msg) {
253      if ( filter == null ) return true;
254      String from = msg.getSender();
255      String to = msg.getReceiver();
256      if ( filter.from != null && !Misc.member(from,filter.from) )
257         return false;
258      if ( filter.to != null && !Misc.member(to,filter.to) )
259         return false;
260      if ( filter.regexp != null && !filter.regexp.isMatch(msg.getContent()) ) // was isMatch
261         return false;
262      return true;
263   }
264 
265   protected void removeSubscriptions() {
266      MessageInfo info;
267      String ruleId;
268      Performative msg;
269      Hashtable input = model.removeAllMessageRulesTo(this);
270      Enumeration enum = input.keys();
271      while( enum.hasMoreElements() ) {
272         info = (MessageInfo)enum.nextElement();
273         ruleId = (String)input.get(info);
274         context.MsgHandler().removeRule(ruleId);
275         switch( model.unsubscribe(info.key,info.agent,ruleId) ) {
276            case VisualiserModel.CANCEL_SUBSCRIPTION:
277                 msg = new Performative("cancel");
278                 msg.setReceiver(info.agent);
279                 msg.setReplyWith(info.key);
280                 msg.setContent(model.getSubscriptionContent(info.key));
281                 context.MailBox().sendMsg(msg);
282                 break;
283            default:
284                 break;
285         }
286      }
287   }
288 
289   protected abstract void registerAgent(String agent, String type);
290 }