~ubuntu-branches/ubuntu/wily/weka/wily

« back to all changes in this revision

Viewing changes to src/main/java/weka/gui/ensembleLibraryEditor/tree/GenericObjectNode.java

  • Committer: Bazaar Package Importer
  • Author(s): tony mancill
  • Date: 2011-08-05 22:40:50 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20110805224050-a01vkwst9epdi4sw
Tags: 3.6.5-1
* Team upload.
* New upstream version (Closes: #632082, #598400)
* Bump Standards-Version to 3.9.2 (no changes required).
* Freshen jar.patch; remove java_cup.patch (incorporated upstream)
* Add README.source to document process of obtaining .png resources.
* Add myself to Uploaders.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *    This program is free software; you can redistribute it and/or modify
3
 
 *    it under the terms of the GNU General Public License as published by
4
 
 *    the Free Software Foundation; either version 2 of the License, or
5
 
 *    (at your option) any later version.
6
 
 *
7
 
 *    This program is distributed in the hope that it will be useful,
8
 
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
 *    GNU General Public License for more details.
11
 
 *
12
 
 *    You should have received a copy of the GNU General Public License
13
 
 *    along with this program; if not, write to the Free Software
14
 
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15
 
 */
16
 
 
17
 
/*
18
 
 *    GenericObjectNode.java
19
 
 *    Copyright (C) 2006 Robert Jung
20
 
 *
21
 
 */
22
 
 
23
 
package weka.gui.ensembleLibraryEditor.tree;
24
 
 
25
 
import weka.classifiers.Classifier;
26
 
import weka.gui.GenericObjectEditor;
27
 
import weka.gui.ensembleLibraryEditor.AddModelsPanel;
28
 
 
29
 
import java.awt.Component;
30
 
import java.beans.BeanInfo;
31
 
import java.beans.IntrospectionException;
32
 
import java.beans.Introspector;
33
 
import java.beans.MethodDescriptor;
34
 
import java.beans.PropertyChangeEvent;
35
 
import java.beans.PropertyChangeListener;
36
 
import java.beans.PropertyDescriptor;
37
 
import java.beans.PropertyEditor;
38
 
import java.beans.PropertyEditorManager;
39
 
import java.beans.PropertyVetoException;
40
 
import java.lang.reflect.InvocationTargetException;
41
 
import java.lang.reflect.Method;
42
 
import java.util.Vector;
43
 
 
44
 
import javax.swing.JFrame;
45
 
import javax.swing.JOptionPane;
46
 
import javax.swing.JPanel;
47
 
import javax.swing.JTree;
48
 
import javax.swing.tree.DefaultMutableTreeNode;
49
 
import javax.swing.tree.DefaultTreeModel;
50
 
 
51
 
/**
52
 
 * This class is responsible for allowing users to choose an object that
53
 
 * was provided with a GenericObjectEditor.  Just about every one of these 
54
 
 * Objects is a Weka Classifier.  There are two important things that these
55
 
 * nodes are responsible for beyond the other parameter node types.  First,
56
 
 * they must discover all of the parameters that need to be added in the 
57
 
 * model as child nodes.  This is done through a loop of introspection that
58
 
 * was copied and adapted from the weka.gui.PropertySheetPanel class.  
59
 
 * Second, this class is also responsible for discovering all possible 
60
 
 * combinations of GenericObject parameters that are stored in its child 
61
 
 * nodes.  This is accomplished by first discovering all of the child node 
62
 
 * parameters in the getValues method and then finding all combinations of 
63
 
 * these values with the combinAllValues method.
64
 
 * 
65
 
 * @author  Robert Jung (mrbobjung@gmail.com)
66
 
 * @version $Revision: 1.1 $
67
 
 */
68
 
public class GenericObjectNode
69
 
  extends DefaultMutableTreeNode
70
 
  implements PropertyChangeListener {
71
 
  
72
 
  /** for serialization */
73
 
  private static final long serialVersionUID = 688096727663132485L;
74
 
  
75
 
  //The following 8 arrays hold the accumulated information about the
76
 
  //Classifier parameters that we discover through introspection.  This
77
 
  //is very similar to the approach within PropertySheetPanel.
78
 
 
79
 
  /** Holds properties of the target */
80
 
  private PropertyDescriptor m_Properties[];
81
 
  
82
 
  /** this tracks which indexes of the m_Properties */
83
 
  private Vector m_UsedPropertyIndexes;
84
 
  
85
 
  /** Holds the methods of the target */
86
 
  private MethodDescriptor m_Methods[];
87
 
  
88
 
  /** Holds property editors of the object */
89
 
  private PropertyEditor m_Editors[];
90
 
  
91
 
  /** Holds current object values for each property */
92
 
  private Object m_Values[];
93
 
  
94
 
  /** The labels for each property */
95
 
  private String m_Names[];
96
 
  
97
 
  /** The tool tip text for each property */
98
 
  private String m_TipTexts[];
99
 
  
100
 
  /** StringBuffer containing help text for the object being edited */
101
 
  private StringBuffer m_HelpText;
102
 
  
103
 
  /** the GenericObjectEditor that was supplied for this node */
104
 
  private GenericObjectEditor m_GenericObjectEditor;
105
 
  
106
 
  /** this Vector stores all of the possible combinations of parameters 
107
 
   * that it obtains from its child nodes.  These combinations are 
108
 
   * created by the recursive combineAllValues method*/
109
 
  private Vector m_WorkingSetCombinations;
110
 
  
111
 
  /** the tip text for our node editor to display */
112
 
  private String m_ToolTipText;
113
 
  
114
 
  /** a reference to the tree model is necessary to be able to add and 
115
 
   * remove nodes in the tree */
116
 
  private DefaultTreeModel m_TreeModel;
117
 
  
118
 
  /** this is a reference to the Tree object that this node is 
119
 
   * contained within. Its required for this node to be able to 
120
 
   * add/remove nodes from the JTree*/
121
 
  private JTree m_Tree;
122
 
  
123
 
  /** This is a reference to the parent panel of the JTree so that we can 
124
 
   * supply it as the required argument when supplying warning JDialog 
125
 
   * messages*/
126
 
  private final AddModelsPanel m_ParentPanel;
127
 
  
128
 
  /** 
129
 
   * The constructor initialiazes the member variables of this node, 
130
 
   * Note that the "value" of this generic object is stored as the treeNode
131
 
   * user object. 
132
 
   * 
133
 
   * @param panel       the reference to the parent panel for calls to JDialog
134
 
   * @param value the value stored at this tree node
135
 
   * @param genericObjectEditor the GenericObjectEditor for this object
136
 
   * @param toolTipText the tipText to be displayed for this object
137
 
   */
138
 
  public GenericObjectNode(AddModelsPanel panel, Object value,
139
 
      GenericObjectEditor genericObjectEditor, String toolTipText) {
140
 
    
141
 
    super(value);
142
 
    //setObject(value);
143
 
    m_ParentPanel = panel;
144
 
    this.m_GenericObjectEditor = genericObjectEditor;
145
 
    this.m_ToolTipText = toolTipText;
146
 
    
147
 
  }
148
 
  
149
 
  /** 
150
 
   * It seems kind of dumb that the reference to the tree model is passed in
151
 
   * seperately - but know that this is actually necessary.  There is a really 
152
 
   * weird chicken before the egg problem.  You cannot create a TreeModel without
153
 
   * giving it its root node.  However, the nodes in your tree can't update the 
154
 
   * structure of the tree unless they have a reference to the TreeModel.  So in 
155
 
   * the end this was the only compromise that I could get to work well
156
 
   * 
157
 
   * @param tree        the tree to use
158
 
   */
159
 
  public void setTree(JTree tree) {
160
 
    this.m_Tree = tree;
161
 
    this.m_TreeModel = (DefaultTreeModel) m_Tree.getModel();
162
 
    
163
 
  }
164
 
  
165
 
  /**
166
 
   * returns the current tree
167
 
   * 
168
 
   * @return            the current tree
169
 
   */
170
 
  public JTree getTree() {
171
 
    return m_Tree;
172
 
  }
173
 
  
174
 
  /**
175
 
   * A getter for the GenericObjectEditor for this node
176
 
   * 
177
 
   * @return            the editor
178
 
   */
179
 
  public GenericObjectEditor getEditor() {
180
 
    return m_GenericObjectEditor;
181
 
  }
182
 
  
183
 
  /**
184
 
   * getter for the tooltip text
185
 
   * 
186
 
   * @return tooltip text
187
 
   */
188
 
  public StringBuffer getHelpText() {
189
 
    return m_HelpText;
190
 
  }
191
 
  
192
 
  /**
193
 
   * getter for the tooltip text
194
 
   * 
195
 
   * @return tooltip text
196
 
   */
197
 
  public String getToolTipText() {
198
 
    return m_ToolTipText;
199
 
  }
200
 
  
201
 
  /**
202
 
   * getter for this node's object
203
 
   * 
204
 
   * @return    the node's object
205
 
   */
206
 
  public Object getObject() {
207
 
    return getUserObject();
208
 
  }
209
 
  
210
 
  /**
211
 
   * setter for this nodes object
212
 
   * 
213
 
   * @param newValue    sets the new object
214
 
   */
215
 
  public void setObject(Object newValue) {
216
 
    setUserObject(newValue);
217
 
  }
218
 
  
219
 
  /**
220
 
   * this is a simple filter for the setUserObject method.  We basically
221
 
   * don't want null values to be passed in.
222
 
   * 
223
 
   * @param o           the object to set
224
 
   */
225
 
  public void setUserObject(Object o) {
226
 
    if (o != null)
227
 
      super.setUserObject(o);
228
 
  }
229
 
  
230
 
  /**
231
 
   * getter for the parent panel
232
 
   * 
233
 
   * @return            the parent panel
234
 
   */
235
 
  public JPanel getParentPanel() {
236
 
    return m_ParentPanel;
237
 
  }
238
 
  
239
 
  /**
240
 
   * returns always null
241
 
   * 
242
 
   * @return            always null
243
 
   */
244
 
  public String toString() {
245
 
    return null;
246
 
    //return getClass().getName() + "[" + getUserObject().toString() + "]";
247
 
  }
248
 
  
249
 
  /**
250
 
   * This implements the PropertyChangeListener for this node that gets 
251
 
   * registered with its Editor.  All we really have to do is change the 
252
 
   * Object value stored internally at this node when its editor says the 
253
 
   * value changed.
254
 
   * 
255
 
   * @param evt         the event
256
 
   */
257
 
  public void propertyChange(PropertyChangeEvent evt) {
258
 
    
259
 
    Object newValue = ((GenericObjectEditor) evt.getSource()).getValue();
260
 
    
261
 
    if (!newValue.getClass().equals(getObject().getClass())) {
262
 
      
263
 
      if (m_TreeModel.getRoot() == this) {
264
 
        
265
 
        try {
266
 
          m_ParentPanel.buildClassifierTree((Classifier) newValue
267
 
              .getClass().newInstance());
268
 
        } catch (InstantiationException e) {
269
 
          e.printStackTrace();
270
 
        } catch (IllegalAccessException e) {
271
 
          e.printStackTrace();
272
 
        }
273
 
        m_ParentPanel.update(m_ParentPanel.getGraphics());
274
 
        m_ParentPanel.repaint();
275
 
        
276
 
        //System.out.println("Changed root");
277
 
        
278
 
      } else {
279
 
        setObject(newValue);
280
 
        updateTree();
281
 
        updateTree();
282
 
        m_TreeModel.nodeChanged(this);
283
 
      }
284
 
    }
285
 
  }
286
 
  
287
 
  /**
288
 
   * This method uses introspection to programatically discover all of 
289
 
   * the parameters for this generic object.  For each one of them it
290
 
   * uses the TreeModel reference to create a new subtree to represent
291
 
   * that parameter and its value ranges.  Note that all of these nodes
292
 
   * are PropertyNodes which themselves hold the logic of figuring out
293
 
   * what type of parameter it is they are representing and thus what 
294
 
   * type of subtree to build.
295
 
   * <p/> 
296
 
   * We need to be careful because this was molded from the code inside of 
297
 
   * the PropertySheetPanel class.  Which means that we are wide open
298
 
   * to copy/paste problems.  In the future, when that code changes to 
299
 
   * adapt to other changes in Weka then this could easily become broken.
300
 
   */
301
 
  public void updateTree() {
302
 
    
303
 
    int childCount = m_TreeModel.getChildCount(this);
304
 
    
305
 
    for (int i = 0; i < childCount; i++) {
306
 
      DefaultMutableTreeNode child = (DefaultMutableTreeNode) m_TreeModel.getChild(this, 0);
307
 
      
308
 
      m_TreeModel.removeNodeFromParent(child);
309
 
    }
310
 
    
311
 
    //removeAllChildren();
312
 
    
313
 
    Object classifier = this.getUserObject();
314
 
    
315
 
    try {
316
 
      BeanInfo bi = Introspector.getBeanInfo(classifier.getClass());
317
 
      m_Properties = bi.getPropertyDescriptors();
318
 
      m_Methods = bi.getMethodDescriptors();
319
 
    } catch (IntrospectionException ex) {
320
 
      System.err.println("PropertySheet: Couldn't introspect");
321
 
      return;
322
 
    }
323
 
    
324
 
    //           Look for a globalInfo method that returns a string
325
 
    // describing the target
326
 
    for (int i = 0; i < m_Methods.length; i++) {
327
 
      String name = m_Methods[i].getDisplayName();
328
 
      Method meth = m_Methods[i].getMethod();
329
 
      if (name.equals("globalInfo")) {
330
 
        if (meth.getReturnType().equals(String.class)) {
331
 
          try {
332
 
            Object args[] = {};
333
 
            String globalInfo = (String) (meth.invoke(getObject(),
334
 
                args));
335
 
            String summary = globalInfo;
336
 
            int ci = globalInfo.indexOf('.');
337
 
            if (ci != -1) {
338
 
              summary = globalInfo.substring(0, ci + 1);
339
 
            }
340
 
            final String className = getObject().getClass().getName();
341
 
            m_HelpText = new StringBuffer("NAME\n");
342
 
            m_HelpText.append(className).append("\n\n");
343
 
            m_HelpText.append("SYNOPSIS\n").append(globalInfo).append("\n\n");
344
 
            
345
 
          } catch (Exception ex) {
346
 
            // ignored
347
 
          }
348
 
        }
349
 
      }
350
 
    }
351
 
    
352
 
    m_UsedPropertyIndexes = new Vector();
353
 
    
354
 
    m_Editors = new PropertyEditor[m_Properties.length];
355
 
    
356
 
    m_Values = new Object[m_Properties.length];
357
 
    m_Names = new String[m_Properties.length];
358
 
    m_TipTexts = new String[m_Properties.length];
359
 
    boolean firstTip = true;
360
 
    
361
 
    for (int i = 0; i < m_Properties.length; i++) {
362
 
      
363
 
      // Don't display hidden or expert properties.
364
 
      if (m_Properties[i].isHidden() || m_Properties[i].isExpert()) {
365
 
        continue;
366
 
      }
367
 
      
368
 
      m_Names[i] = m_Properties[i].getDisplayName();
369
 
      Class type = m_Properties[i].getPropertyType();
370
 
      Method getter = m_Properties[i].getReadMethod();
371
 
      Method setter = m_Properties[i].getWriteMethod();
372
 
      
373
 
      // Only display read/write properties.
374
 
      if (getter == null || setter == null) {
375
 
        continue;
376
 
      }
377
 
      
378
 
      try {
379
 
        Object args[] = {};
380
 
        Object value = getter.invoke(classifier, args);
381
 
        m_Values[i] = value;
382
 
        
383
 
        PropertyEditor editor = null;
384
 
        Class pec = m_Properties[i].getPropertyEditorClass();
385
 
        if (pec != null) {
386
 
          try {
387
 
            editor = (PropertyEditor) pec.newInstance();
388
 
          } catch (Exception ex) {
389
 
            // Drop through.
390
 
          }
391
 
        }
392
 
        if (editor == null) {
393
 
          editor = PropertyEditorManager.findEditor(type);
394
 
        }
395
 
        m_Editors[i] = editor;
396
 
        
397
 
        // If we can't edit this component, skip it.
398
 
        if (editor == null) {
399
 
          continue;
400
 
        }
401
 
        if (editor instanceof GenericObjectEditor) {
402
 
          ((GenericObjectEditor) editor).setClassType(type);
403
 
        }
404
 
        
405
 
        // Don't try to set null values:
406
 
        if (value == null) {
407
 
          continue;
408
 
        }
409
 
        
410
 
        editor.setValue(value);
411
 
        
412
 
        // now look for a TipText method for this property
413
 
        String tipName = m_Names[i] + "TipText";
414
 
        for (int j = 0; j < m_Methods.length; j++) {
415
 
          String mname = m_Methods[j].getDisplayName();
416
 
          Method meth = m_Methods[j].getMethod();
417
 
          if (mname.equals(tipName)) {
418
 
            if (meth.getReturnType().equals(String.class)) {
419
 
              try {
420
 
                String tempTip = (String) (meth.invoke(
421
 
                    classifier, args));
422
 
                int ci = tempTip.indexOf('.');
423
 
                if (ci < 0) {
424
 
                  m_TipTexts[i] = tempTip;
425
 
                } else {
426
 
                  m_TipTexts[i] = tempTip.substring(0, ci);
427
 
                }
428
 
                
429
 
                if (m_HelpText != null) {
430
 
                  if (firstTip) {
431
 
                    m_HelpText.append("OPTIONS\n");
432
 
                    firstTip = false;
433
 
                  }
434
 
                  m_HelpText.append(m_Names[i]).append(" -- ");
435
 
                  m_HelpText.append(tempTip).append("\n\n");
436
 
                  
437
 
                }
438
 
                
439
 
              } catch (Exception ex) {
440
 
                
441
 
              }
442
 
              break;
443
 
            }
444
 
          }
445
 
        }
446
 
        
447
 
        //Here we update the usedPropertyIndexes variable so that
448
 
        //later on we will know which ones to look at.
449
 
        m_UsedPropertyIndexes.add(new Integer(i));
450
 
        
451
 
        int currentCount = m_TreeModel.getChildCount(this);
452
 
        
453
 
        //Now we make a child node and add it to the tree underneath 
454
 
        //this one
455
 
        PropertyNode newNode = new PropertyNode(m_Tree, m_ParentPanel,
456
 
            m_Names[i], m_TipTexts[i], m_Values[i], m_Editors[i]);
457
 
        
458
 
        m_TreeModel.insertNodeInto(newNode, this, currentCount);
459
 
        
460
 
      } catch (InvocationTargetException ex) {
461
 
        System.err.println("Skipping property " + m_Names[i]
462
 
                                                          + " ; exception on target: " + ex.getTargetException());
463
 
        ex.getTargetException().printStackTrace();
464
 
        continue;
465
 
      } catch (Exception ex) {
466
 
        System.err.println("Skipping property " + m_Names[i]
467
 
                                                          + " ; exception: " + ex);
468
 
        ex.printStackTrace();
469
 
        continue;
470
 
      }
471
 
      
472
 
    }
473
 
    
474
 
    //Finally we tell the TreeModel to update itself so the changes
475
 
    //will be visible
476
 
    m_TreeModel.nodeStructureChanged(this);
477
 
  }
478
 
  
479
 
  /**
480
 
   * This method iterates over all of the child nodes of this 
481
 
   * GenericObjectNode and requests the verious sets of values that the
482
 
   * user has presumably specified.  Once these sets of values are 
483
 
   * 
484
 
   * @return a Vector consisting of all parameter combinations
485
 
   */
486
 
  public Vector getValues() {
487
 
    
488
 
    Vector valuesVector = new Vector();
489
 
    
490
 
    int childCount = m_TreeModel.getChildCount(this);
491
 
    
492
 
    //poll all child nodes for their values.
493
 
    for (int i = 0; i < childCount; i++) {
494
 
      
495
 
      PropertyNode currentChild = (PropertyNode) m_TreeModel.getChild(
496
 
          this, i);
497
 
      
498
 
      Vector v = currentChild.getAllValues();
499
 
      valuesVector.add(v);
500
 
      
501
 
    }
502
 
    
503
 
    //Need to initialize the working set of paramter combinations
504
 
    m_WorkingSetCombinations = new Vector();
505
 
    
506
 
    //obtain all combinations of the paremeters
507
 
    combineAllValues(new Vector(), valuesVector);
508
 
    
509
 
    /*
510
 
     //nice for initially debugging this - and there was a WHOLE lot of
511
 
      //that going on till this crazy idea finally worked.
512
 
       for (int i = 0; i < m_WorkingSetCombinations.size(); i++) {
513
 
       
514
 
       System.out.print("Combo "+i+": ");
515
 
       
516
 
       Vector current = (Vector)m_WorkingSetCombinations.get(i);
517
 
       for (int j = 0; j < current.size(); j++) {
518
 
       
519
 
       System.out.print(current.get(j)+"\t");
520
 
       
521
 
       }
522
 
       
523
 
       System.out.print("\n");
524
 
       }
525
 
       */
526
 
    
527
 
    //Now the real work begins.  Here we need to translate all of the values
528
 
    //received from the editors back into the actual class types that the 
529
 
    //Weka classifiers will understand.  for example, String values for 
530
 
    //enumerated values need to be turned back into the SelectedTag objects 
531
 
    //that classifiers understand. 
532
 
    //This vector will hold all of the actual generic objects that are being 
533
 
    //instantiated
534
 
    Vector newGenericObjects = new Vector();
535
 
    
536
 
    for (int i = 0; i < m_WorkingSetCombinations.size(); i++) {
537
 
      
538
 
      Vector current = (Vector) m_WorkingSetCombinations.get(i);
539
 
      
540
 
      //create a new copy of this class.  We will use this copy to test whether
541
 
      //the current set of parameters is valid.
542
 
      Object o = this.getUserObject();
543
 
      Class c = o.getClass();
544
 
      Object copy = null;
545
 
      
546
 
      try {
547
 
        copy = c.newInstance();
548
 
      } catch (InstantiationException e) {
549
 
        e.printStackTrace();
550
 
      } catch (IllegalAccessException e) {
551
 
        e.printStackTrace();
552
 
      }
553
 
      
554
 
      for (int j = 0; j < current.size(); j++) {
555
 
        
556
 
        Object[] args = new Object[1];
557
 
        
558
 
        int index = ((Integer) m_UsedPropertyIndexes.get(j)).intValue();
559
 
        
560
 
        PropertyDescriptor property = (PropertyDescriptor) m_Properties[index];
561
 
        Method setter = property.getWriteMethod();
562
 
        Class[] params = setter.getParameterTypes();
563
 
        
564
 
        Object currentVal = current.get(j);
565
 
        
566
 
        //System.out.println(currentVal.getClass().toString());
567
 
        
568
 
        //we gotta turn strings back into booleans 
569
 
        if (params.length == 1
570
 
            && params[0].toString().equals("boolean")
571
 
            && currentVal.getClass().toString().equals(
572
 
            "class java.lang.String")) {
573
 
          
574
 
          currentVal = new Boolean((String) current.get(j));
575
 
        }
576
 
        
577
 
        //we gotta turn strings back into "Tags"
578
 
        if (params.length == 1
579
 
            && params[0].toString().equals(
580
 
            "class weka.core.SelectedTag")
581
 
            && currentVal.getClass().toString().equals(
582
 
            "class java.lang.String")) {
583
 
          
584
 
          String tagString = (String) current.get(j);
585
 
          
586
 
          m_Editors[index].setAsText(tagString);
587
 
          currentVal = m_Editors[index].getValue();
588
 
          
589
 
        }
590
 
        
591
 
        args[0] = currentVal;
592
 
        
593
 
        /*
594
 
         System.out.print("setterName: "+setter.getName()+
595
 
         " editor class: "+m_Editors[index].getClass()+
596
 
         " params: ");
597
 
         
598
 
         
599
 
         for (int k = 0; k < params.length; k++) 
600
 
         System.out.print(params[k].toString()+" ");
601
 
         
602
 
         System.out.println(" value class: "+args[0].getClass().toString());
603
 
         */
604
 
        
605
 
        try {
606
 
          
607
 
          //we tell the setter for the current parameter to update the copy
608
 
          //with the current parameter value
609
 
          setter.invoke(copy, args);
610
 
          
611
 
        } catch (InvocationTargetException ex) {
612
 
          if (ex.getTargetException() instanceof PropertyVetoException) {
613
 
            String message = "WARNING: Vetoed; reason is: "
614
 
              + ex.getTargetException().getMessage();
615
 
            System.err.println(message);
616
 
            
617
 
            Component jf;
618
 
            jf = m_ParentPanel.getRootPane();
619
 
            JOptionPane.showMessageDialog(jf, message, "error",
620
 
                JOptionPane.WARNING_MESSAGE);
621
 
            if (jf instanceof JFrame)
622
 
              ((JFrame) jf).dispose();
623
 
            
624
 
          } else {
625
 
            System.err.println(ex.getTargetException().getClass()
626
 
                .getName()
627
 
                + " while updating "
628
 
                + property.getName()
629
 
                + ": " + ex.getTargetException().getMessage());
630
 
            Component jf;
631
 
            jf = m_ParentPanel.getRootPane();
632
 
            JOptionPane.showMessageDialog(jf, ex
633
 
                .getTargetException().getClass().getName()
634
 
                + " while updating "
635
 
                + property.getName()
636
 
                + ":\n" + ex.getTargetException().getMessage(),
637
 
                "error", JOptionPane.WARNING_MESSAGE);
638
 
            if (jf instanceof JFrame)
639
 
              ((JFrame) jf).dispose();
640
 
            
641
 
          }
642
 
          
643
 
        } catch (IllegalArgumentException e) {
644
 
          e.printStackTrace();
645
 
        } catch (IllegalAccessException e) {
646
 
          e.printStackTrace();
647
 
        }
648
 
        
649
 
      }
650
 
      
651
 
      //At this point we have set all the parameters for this GenericObject
652
 
      //with a single combination that was generated from the 
653
 
      //m_WorkingSetCombinations Vector and can add it to the collection that
654
 
      //will be returned
655
 
      newGenericObjects.add(copy);
656
 
      
657
 
    }
658
 
    
659
 
    return newGenericObjects;
660
 
  }
661
 
  
662
 
  /** This method is responsible for returning all possible values through 
663
 
   * a recursive loop.
664
 
   * 
665
 
   * When the recursion terminates that means that there are no more parameter
666
 
   * sets to branch out through so all we have to do is save the current Vector
667
 
   * in the working set of combinations.  Otherwise we iterate through all 
668
 
   * possible values left in the next set of parameter values and recursively
669
 
   * call this function.
670
 
   * 
671
 
   * @param previouslySelected stores the values chosen in this branch of the recursion 
672
 
   * @param remainingValues the sets of values left 
673
 
   */
674
 
  public void combineAllValues(Vector previouslySelected,
675
 
      Vector remainingValues) {
676
 
    
677
 
    if (remainingValues.isEmpty()) {
678
 
      m_WorkingSetCombinations.add(previouslySelected);
679
 
      return;
680
 
    }
681
 
    
682
 
    Vector currentSet = new Vector((Vector) remainingValues.get(0));
683
 
    Vector tmpRemaining = new Vector(remainingValues);
684
 
    tmpRemaining.removeElementAt(0);
685
 
    
686
 
    for (int i = 0; i < currentSet.size(); i++) {
687
 
      Vector tmpPreviouslySelected = new Vector(previouslySelected);
688
 
      tmpPreviouslySelected.add(currentSet.get(i));
689
 
      combineAllValues(tmpPreviouslySelected, tmpRemaining);
690
 
    }
691
 
    
692
 
  }
693
 
  
694
 
}
 
 
b'\\ No newline at end of file'