ResourceParametersEditor.java
001 /*
002  *  Copyright (c) 1995-2010, The University of Sheffield. See the file
003  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
004  *
005  *  This file is part of GATE (see http://gate.ac.uk/), and is free
006  *  software, licenced under the GNU Library General Public License,
007  *  Version 2, June 1991 (in the distribution as file licence.html,
008  *  and also available at http://gate.ac.uk/gate/licence.html).
009  *
010  *  Valentin Tablan 03/10/2001
011  *
012  *  $Id: ResourceParametersEditor.java 12494 2010-04-15 15:30:11Z thomas_heitz $
013  *
014  */
015 
016 package gate.gui;
017 
018 import java.awt.*;
019 import java.awt.event.*;
020 import java.io.IOException;
021 import java.lang.reflect.Method;
022 import java.util.*;
023 import java.util.List;
024 
025 import javax.swing.*;
026 import javax.swing.event.ChangeEvent;
027 import javax.swing.table.*;
028 
029 import gate.*;
030 import gate.creole.*;
031 import gate.event.CreoleEvent;
032 import gate.event.CreoleListener;
033 import gate.swing.XJTable;
034 import gate.swing.XJFileChooser;
035 import gate.util.*;
036 
037 /**
038  * Allows the editing of a set of parameters for a resource. It needs a
039  * pointer to the resource and a list of the parameter names for the
040  * parameters that should be displayed. The list of the parameters is
041  * actually a list of lists of strings representing parameter
042  * disjunctions.
043  */
044 public class ResourceParametersEditor extends XJTable implements CreoleListener {
045 
046   public ResourceParametersEditor() {
047     initLocalData();
048     initGuiComponents();
049     initListeners();
050     setSortable(true);
051     setSortedColumn(0);
052     setComparator(0new ParameterDisjunctionComparator());
053     setTabSkipUneditableCell(true);
054     setEditCellAsSoonAsFocus(true);
055   }
056 
057   /**
058    * Initialises this GUI component.
059    
060    @param resource the resource for which the parameters need to be
061    *          set.
062    @param parameters a list of lists of {@link Parameter} representing
063    *          parameter disjunctions.
064    */
065   public void init(Resource resource, List parameters) {
066     cleanup();
067     this.resource = resource;
068     if(parameters != null) {
069       parameterDisjunctions = new ArrayList<ParameterDisjunction>(parameters.size());
070       for(int i = 0; i < parameters.size(); i++) {
071         parameterDisjunctions.add(new ParameterDisjunction(resource,
072                 (List)parameters.get(i)));
073       }
074     }
075     else {
076       parameterDisjunctions = null;
077     }
078     tableModel.fireTableDataChanged();
079     fileChooser = MainFrame.getFileChooser();
080     // must be saved now as it will be reset when the file chooser is hidden
081     fileChooserResource = (resource != null?
082       resource.getClass().getName() : fileChooser.getResource();
083   }
084 
085   protected void initLocalData() {
086     resource = null;
087     parameterDisjunctions = null;
088   }// protected void initLocalData()
089 
090   protected void initGuiComponents() {
091     setModel(tableModel = new ParametersTableModel());
092     getColumnModel().getColumn(0).setCellRenderer(
093             new ParameterDisjunctionRenderer());
094     getColumnModel().getColumn(2).setCellRenderer(new DefaultTableCellRenderer());
095     getColumnModel().getColumn(2).setCellRenderer(new BooleanRenderer());
096     getColumnModel().getColumn(3).setCellRenderer(new ParameterValueRenderer());
097     getColumnModel().getColumn(0).setCellEditor(
098             new ParameterDisjunctionEditor());
099     getColumnModel().getColumn(3).setCellEditor(new ParameterValueEditor());
100     setAutoResizeMode(AUTO_RESIZE_LAST_COLUMN);
101 
102     setSurrendersFocusOnKeystroke(true);
103   }// protected void initGuiComponents()
104 
105   protected void initListeners() {
106     Gate.getCreoleRegister().addCreoleListener(this);
107   }
108 
109   /**
110    * Cleans the internal data and prepares this object to be collected
111    */
112   public void cleanup() {
113     Gate.getCreoleRegister().removeCreoleListener(this);
114     if(parameterDisjunctions != null && parameterDisjunctions.size() 0) {
115       for(int i = 0; i < parameterDisjunctions.size(); i++) {
116         parameterDisjunctions.get(i).cleanup();
117       }
118     }
119     resource = null;
120   }
121 
122   /**
123    * Sets the parameters for the resource to their new values as
124    * resulted from the user's edits.
125    */
126   public void setParameters() throws ResourceInstantiationException {
127     if(resource == null || parameterDisjunctions == nullreturn;
128     // stop current edits
129     if(getEditingColumn() != -&& getEditingRow() != -1) {
130       editingStopped(new ChangeEvent(getCellEditor(getEditingRow(),
131               getEditingColumn())));
132     }
133     // set the parameters
134     for(int i = 0; i < parameterDisjunctions.size(); i++) {
135       ParameterDisjunction pDisj = parameterDisjunctions
136               .get(i);
137       resource.setParameterValue(pDisj.getName(), pDisj.getValue());
138     }
139   }
140 
141   /**
142    * Does this GUI component allow editing?
143    */
144 
145   public Resource getResource() {
146     return resource;
147   }
148 
149   /**
150    * Gets the current values for the parameters.
151    
152    @return {@link FeatureMap} containing the curent values for the
153    *         currently selected parameters in each disjunction.
154    */
155   public FeatureMap getParameterValues() {
156     // stop current edits
157     if(getEditingColumn() != -&& getEditingRow() != -1) {
158       editingStopped(new ChangeEvent(getCellEditor(getEditingRow(),
159               getEditingColumn())));
160     }
161     // get the parameters
162     FeatureMap values = Factory.newFeatureMap();
163     if(parameterDisjunctions != null) {
164       for(int i = 0; i < parameterDisjunctions.size(); i++) {
165         ParameterDisjunction pDisj = parameterDisjunctions.get(i);
166         values.put(pDisj.getName(), pDisj.getValue());
167       }
168     }
169     return values;
170   }
171 
172   public void resourceLoaded(CreoleEvent e) {
173     repaint();
174   }
175 
176   public void resourceUnloaded(CreoleEvent e) {
177     repaint();
178   }
179 
180   public void resourceRenamed(Resource resource, String oldName, String newName) {
181     repaint();
182   }
183 
184   public void datastoreOpened(CreoleEvent e) {
185   }
186 
187   public void datastoreCreated(CreoleEvent e) {
188   }
189 
190   public void datastoreClosed(CreoleEvent e) {
191   }
192 
193   public void setEditable(boolean editable) {
194     this.editable = editable;
195   }
196 
197   public boolean isEditable() {
198     return editable;
199   }
200 
201   /**
202    * Called by other GUI classes that use this as a subcomponent that
203    * doesn't need to update with the creole register changes.
204    */
205   void removeCreoleListenerLink() {
206     // this component is only used as a viewer now; it doesn't need to
207     // update
208     // so we don't need to listen to creole events
209     Gate.getCreoleRegister().removeCreoleListener(this);
210     if(parameterDisjunctions != null && parameterDisjunctions.size() 0) {
211       for(int i = 0; i < parameterDisjunctions.size(); i++) {
212         parameterDisjunctions.get(i).removeCreoleListenerLink();
213       }
214     }
215 
216   }
217 
218   ParametersTableModel tableModel;
219 
220   Resource resource;
221 
222   /**
223    * A pointer to the filechooser from MainFrame.
224    */
225   static XJFileChooser fileChooser;
226 
227   String fileChooserResource;
228 
229   /**
230    * A list of {@link ParameterDisjunction}
231    */
232   protected List<ParameterDisjunction> parameterDisjunctions;
233 
234   protected boolean editable = true;
235 
236   // inner classes
237   protected class ParametersTableModel extends AbstractTableModel {
238 
239     public int getColumnCount() {
240       return 4;
241     }
242 
243     public Class getColumnClass(int columnIndex) {
244       switch(columnIndex) {
245         case 0:
246           return ParameterDisjunction.class;
247         case 1:
248           return String.class;
249         case 2:
250           return Boolean.class;
251         case 3:
252           return Object.class;
253         default:
254           return Object.class;
255       }
256     }// public Class getColumnClass(int columnIndex)
257 
258     public String getColumnName(int columnIndex) {
259       switch(columnIndex) {
260         case 0:
261           return "Name";
262         case 1:
263           return "Type";
264         case 2:
265           return "Required";
266         case 3:
267           return "Value";
268         default:
269           return "?";
270       }
271     }// public String getColumnName(int columnIndex)
272 
273     public boolean isCellEditable(int rowIndex, int columnIndex) {
274       switch(columnIndex) {
275         case 0:
276           return parameterDisjunctions.get(rowIndex).size() 1;
277         case 1:
278           return false;
279         case 2:
280           return false;
281         case 3:
282           return editable;
283         default:
284           return false;
285       }
286     }// public boolean isCellEditable
287 
288     public int getRowCount() {
289       return (parameterDisjunctions == null: parameterDisjunctions.size();
290     }
291 
292     public Object getValueAt(int rowIndex, int columnIndex) {
293       ParameterDisjunction pDisj = parameterDisjunctions.get(rowIndex);
294       switch(columnIndex) {
295         case 0:
296           return pDisj;
297         case 1:
298           String paramType = pDisj.getType();
299           return paramType.substring(paramType.lastIndexOf('.'1)
300         case 2:
301           return pDisj.isRequired();
302         case 3:
303           return pDisj.getValue();
304         default:
305           return "?";
306       }
307     }// public Object getValueAt
308 
309     public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
310       ParameterDisjunction pDisj = parameterDisjunctions.get(rowIndex);
311       switch(columnIndex) {
312         case 0{
313           if(aValue instanceof ParameterDisjunction){
314             //do nothing
315           else if (aValue instanceof Integer){
316             pDisj.setSelectedIndex((IntegeraValue);
317           }
318           break;
319         }
320         case 1{
321           break;
322         }
323         case 2{
324           break;
325         }
326         case 3{
327           pDisj.setValue(aValue);
328           break;
329         }
330         default{
331         }
332       }
333       tableModel.fireTableCellUpdated(rowIndex, columnIndex);
334     }// public void setValueAt
335   }// /class FeaturesTableModel extends DefaultTableModel
336 
337   class ParameterDisjunctionRenderer extends DefaultTableCellRenderer {
338     public ParameterDisjunctionRenderer() {
339       combo = new JComboBox();
340       class CustomRenderer extends JLabel implements ListCellRenderer {
341         public Component getListCellRendererComponent(JList list, Object value,
342                 int index, boolean isSelected, boolean cellHasFocus) {
343 
344           setText(text);
345           setIcon(MainFrame.getIcon(iconName));
346           return this;
347         }
348       }
349       combo.setRenderer(new CustomRenderer());
350     }
351 
352     public Component getTableCellRendererComponent(JTable table, Object value,
353             boolean isSelected, boolean hasFocus, int row, int column) {
354       ParameterDisjunction pDisj = (ParameterDisjunction)value;
355       text = pDisj.getName();
356       String type = pDisj.getType();
357       iconName = "param";
358       if(Gate.isGateType(type)) {
359         ResourceData rData = Gate.getCreoleRegister().get(type);
360         if(rData != nulliconName = rData.getIcon();
361       }
362       if(pDisj.size() 1) {
363         combo.setModel(new DefaultComboBoxModel(new Object[] {text}));
364         return combo;
365       }
366       // prepare the renderer
367       super.getTableCellRendererComponent(table, text, isSelected,
368         hasFocus, row, column);
369       setIcon(MainFrame.getIcon(iconName));
370       return this;
371     }// public Component getTableCellRendererComponent
372 
373     // combobox used for OR parameters
374     JComboBox combo;
375 
376     String iconName;
377 
378     String text;
379   }// class ParameterDisjunctionRenderer
380 
381   /**
382    * A renderer that displays a File Open button next to a text field.
383    * Used for setting URLs from files.
384    */
385   class ParameterValueRenderer extends DefaultTableCellRenderer {
386     public ParameterValueRenderer() {
387       fileButton = new JButton(MainFrame.getIcon("open-file"));
388       fileButton.setToolTipText("Browse the file system");
389       listButton = new JButton(MainFrame.getIcon("edit-list"));
390       listButton.setToolTipText("Edit the list");
391       fmButton = new JButton(MainFrame.getIcon("edit-list"));
392       fmButton.setToolTipText("Edit the feature map");
393       textField = new JTextField(25){
394         @Override
395         public Dimension getMinimumSize() {
396           //we don't want to be squashed!
397           return getPreferredSize();
398         }
399         
400       };
401       textButtonBox = new JPanel();
402       textButtonBox.setLayout(new BoxLayout(textButtonBox, BoxLayout.X_AXIS));
403       textButtonBox.setOpaque(false);
404       combo = new JComboBox();
405       combo.setRenderer(new ResourceRenderer());
406     }// CustomObjectRenderer()
407 
408     public Component getTableCellRendererComponent(JTable table, Object value,
409             boolean isSelected, boolean hasFocus, int row, int column) {
410 
411       ParameterDisjunction pDisj = (ParameterDisjunction)table
412         .getValueAt(row, convertColumnIndexToView(0));
413       String type = pDisj.getType();
414       // set the tooltip
415       combo.setToolTipText(pDisj.getComment());
416       textField.setToolTipText(pDisj.getComment());
417       textButtonBox.setToolTipText(pDisj.getComment());
418 
419       if(Gate.isGateType(type)) {
420         // Gate type
421         if(ResourceParametersEditor.this.isEditable()) {
422           combo.setModel(new DefaultComboBoxModel(new Object[] {value == null
423                   "<none>"
424                   : value}));
425           return combo;
426         }
427         else {
428           // not editable; we'll just use the text field
429           // prepare the renderer
430           String text = value == null "<none>" : value.toString();
431           // super.getTableCellRendererComponent(table, text,
432           // isSelected,
433           // hasFocus, row, column);
434           textField.setText(text);
435           return textField;
436         }
437       }
438       else {
439         Class typeClass = null;
440         try {
441           // load type class through GATE classloader
442           typeClass = Class.forName(type, true, Gate.getClassLoader());
443         }
444         catch(ClassNotFoundException cnfe) {
445           cnfe.printStackTrace();
446         }
447         // non Gate type -> we'll use the text field
448         String text = (value == null)
449                 ""
450                 : value.toString();
451         // prepare the renderer
452         textField.setText(text);
453         // super.getTableCellRendererComponent(table, text, isSelected,
454         // hasFocus, row, column);
455 
456         if(type.equals("java.net.URL")) {
457           if(ResourceParametersEditor.this.isEditable()) {
458             textButtonBox.removeAll();
459             textField.setText(text);
460             // textButtonBox.add(this);
461             textButtonBox.add(textField);
462             // this.setMaximumSize(new Dimension(Integer.MAX_VALUE,
463             // getPreferredSize().height));
464             textButtonBox.add(Box.createHorizontalStrut(5));
465             textButtonBox.add(fileButton);
466             return textButtonBox;
467           }
468           else {
469             // return this;
470             return textField;
471           }
472         }
473         else if(typeClass != null
474                 && Collection.class.isAssignableFrom(typeClass)) {
475           // List value
476           // setText(textForList((List)value));
477           textField.setText(textForList((Collection)value));
478           if(ResourceParametersEditor.this.isEditable()) {
479             textButtonBox.removeAll();
480             // textButtonBox.add(this);
481             textButtonBox.add(textField);
482             // this.setMaximumSize(new Dimension(Integer.MAX_VALUE,
483             // getPreferredSize().height));
484             textButtonBox.add(Box.createHorizontalStrut(5));
485             textButtonBox.add(listButton);
486             return textButtonBox;
487           }
488         }
489         else if(typeClass != null
490                 && FeatureMap.class.isAssignableFrom(typeClass)) {
491           textField.setText(textForFeatureMap((FeatureMap)value));
492           if(ResourceParametersEditor.this.isEditable()) {
493             textButtonBox.removeAll();
494             textButtonBox.add(textField);
495             textButtonBox.add(Box.createHorizontalStrut(5));
496             textButtonBox.add(fmButton);
497             return textButtonBox;
498           }
499         }
500         else if(typeClass != null && typeClass.isEnum()) {
501           if(ResourceParametersEditor.this.isEditable()) {
502             combo.setModel(new DefaultComboBoxModel(new Object[] {value == null
503                     "<none>"
504                     : value}));
505             return combo;
506           }
507           else {
508             return textField;
509           }
510         }
511         else {
512           // return this;
513           return textField;
514         }
515 
516         // not actually reachable, but keeps the compiler happy
517         return textField;
518       }
519     }// public Component getTableCellRendererComponent
520 
521 
522     JButton fileButton;
523 
524     JButton listButton;
525 
526     JButton fmButton;
527 
528     JComboBox combo;
529 
530     JPanel textButtonBox;
531 
532     JTextField textField;
533   }// class ObjectRenderer extends DefaultTableCellRenderer
534 
535   class ParameterDisjunctionComparator implements Comparator {
536     public int compare(Object o1, Object o2) {
537       ParameterDisjunction pDisj1 = (ParameterDisjunction)o1;
538       ParameterDisjunction pDisj2 = (ParameterDisjunction)o2;
539       return pDisj1.getName().compareTo(pDisj2.getName());
540     }
541   }
542 
543   class ParameterDisjunctionEditor extends DefaultCellEditor {
544     public ParameterDisjunctionEditor() {
545       super(new JComboBox());
546       combo = (JComboBox)super.getComponent();
547       class CustomRenderer extends JLabel implements ListCellRenderer {
548         public CustomRenderer() {
549           setOpaque(true);
550         }
551 
552         public Component getListCellRendererComponent(JList list, Object value,
553                 int index, boolean isSelected, boolean cellHasFocus) {
554           if(isSelected) {
555             setBackground(list.getSelectionBackground());
556             setForeground(list.getSelectionForeground());
557           }
558           else {
559             setBackground(list.getBackground());
560             setForeground(list.getForeground());
561           }
562 
563           setFont(list.getFont());
564 
565           setText((String)value);
566 
567           String iconName = "param";
568           Parameter[] params = pDisj.getParameters();
569           for(int i = 0; i < params.length; i++) {
570             Parameter param = params[i];
571             if(param.getName().equals(value)) {
572               String type = param.getTypeName();
573               if(Gate.getCreoleRegister().containsKey(type)) {
574                 ResourceData rData = Gate.getCreoleRegister()
575                         .get(type);
576                 if(rData != nulliconName = rData.getIcon();
577               }
578               break;
579             }// if(params[i].getName().equals(value))
580           }// for(int i = 0; params.length; i++)
581 
582           setIcon(MainFrame.getIcon(iconName));
583           return this;
584         }
585       // class CustomRenderer extends JLabel implements
586         // ListCellRenderer
587       combo.setRenderer(new CustomRenderer());
588       combo.addActionListener(new ActionListener() {
589         public void actionPerformed(ActionEvent e) {
590           pDisj.setSelectedIndex(combo.getSelectedIndex());
591           stopCellEditing();
592         }
593       });
594     }// public ParameterDisjunctionEditor()
595 
596     public Component getTableCellEditorComponent(JTable table, Object value,
597             boolean isSelected, int row, int column) {
598       pDisj = (ParameterDisjunction)value;
599       DefaultComboBoxModel comboModel = new DefaultComboBoxModel(pDisj.getNames());
600       combo.setModel(comboModel);
601       combo.setSelectedIndex(pDisj.getSelectedIndex());
602       return combo;
603     }// public Component getTableCellEditorComponent
604 
605     public Object getCellEditorValue() {
606       pDisj.setSelectedIndex(combo.getSelectedIndex());
607 //      return combo.getSelectedIndex();
608       return pDisj;
609     }
610 
611     public boolean stopCellEditing() {
612       combo.hidePopup();
613       return super.stopCellEditing();
614     }
615 
616     JComboBox combo;
617 
618     ParameterDisjunction pDisj;
619   }// class ParameterDisjunctionEditor extends DefaultCellEditor
620 
621   class ParameterValueEditor extends AbstractCellEditor implements
622                                                        TableCellEditor {
623     ParameterValueEditor() {
624       combo = new JComboBox();
625       combo.setRenderer(new ResourceRenderer());
626       combo.setEditable(false);
627 
628       textField = new JTextField(20);
629 
630       fileButton = new JButton(MainFrame.getIcon("open-file"));
631       fileButton.setToolTipText("Browse the file system");
632       fileButton.addActionListener(new ActionListener() {
633         public void actionPerformed(ActionEvent e) {
634           fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
635           fileChooser.setDialogTitle("Select a file");
636           fileChooser.setResource(fileChooserResource);
637           int res = fileChooser.showOpenDialog(ResourceParametersEditor.this);
638           if(res == JFileChooser.APPROVE_OPTION) {
639             try {
640               textField.setText(fileChooser.getSelectedFile().toURI().toURL()
641                       .toExternalForm());
642             }
643             catch(IOException ioe) {
644               ioe.printStackTrace();
645             }
646             fireEditingStopped();
647           }
648           else {
649             fireEditingCanceled();
650           }
651         }
652       });
653 
654       listButton = new JButton(MainFrame.getIcon("edit-list"));
655       listButton.setToolTipText("Edit the list");
656       listButton.addActionListener(new ActionListener() {
657         public void actionPerformed(ActionEvent e) {
658           List returnedList = listEditor.showDialog();
659           if(returnedList != null) {
660             listValue = returnedList;
661             fireEditingStopped();
662           }
663           else {
664             fireEditingCanceled();
665           }
666         }
667       });
668 
669       fmButton = new JButton(MainFrame.getIcon("edit-list"));
670       fmButton.setToolTipText("Edit the feature map");
671       fmButton.addActionListener(new ActionListener() {
672         public void actionPerformed(ActionEvent e) {
673           FeatureMap returnedFM = fmEditor.showDialog();
674           if(returnedFM != null) {
675             fmValue = returnedFM;
676             fireEditingStopped();
677           }
678           else {
679             fireEditingCanceled();
680           }
681         }
682       });
683 
684       textButtonBox = new JPanel();
685       textButtonBox.setLayout(new BoxLayout(textButtonBox, BoxLayout.X_AXIS));
686       textButtonBox.setOpaque(false);
687       textFieldBoolean = new JTextField();
688       textFieldBoolean.setEditable(false);
689       textFieldBoolean.addMouseListener(new MouseAdapter() {
690         public void mouseClicked(MouseEvent e) {
691           Boolean value = Boolean.valueOf(textFieldBoolean.getText());
692           value = !value;
693           textFieldBoolean.setText(value.toString());
694         }
695       });
696       textFieldBoolean.addKeyListener(new KeyAdapter() {
697         public void keyTyped(KeyEvent e) {
698           Boolean value = Boolean.valueOf(textFieldBoolean.getText());
699           value = !value;
700           textFieldBoolean.setText(value.toString());
701         }
702       });
703 
704       textButtonBox.addFocusListener(new FocusAdapter() {
705         public void focusGained(FocusEvent e) {
706           if(!comboUsed) {
707             // needed because the focus would otherwise stay
708             // on the textButtonBox panel
709             textField.requestFocusInWindow();
710           }
711         }
712       });
713       // select the opposite element when tab key is pressed
714       textField.addKeyListener(new KeyAdapter() {
715         public void keyPressed(KeyEvent e) {
716           JTextField textField = (JTextFielde.getSource();
717           if((e.getKeyCode() == KeyEvent.VK_TAB)
718           && textField.getParent().getComponentCount() == 3) {
719             textField.getParent().getComponent(2).requestFocusInWindow();
720             e.consume();
721           }
722         }
723       });
724 
725     }// ParameterValueEditor()
726 
727     public Component getTableCellEditorComponent(JTable table, Object value,
728             boolean isSelected, int row, int column) {
729       comboUsed = false;
730       listUsed = false;
731       fmUsed = false;
732       ParameterDisjunction pDisj = (ParameterDisjunction)table
733         .getValueAt(row, convertColumnIndexToView(0));
734       type = pDisj.getType();
735       // set the tooltip
736       combo.setToolTipText(pDisj.getComment());
737       textField.setToolTipText(pDisj.getComment());
738       textFieldBoolean.setToolTipText(pDisj.getComment());
739 
740       if(Gate.isGateType(type)) {
741         // Gate type
742         comboUsed = true;
743         ArrayList<Object> values = new ArrayList<Object>();
744         try {
745           values.addAll(Gate.getCreoleRegister().getAllInstances(type));
746         }
747         catch(GateException ge) {
748           ge.printStackTrace(Err.getPrintWriter());
749         }
750         values.add(0"<none>");
751         combo.setModel(new DefaultComboBoxModel(values.toArray()));
752         combo.setSelectedItem(value == null "<none>" : value);
753         return combo;
754       }
755       else {
756         // non Gate type
757         Class typeClass = null;
758         try {
759           // load type class through GATE classloader
760           typeClass = Class.forName(type, true, Gate.getClassLoader());
761         }
762         catch(ClassNotFoundException cnfe) {
763           cnfe.printStackTrace();
764         }
765 
766         textField.setText((value == null"" : value.toString());
767         if(type.equals("java.net.URL")) {
768           // clean up all filters
769           fileChooser.resetChoosableFileFilters();
770           fileChooser.setAcceptAllFileFilterUsed(true);
771           fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
772           Parameter param = pDisj.getParameter();
773           Set sufixes = param.getSuffixes();
774           if(sufixes != null) {
775             ExtensionFileFilter fileFilter = new ExtensionFileFilter();
776             Iterator sufIter = sufixes.iterator();
777             while(sufIter.hasNext()) {
778               fileFilter.addExtension((String)sufIter.next());
779             }
780             fileFilter.setDescription("Known file types " + sufixes.toString());
781             fileChooser.addChoosableFileFilter(fileFilter);
782             fileChooser.setFileFilter(fileFilter);
783           }
784 
785           textField.setEditable(true);
786           textButtonBox.removeAll();
787           textButtonBox.add(textField);
788           textButtonBox.add(Box.createHorizontalStrut(5));
789           textButtonBox.add(fileButton);
790           return textButtonBox;
791         }
792         else if(type.equals("java.lang.Boolean")) {
793           textFieldBoolean.setText(value == null "false" : value.toString());
794           return textFieldBoolean;
795         }
796         else if(typeClass != null
797                 && Collection.class.isAssignableFrom(typeClass)) {
798           // List value
799           listUsed = true;
800           Parameter param = pDisj.getParameter();
801 
802           listValue = (Collection)value;
803           listEditor = new ListEditorDialog(SwingUtilities.getAncestorOfClass(
804                   Window.class, ResourceParametersEditor.this),
805                   (Collection)value, typeClass, param.getItemClassName());
806 
807           textField.setEditable(false);
808           textField.setText(textForList((Collection)value));
809           textButtonBox.removeAll();
810           textButtonBox.add(textField);
811           textButtonBox.add(Box.createHorizontalStrut(5));
812           textButtonBox.add(listButton);
813           return textButtonBox;
814         }
815         else if(typeClass != null
816                 && FeatureMap.class.isAssignableFrom(typeClass)) {
817           // List value
818           fmUsed = true;
819 
820           fmValue = (FeatureMap)value;
821           fmEditor = new FeatureMapEditorDialog(SwingUtilities
822                   .getAncestorOfClass(Window.class,
823                           ResourceParametersEditor.this)(FeatureMap)value);
824 
825           textField.setEditable(false);
826           textField.setText(textForFeatureMap((FeatureMap)value));
827           textButtonBox.removeAll();
828           textButtonBox.add(textField);
829           textButtonBox.add(Box.createHorizontalStrut(5));
830           textButtonBox.add(fmButton);
831           return textButtonBox;
832         }
833         else if(typeClass != null && typeClass.isEnum()) {
834           comboUsed = true;
835           try {
836             // extract list of allowable values by reflection - every
837             // enum type has a values method returning an array of values
838             Method getValuesMethod = typeClass.getMethod("values");
839             Object[] enumValues = (Object[])getValuesMethod.invoke(null);
840             Object[] comboValues = null;
841             Parameter param = pDisj.getParameter();
842             // only allow selection of "<none>" for optional parameters
843             if(param.isOptional()) {
844               comboValues = new Object[enumValues.length + 1];
845               comboValues[0"<none>";
846               System.arraycopy(enumValues, 0, comboValues, 1,enumValues.length);
847             }
848             else {
849               comboValues = enumValues;
850             }
851             combo.setModel(new DefaultComboBoxModel(comboValues));
852             combo.setSelectedItem(value == null "<none>" : value);
853             return combo;
854           }
855           catch(Exception ex) {
856             throw new LuckyException("Error calling \"values\" method of an "
857                     "enum type");
858           }
859         }
860         else {
861           textField.setEditable(true);
862           return textField;
863         }
864       }
865     }// getTableCellEditorComponent
866 
867     public Object getCellEditorValue() {
868       if(comboUsed) {
869         Object value = combo.getSelectedItem();
870         return value == "<none>" null : value;
871       }
872       else if(listUsed) {
873         return listValue;
874       }
875       else if(fmUsed) {
876         return fmValue;
877       }
878       else {
879         if(type.equals("java.lang.Boolean")) {
880           // get the value from the label
881           return Boolean.valueOf(textFieldBoolean.getText());
882         }
883         else {
884           // get the value from the text field
885           return textField.getText();
886           // return ((textField.getText().equals("")) ? null :
887           // textField.getText());
888         }
889       }
890     }// public Object getCellEditorValue()
891 
892     /**
893      * The type of the value currently being edited
894      */
895     String type;
896 
897     /**
898      * Combobox use as editor for Gate objects (chooses between
899      * instances)
900      */
901     JComboBox combo;
902 
903     /**
904      * Generic editor for all types that are not treated special
905      */
906     JTextField textField;
907 
908     /**
909      * Editor used for boolean values.
910      */
911     JTextField textFieldBoolean;
912 
913     ListEditorDialog listEditor = null;
914 
915     Collection listValue;
916 
917     FeatureMapEditorDialog fmEditor = null;
918 
919     FeatureMap fmValue;
920 
921     boolean comboUsed;
922 
923     boolean listUsed;
924 
925     boolean fmUsed;
926 
927     JButton fileButton;
928 
929     JButton listButton;
930 
931     JButton fmButton;
932 
933     /** Contains a textfield and a button */
934     JPanel textButtonBox;
935   }// /class ParameterValueEditor
936 
937   /**
938    * Gets a string representation for a list value
939    */
940   protected String textForList(Collection list) {
941     if(list == null || list.isEmpty()) return "[]";
942     StringBuilder res = new StringBuilder("[");
943     Iterator elemIter = list.iterator();
944     while(elemIter.hasNext()) {
945       Object elem = elemIter.next();
946       if(elem != null)
947         res.append((elem instanceof NameBearer?
948           ((NameBearerelem).getName() : elem.toString())
949           .append(", ");
950       else res.append("<null>, ");
951     }
952     res.delete(res.length() 2, res.length() 1);
953     res.append("]");
954     return res.toString();
955   }
956 
957   /**
958    * Get a string representation for a FeatureMap value.
959    */
960   protected String textForFeatureMap(FeatureMap fm) {
961     return (fm == null"" : fm.toString();
962   }
963 
964 }// class NewResourceDialog