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.generator.task.rulebase;
25  
26  import javax.swing.*;
27  import javax.swing.table.*;
28  import javax.swing.event.*;
29  import javax.swing.border.* ;
30  import javax.swing.text.*;
31  import java.awt.*;
32  import java.awt.event.*;
33  import java.util.*;
34  import java.io.*;
35  
36  import zeus.util.*;
37  import zeus.concepts.*;
38  import zeus.generator.util.*;
39  import zeus.rete.Action;
40  import zeus.gui.fields.*;
41  
42  
43  public class RuleUI  extends JPanel
44                       implements  ListSelectionListener,
45                                   FocusListener,
46                                   ActionListener  {
47  
48     private JPanel  contentPane;
49     private JTable  ruleTable;
50     private JScrollPane ruleSP,lhsSP,rhsSP;
51     private JTextArea lhsArea,rhsArea;
52     private RuleModel ruleBuffer;
53     private JComboBox predicateList, actionList, functionList;
54     private JButton predicateBtn, actionBtn, functionBtn;
55     protected FactPanel factPanel;
56     protected boolean lhsFocus, rhsFocus;
57     protected JMenuItem fsave, fexit;
58     protected OntologyDb db = null;
59     protected ReteKB kb = null;
60  
61     private final int WIDTH = 640;
62     private final int HEIGHT = 480;
63     private final int LWIDTH = 300;
64     private final int LHEIGHT = 250;
65     private  JFrame frame;
66  
67     protected String[] precedenceWds = zeus.rete.Action.types;
68     protected String[] booleanWds = {"not","test"};
69     protected Vector   methodValues;
70  
71     protected SimpleAttributeSet boolFmt, preFmt, methFmt, plainFmt;
72  
73  //---------------------------------------------------------------------------
74        public RuleUI(OntologyDb db, Editor editor,
75                      ReteKB kb, Vector methodValues) {
76  
77           this.methodValues = methodValues;
78           this.db = db;
79           this.kb = kb;
80  
81           ruleBuffer = new RuleModel(kb,db);
82           ruleBuffer.addChangeListener(editor);
83  
84           GridBagLayout gridBagLayout = new GridBagLayout();
85           GridBagConstraints gbc = new GridBagConstraints();
86           setLayout(gridBagLayout);
87           setBackground(Color.lightGray);
88           setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
89  
90  	 // Add the control panel
91           ControlPanel controlPane =
92              new ControlPanel(editor,"Rulebase Editor",true,true);
93           gbc.gridwidth = GridBagConstraints.REMAINDER;
94           gbc.anchor = GridBagConstraints.NORTHWEST;
95           gbc.fill = GridBagConstraints.HORIZONTAL;
96           gbc.insets = new Insets(8,8,8,8);
97           gbc.weightx = gbc.weighty = 0;
98           gridBagLayout.setConstraints(controlPane,gbc);
99           add(controlPane);
100 
101          // Add the panel that will contain the task's nodes
102          JPanel dataPanel = new JPanel();
103          gbc.gridwidth = GridBagConstraints.REMAINDER;
104          gbc.anchor = GridBagConstraints.NORTHWEST;
105          gbc.fill = GridBagConstraints.BOTH;
106          gbc.weightx = gbc.weighty = 1;
107          gbc.insets = new Insets(8,8,8,8);
108          gridBagLayout.setConstraints(dataPanel,gbc);
109          add(dataPanel);
110 
111          gridBagLayout = new GridBagLayout();
112          gbc = new GridBagConstraints();
113          dataPanel.setLayout(gridBagLayout);
114          dataPanel.setBackground(Color.lightGray);
115 //         dataPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
116 
117          JToolBar toolbar = new RuleToolBar();
118 	 gbc.gridwidth = GridBagConstraints.REMAINDER;
119          gbc.anchor = GridBagConstraints.NORTHWEST;
120          gbc.fill = GridBagConstraints.NONE;
121          gbc.insets = new Insets(0,8,0,0);
122          gbc.weightx = gbc.weighty = 0;
123          gridBagLayout.setConstraints(toolbar,gbc);
124          dataPanel.add(toolbar);
125 
126      // Create data info area     
127          TableColumnModel tm = new DefaultTableColumnModel();     
128          TableColumn column = new TableColumn(RuleModel.RULE,12);
129          column.setHeaderValue(ruleBuffer.getColumnName(RuleModel.RULE));
130          tm.addColumn(column);
131          column = new TableColumn(RuleModel.PRIORITY,12,     
132             new DefaultTableCellRenderer(),
133             new DefaultCellEditor(new WholeNumberField(zeus.rete.Rule.MIN_SALIENCE,
134                zeus.rete.Rule.MAX_SALIENCE)));
135          column.setHeaderValue(ruleBuffer.getColumnName(RuleModel.PRIORITY));
136          tm.addColumn(column);
137     
138          ruleTable = new JTable(ruleBuffer,tm);
139          ruleTable.getTableHeader().setReorderingAllowed(false);
140          ruleTable.setColumnSelectionAllowed(false);
141 
142          ruleSP = new JScrollPane(ruleTable);
143          ruleSP.setPreferredSize(new Dimension(400,150));
144          ruleTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
145          ruleTable.getSelectionModel().addListSelectionListener(this);
146 
147          gbc.gridwidth = GridBagConstraints.REMAINDER;
148          gbc.anchor = GridBagConstraints.NORTHWEST;
149          gbc.fill = GridBagConstraints.HORIZONTAL;
150          gbc.weightx = gbc.weighty = 0;
151          gbc.insets = new Insets(8,8,0,8);
152          gridBagLayout.setConstraints(ruleSP,gbc);
153          dataPanel.add(ruleSP);
154 
155          JPanel panel = getIfThenPanel();
156 	 gbc.gridwidth = 1;
157          gbc.anchor = GridBagConstraints.NORTHWEST;
158          gbc.fill = GridBagConstraints.BOTH;
159          gbc.weightx = gbc.weighty = 1;
160          gbc.insets = new Insets(8,8,8,0);
161          gridBagLayout.setConstraints(panel,gbc);
162          dataPanel.add(panel);
163 
164          panel = getUtilitiesPanel();
165 	 gbc.gridwidth = GridBagConstraints.REMAINDER;
166          gbc.anchor = GridBagConstraints.NORTHWEST;
167          gbc.fill = GridBagConstraints.VERTICAL;
168          gbc.weightx = gbc.weighty = 0;
169          gbc.insets = new Insets(8,8,8,8);
170          gridBagLayout.setConstraints(panel,gbc);
171          dataPanel.add(panel);
172 
173 	 lhsFocus = false;
174          rhsFocus  = false;
175 //         setTextFormats();
176 //         setPreferredSize(new Dimension(WIDTH,HEIGHT));
177       }
178 
179 //---------------------------------------------------------------------------
180       public void save() {
181 	 kb.setRules(ruleBuffer.getData());
182       }
183 //---------------------------------------------------------------------------
184       void setTextFormats(){
185           boolFmt = new SimpleAttributeSet();
186           StyleConstants.setForeground(boolFmt,Color.red);
187           preFmt = new SimpleAttributeSet();
188           StyleConstants.setForeground(preFmt,Color.blue);
189           methFmt = new SimpleAttributeSet();
190           StyleConstants.setForeground(methFmt,Color.green);
191           plainFmt = new SimpleAttributeSet();
192           StyleConstants.setForeground(plainFmt,Color.black);
193 
194       }
195 //---------------------------------------------------------------------------
196       void createFrame(){
197         frame = new JFrame("Rule Editor");
198         frame.getContentPane().add(this);
199         frame.addWindowListener(
200            new WindowAdapter() {
201               public void windowClosing(WindowEvent evt) { System.exit(0); }
202            }
203         );
204         JMenuBar menuBar = new JMenuBar();
205         JMenu fMenu = new JMenu("File");
206         menuBar.add(fMenu);
207         fsave = new JMenuItem("Save");
208         fsave.addActionListener(this);
209         fMenu.add(fsave);
210         fexit = new JMenuItem("Exit");
211         fexit.addActionListener(this);
212         fMenu.add(fexit);
213         frame.setJMenuBar(menuBar);
214         frame.pack();
215         frame.show();
216      }
217 
218 //---------------------------------------------------------------------------
219       class RuleToolBar extends JToolBar implements ActionListener{
220         protected JButton       newBtn;
221         protected JButton       deleteBtn;
222 
223         public RuleToolBar() {
224           setBackground(java.awt.Color.lightGray);
225           setBorder( new BevelBorder(BevelBorder.LOWERED ) );
226           setFloatable(false);
227 
228           String sep = System.getProperty("file.separator");
229           String path = SystemProps.getProperty("gif.dir") + "generator" + sep;
230 
231           // New Button
232           newBtn = new JButton(new ImageIcon(path + "new1.gif"));
233       	  newBtn.setMargin(new Insets(0,0,0,0));
234           add(newBtn);
235           newBtn.setToolTipText("New rule");
236           newBtn.addActionListener(this);
237 
238           // Delete Button
239           deleteBtn = new JButton(new ImageIcon(path + "delete1.gif"));
240 	  deleteBtn.setMargin(new Insets(0,0,0,0));
241           add(deleteBtn);
242           deleteBtn.setToolTipText("Delete");
243           deleteBtn.addActionListener(this);
244 
245          }
246           public void actionPerformed(ActionEvent e)  {
247             Object src = e.getSource();
248             if ( src == newBtn ) {
249                ruleBuffer.addRule();
250             }
251             else if ( src == deleteBtn ) {
252               int row = ruleTable.getSelectedRow();
253               if (row != -1 && row <= ruleBuffer.getRowCount())
254                  ruleBuffer.deleteRule(row);
255               ruleTable.clearSelection();
256               lhsArea.setText("");
257               rhsArea.setText("");
258             }
259           }
260 
261       }
262 //---------------------------------------------------------------------------
263       JPanel getUtilitiesPanel() {
264          JPanel panel = new JPanel();
265          GridBagLayout gridBagLayout = new GridBagLayout();
266          GridBagConstraints gbc = new GridBagConstraints();
267          panel.setLayout(gridBagLayout);
268          panel.setBackground(Color.lightGray);
269 //         panel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
270 
271          functionBtn = new JButton("Insert Function");
272          functionBtn.addActionListener(this);
273          functionBtn.setToolTipText("Click to insert selected function");
274 	 gbc.gridwidth = 1;
275          gbc.anchor = GridBagConstraints.WEST;
276          gbc.fill = GridBagConstraints.HORIZONTAL;
277          gbc.insets = new Insets(8,8,0,0);
278          gridBagLayout.setConstraints(functionBtn,gbc);
279          panel.add(functionBtn);
280 
281          functionList = new JComboBox(methodValues) {
282             public void contentsChanged(ListDataEvent e) {
283                selectedItemReminder = null;
284                super.contentsChanged(e);
285             }
286          };
287          functionList.addActionListener(this);
288          functionList.setForeground(Color.green);
289 	 gbc.gridwidth = GridBagConstraints.REMAINDER;
290          gbc.anchor = GridBagConstraints.WEST;
291          gbc.fill = GridBagConstraints.HORIZONTAL;
292          gbc.insets = new Insets(8,8,0,0);
293          gridBagLayout.setConstraints(functionList,gbc);
294          panel.add(functionList);
295 
296          predicateBtn = new JButton("Insert Predicate");
297          predicateBtn.addActionListener(this);
298          predicateBtn.setToolTipText("Click to insert selected predicate");
299 	 gbc.gridwidth = 1;
300          gbc.anchor = GridBagConstraints.WEST;
301          gbc.fill = GridBagConstraints.HORIZONTAL;
302          gbc.insets = new Insets(8,8,0,0);
303          gridBagLayout.setConstraints(predicateBtn,gbc);
304          panel.add(predicateBtn);
305 
306          predicateList = new JComboBox(booleanWds) {
307             public void contentsChanged(ListDataEvent e) {
308                selectedItemReminder = null;
309                super.contentsChanged(e);
310             }
311          };
312          predicateList.addActionListener(this);
313          functionList.setForeground(Color.red);
314 	 gbc.gridwidth = GridBagConstraints.REMAINDER;
315          gbc.anchor = GridBagConstraints.WEST;
316          gbc.fill = GridBagConstraints.HORIZONTAL;
317          gbc.insets = new Insets(8,8,0,0);
318          gridBagLayout.setConstraints(predicateList,gbc);
319          panel.add(predicateList);
320 
321          actionBtn = new JButton("Insert Action");
322          actionBtn.addActionListener(this);
323          actionBtn.setToolTipText("Click to insert selected action");
324 	 gbc.gridwidth = 1;
325          gbc.anchor = GridBagConstraints.WEST;
326          gbc.fill = GridBagConstraints.HORIZONTAL;
327          gbc.insets = new Insets(8,8,0,0);
328          gridBagLayout.setConstraints(actionBtn,gbc);
329          panel.add(actionBtn);
330 
331          actionList = new JComboBox(precedenceWds) {
332             public void contentsChanged(ListDataEvent e) {
333                selectedItemReminder = null;
334                super.contentsChanged(e);
335             }
336          };
337          actionList.addActionListener(this);
338          functionList.setForeground(Color.blue);
339 	 gbc.gridwidth = GridBagConstraints.REMAINDER;
340          gbc.anchor = GridBagConstraints.WEST;
341          gbc.fill = GridBagConstraints.HORIZONTAL;
342          gbc.insets = new Insets(8,8,0,0);
343          gridBagLayout.setConstraints(actionList,gbc);
344          panel.add(actionList);
345 
346 	 factPanel= new FactPanel(this,db);
347 //         factPanel.setPreferredSize(new Dimension(LWIDTH,LHEIGHT+300));
348          factPanel.setBorder(makeBorder("Ontology"));
349 
350 	 gbc.gridwidth = GridBagConstraints.REMAINDER;
351          gbc.anchor = GridBagConstraints.NORTHWEST;
352          gbc.fill = GridBagConstraints.BOTH;
353          gbc.weightx = gbc.weighty = 1;
354          gbc.insets = new Insets(8,0,0,0);
355          gridBagLayout.setConstraints(factPanel,gbc);
356          panel.add(factPanel);
357 
358          return panel;
359       }
360 //---------------------------------------------------------------------------
361       JTextArea getLastTextAreaWithFocus() {
362           if (lhsFocus)
363             return lhsArea;
364           else if (rhsFocus)
365             return rhsArea;
366           else
367             return null;
368       }
369 //---------------------------------------------------------------------------
370       void setFocus(JTextArea textarea){
371 
372            if (textarea == lhsArea) {
373              lhsFocus = true;
374              rhsFocus = false;
375            }
376            else if (textarea == rhsArea) {
377              rhsFocus = true;
378              lhsFocus = false;
379            }
380       }
381 //---------------------------------------------------------------------------
382       void appendTextTo(JTextArea textarea, String text, boolean keyword){
383            int pos = textarea.getCaretPosition();
384            Document doc = null;
385 
386            if (textarea == lhsArea) {
387               doc = lhsArea.getDocument();
388               insert(doc,text,pos);
389            }
390            else if (textarea == rhsArea) {
391              doc = rhsArea.getDocument();
392              insert(doc,text,pos);
393            }
394 
395            if(keyword && !methodValues.contains(text))
396              textarea.setCaretPosition(textarea.getCaretPosition()-1);
397            else {
398              textarea.setCaretPosition(textarea.getDocument().getLength());
399              try {
400                doc.insertString(textarea.getCaretPosition(),"\n",null);
401              }
402              catch (BadLocationException e) {
403 //               e.printStackTrace();
404              }
405            }
406       }
407 //---------------------------------------------------------------------------
408       void insert(Document doc, String text, int pos) {
409 
410           try {
411            if (Misc.member(text,booleanWds)) {
412               doc.insertString(pos,"(" + text + " )",null);
413            }
414            else if (Misc.member(text,precedenceWds)) {
415               if ( text.equals(Action.types[Action.MESSAGE]) ) {
416                  text += " ";
417                  for(int i = 0; i < Performative.ATTRIBUTE_TYPES.length; i++ )
418                     text += "(" + Performative.ATTRIBUTE_TYPES[i] + " " +
419 		             Fact.V_STR + db.GenSym().plainId("var") + ")";
420                  doc.insertString(pos,"(" + text + ")",null);
421               }
422               else if ( text.equals(Action.types[Action.ACHIEVE]) ||
423                         text.equals(Action.types[Action.BUY]) ||
424                         text.equals(Action.types[Action.SELL]) ) {
425                  text += " ";
426                  for(int i = 0; i < OntologyDb.GOAL_ATTRIBUTES.length; i++ )
427                     text += "(" + OntologyDb.GOAL_ATTRIBUTES[i] + " " +
428 		             Fact.V_STR + db.GenSym().plainId("var") + ")";
429                  doc.insertString(pos,"(" + text + ")",null);
430               }
431               else if ( text.equals(Action.types[Action.IF]) )
432                   doc.insertString(pos,"(" + text + "  \n then\n\n else\n\n)",null);
433               else if ( text.equals(Action.types[Action.WHILE]) )
434                   doc.insertString(pos,"(" + text + "  \n do\n\n)",null);
435               else
436                  doc.insertString(pos,"(" + text + " )",null);
437            }
438            else if (methodValues.contains(text))
439               doc.insertString(pos,text,null);
440            else {
441               doc.insertString(pos,text,null);
442            }
443           }
444           catch (BadLocationException e) {
445           }
446       }
447 
448 //---------------------------------------------------------------------------
449       void appendTextTo(String text){
450          JTextArea textarea = getLastTextAreaWithFocus();
451          if (textarea != null) {
452              appendTextTo(textarea,text,false);
453          }
454       }
455       public void actionPerformed(ActionEvent e){
456          Object source = e.getSource();
457          String value = null;
458          JTextArea textarea;
459 
460          if (source == fsave) {
461             writeRulesToFile();
462          }
463          else if (source == fexit) {
464             System.exit(0);
465          }
466          else if ( source == predicateList || source == predicateBtn ||
467 	           source == functionList  || source == functionBtn  ||
468 		   source == actionList    || source == actionBtn ) {
469             textarea = getLastTextAreaWithFocus();
470             if (textarea != null) {
471                if (source == predicateList || source == predicateBtn )
472                   value = (String)predicateList.getSelectedItem();
473                else if (source == actionList || source == actionBtn )
474                   value = (String)actionList.getSelectedItem();
475                else if (source == functionList || source == functionBtn )
476                   value = (String)functionList.getSelectedItem();
477                if ( value != null) {
478                  if (Misc.member(value,precedenceWds) && textarea != rhsArea)
479                     return;
480                  appendTextTo(textarea,value,true);
481               }
482             }
483          }
484       }
485 //---------------------------------------------------------------------------
486       public void focusGained(FocusEvent e) {
487            JTextArea textarea = (JTextArea) e.getSource();
488            setFocus(textarea);
489       }
490 //---------------------------------------------------------------------------
491       public void focusLost(FocusEvent e) {
492       }
493 //---------------------------------------------------------------------------
494       JPanel getIfThenPanel(){
495          JPanel panel = new JPanel(new GridLayout(2,1,5,5));
496          panel.setBackground(Color.lightGray);
497 
498          lhsArea = new JTextArea(new PlainDocument(),"",6,80);
499          lhsSP = new JScrollPane(lhsArea);
500          lhsSP.setBorder(makeBorder("Conditions"));
501          lhsArea.addFocusListener(this);
502          lhsSP.setPreferredSize(new Dimension(500,100));
503          panel.add(lhsSP);
504 
505          rhsArea = new JTextArea(new PlainDocument(),"",6,80);
506          rhsSP = new JScrollPane(rhsArea);
507          rhsSP.setBorder(makeBorder("Actions"));
508          rhsSP.setPreferredSize(new Dimension(500,100));
509          rhsArea.addFocusListener(this);
510          panel.add(rhsSP);
511 
512          lhsArea.setLineWrap(true);
513          lhsArea.setWrapStyleWord(true);
514          rhsArea.setLineWrap(true);
515          rhsArea.setWrapStyleWord(true);
516 
517 	 return panel;
518       }
519 
520 //---------------------------------------------------------------------------
521       private TitledBorder makeBorder(String title){
522           TitledBorder border = (BorderFactory.createTitledBorder(title));
523           border.setTitlePosition(TitledBorder.TOP);
524 	  border.setTitleJustification(TitledBorder.RIGHT);
525 	  border.setTitleFont(new Font("Helvetica", Font.BOLD, 12));
526 	  border.setTitleColor(Color.black);
527           return border;
528      }
529 
530 //---------------------------------------------------------------------------
531      void writeRulesToFile(){
532          Rule rule;
533          String fname;
534          File f1 = null;
535          String fsep = System.getProperty("file.separator");
536          String fdir = SystemProps.getProperty("zeus.dir") + "rete" + fsep + "clp" + fsep;
537          String image = SystemProps.getProperty("gir.dir") + "generator" + "kb.gif";
538 
539          JFileChooser chooser = new JFileChooser(new File(fdir));
540          //chooser.addChoosableFileType("Rule bases (*.kb)", "kb", new ImageIcon(image));
541          int val = chooser.showSaveDialog(frame);
542          if (val == JFileChooser.APPROVE_OPTION )
543           f1 = chooser.getSelectedFile();
544 
545          if (f1 == null) {
546             JOptionPane.showMessageDialog(null,"File hasn't been specified","Error",JOptionPane.ERROR_MESSAGE);
547             return;
548          }
549          try {
550 
551 	   PrintWriter out = new PrintWriter(new FileWriter(f1));
552            Vector rules = ruleBuffer.getRules();
553            for(int i=0;i < rules.size(); i++) {
554               rule = (Rule) rules.elementAt(i);
555               printRule(rule,out);
556            }
557            out.flush();
558 	   out.close();
559          }
560          catch(IOException e) {
561 	   e.printStackTrace();
562          }
563      }
564 //---------------------------------------------------------------------------
565      void printRule(Rule rule, PrintWriter out) {
566          out.println("   (" + rule.name );
567          out.println();
568          out.println(rule.getCondition().trim());
569          out.println("=>");
570          out.println(rule.getConclusion().trim());
571          out.println();
572          out.println("   )");
573          out.println(); out.println();
574      }
575 //---------------------------------------------------------------------------
576       public void valueChanged(ListSelectionEvent e) {
577           int row;
578           if (e.getSource() == ruleTable.getSelectionModel() ) {
579              row = ruleTable.getSelectedRow();
580              if (row >= 0  && row < ruleBuffer.getRowCount()) {
581               lhsArea.setDocument(ruleBuffer.getRule(row).getLHS());
582               rhsArea.setDocument(ruleBuffer.getRule(row).getRHS());
583              }
584           }
585       }
586 //---------------------------------------------------------------------------
587 }