source: src/main/java/weka/gui/beans/xml/XMLBeans.java @ 6

Last change on this file since 6 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 63.8 KB
Line 
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 * XMLBeans.java
19 * Copyright (C) 2005 University of Waikato, Hamilton, New Zealand
20 */
21
22package weka.gui.beans.xml;
23
24import weka.core.converters.ConverterUtils;
25import weka.core.xml.XMLBasicSerialization;
26import weka.core.xml.XMLDocument;
27import weka.core.Environment;
28import weka.core.EnvironmentHandler;
29import weka.gui.beans.BeanConnection;
30import weka.gui.beans.BeanInstance;
31import weka.gui.beans.BeanVisual;
32import weka.gui.beans.MetaBean;
33import weka.gui.beans.Visible;
34import weka.gui.beans.BeanCommon;
35
36import java.awt.Color;
37import java.awt.Dimension;
38import java.awt.Font;
39import java.awt.Point;
40import java.beans.BeanInfo;
41import java.beans.EventSetDescriptor;
42import java.beans.Introspector;
43import java.beans.beancontext.BeanContextSupport;
44import java.io.File;
45import java.util.Enumeration;
46import java.util.Hashtable;
47import java.util.StringTokenizer;
48import java.util.Vector;
49
50import javax.swing.JComponent;
51import javax.swing.JPanel;
52import javax.swing.plaf.ColorUIResource;
53import javax.swing.plaf.FontUIResource;
54
55import org.w3c.dom.Document;
56import org.w3c.dom.Element;
57import org.w3c.dom.NodeList;
58
59/**
60 * This class serializes and deserializes a KnowledgeFlow setup to and fro XML.
61 * <br>
62 *
63 * @author FracPete (fracpete at waikato dot ac dot nz)
64 * @version $Revision: 5235 $
65 */
66public class XMLBeans 
67  extends XMLBasicSerialization {
68
69  /** the value of the id property */
70  public final static String VAL_ID = "id";
71
72  /** the value of the x property */
73  public final static String VAL_X = "x";
74
75  /** the value of the y property */
76  public final static String VAL_Y = "y";
77
78  /** the value of the bean property */
79  public final static String VAL_BEAN = "bean";
80
81  /** the value of the customName property */
82  public final static String VAL_CUSTOM_NAME = "custom_name";
83 
84  /** the value of the source property */
85  public final static String VAL_SOURCEID = "source_id";
86 
87  /** the value of the target property */
88  public final static String VAL_TARGETID = "target_id";
89 
90  /** the value of the eventname property */
91  public final static String VAL_EVENTNAME = "eventname";
92 
93  /** the value of the hidden property */
94  public final static String VAL_HIDDEN = "hidden";
95 
96  /** the value of the file property */
97  public final static String VAL_FILE = "file";
98 
99  /** the value of the dir property */
100  public final static String VAL_DIR = "dir";
101 
102  /** the value of the prefix property */
103  public final static String VAL_PREFIX = "prefix";
104
105  public final static String VAL_RELATIVE_PATH = "useRelativePath";
106 
107  /** the value of the options property */
108  public final static String VAL_OPTIONS = "options";
109 
110  /** the value of the saver property */
111  public final static String VAL_SAVER = "saver";
112 
113  /** the value of the loader property */
114  public final static String VAL_LOADER = "loader";
115 
116  /** the value of the text property */
117  public final static String VAL_TEXT = "text";
118 
119  /** the value of the beanContext property */
120  public final static String VAL_BEANCONTEXT = "beanContext";
121
122  /** the value of the width property */
123  public final static String VAL_WIDTH = "width";
124
125  /** the value of the height property */
126  public final static String VAL_HEIGHT = "height";
127
128  /** the value of the red property */
129  public final static String VAL_RED = "red";
130
131  /** the value of the green property */
132  public final static String VAL_GREEN = "green";
133 
134  /** the value of the blue property */
135  public final static String VAL_BLUE = "blue";
136
137  /** the value of the value property */
138  public final static String VAL_NAME = "name";
139
140  /** the value of the style property */
141  public final static String VAL_STYLE = "style";
142 
143  /** the value of the location property */
144  public final static String VAL_LOCATION = "location";
145 
146  /** the value of the size property */
147  public final static String VAL_SIZE = "size";
148 
149  /** the value of the color property */
150  public final static String VAL_COLOR = "color";
151 
152  /** the value of the font property */
153  public final static String VAL_FONT = "font";
154 
155  /** the value of the iconpath property */
156  public final static String VAL_ICONPATH = "iconPath";
157 
158  /** the value of the animatedIconPath property */
159  public final static String VAL_ANIMATEDICONPATH = "animatedIconPath";
160 
161  /** the value of the associatedConnections property */
162  public final static String VAL_ASSOCIATEDCONNECTIONS = "associatedConnections";
163 
164  /** the value of the input property */
165  public final static String VAL_INPUTS = "inputs";
166 
167  /** the value of the input id property */
168  public final static String VAL_INPUTSID = "inputs_id";
169 
170  /** the value of the outputs id property */
171  public final static String VAL_OUTPUTS = "outputs";
172 
173  /** the value of the outputs property */
174  public final static String VAL_OUTPUTSID = "outputs_id";
175 
176  /** the value of the subFlow property */
177  public final static String VAL_SUBFLOW = "subFlow";
178 
179  /** the value of the originalCoords property */
180  public final static String VAL_ORIGINALCOORDS = "originalCoords";
181 
182  /** the value of the relationNameForFilename property (Saver) */
183  public final static String VAL_RELATIONNAMEFORFILENAME = "relationNameForFilename";
184
185  /** the index in the Vector, where the BeanInstances are stored
186   * (Instances and Connections are stored in a Vector and then serialized) */
187  public final static int INDEX_BEANINSTANCES = 0;
188
189  /** the index in the Vector, where the BeanConnections are stored
190  * (Instances and Connections are stored in a Vector and then serialized) */
191  public final static int INDEX_BEANCONNECTIONS = 1;
192 
193  /** the component that manages the layout of the beans */
194  protected JComponent m_BeanLayout;
195 
196  /** keeps track of the BeanInstances read so far, used for the BeanConnections */
197  protected Vector m_BeanInstances;
198 
199  /** keeps track of the BeanInstances read so far, used for the BeanConnections */
200  protected Vector m_BeanInstancesID;
201
202  /** whether to ignore the BeanConnection */
203  protected boolean m_IgnoreBeanConnections;
204 
205  /** the current MetaBean (for the BeanConnections) */
206  protected MetaBean m_CurrentMetaBean;
207
208  /** the identifier for regular BeanConnections */
209  protected final static String REGULAR_CONNECTION = "regular_connection";
210 
211  /** the relation between Bean and connection, MetaBean BeanConnections
212   * are stored under the reference of the MetaBean, regular connections
213   * are stored under REGULAR_CONNECTION. The relation has the following
214   * format (is a string): sourcePos,targetPos,event,hidden
215   * @see #REGULAR_CONNECTION */
216  protected Hashtable m_BeanConnectionRelation;
217 
218  /** the data that is about to be read/written contains a complete layout
219   * @see #m_DataType */
220  public final static int DATATYPE_LAYOUT = 0;
221 
222  /** the data that is about to be read/written contains user-components, i.e.,
223   * Metabeans
224   * @see #m_DataType */
225  public final static int DATATYPE_USERCOMPONENTS = 1;
226 
227  /** the type of data that is be read/written
228   * @see #DATATYPE_LAYOUT
229   * @see #DATATYPE_USERCOMPONENTS */
230  protected int m_DataType = DATATYPE_LAYOUT;
231 
232  /** the beancontext to use for loading from XML and the beancontext is
233   * null in the bean */
234  protected BeanContextSupport m_BeanContextSupport = null;
235 
236  /**
237   * initializes the serialization for layouts
238   *
239   * @param layout      the component that manages the layout
240   * @param context     the bean context support to use
241   * @throws Exception  if initialization fails
242   */
243  public XMLBeans(JComponent layout, BeanContextSupport context) throws Exception {
244    this(layout, context, DATATYPE_LAYOUT);
245  }
246 
247  /**
248   * initializes the serialization for different types of data
249   *
250   * @param layout      the component that manages the layout
251   * @param context     the bean context support to use
252   * @param datatype    the type of data to read/write
253   * @throws Exception  if initialization fails
254   */
255  public XMLBeans(JComponent layout, BeanContextSupport context, int datatype) throws Exception {
256    super();
257   
258    m_BeanLayout = layout;
259    m_BeanContextSupport = context;
260    setDataType(datatype);
261  }
262 
263  /**
264   * sets what kind of data is to be read/written
265   * @param value       the type of data
266   * @see #m_DataType
267   */
268  public void setDataType(int value) {
269    if (value == DATATYPE_LAYOUT)
270      m_DataType = value;
271    else if (value == DATATYPE_USERCOMPONENTS)
272      m_DataType = value;
273    else
274      System.out.println("DataType '" + value + "' is unknown!");
275  }
276 
277  /**
278   * returns the type of data that is to be read/written
279   * @return the type of data
280   * @see #m_DataType
281   */
282  public int getDataType() {
283    return m_DataType;
284  }
285
286  /**
287   * generates internally a new XML document and clears also the IgnoreList and
288   * the mappings for the Read/Write-Methods
289   *
290   * @throws Exception if something goes wrong
291   */
292  public void clear() throws Exception {
293    Vector<String>      classnames;
294    int                 i;
295   
296    super.clear();
297   
298    // ignore: suppress unnecessary GUI stuff
299    // needs to be checked for new Java versions (might introduce new properties)
300    // - works with Java 1.5
301    m_Properties.addIgnored("UI");
302    m_Properties.addIgnored("actionMap");
303    m_Properties.addIgnored("alignmentX");
304    m_Properties.addIgnored("alignmentY");
305    m_Properties.addIgnored("autoscrolls");
306    m_Properties.addIgnored("background");
307    m_Properties.addIgnored("border");
308    m_Properties.addIgnored("componentPopupMenu");
309    m_Properties.addIgnored("debugGraphicsOptions");
310    m_Properties.addIgnored("doubleBuffered");
311    m_Properties.addIgnored("enabled");
312    m_Properties.addIgnored("focusCycleRoot");
313    m_Properties.addIgnored("focusTraversalPolicy");
314    m_Properties.addIgnored("focusTraversalPolicyProvider");
315    m_Properties.addIgnored("focusable");
316    m_Properties.addIgnored("font");
317    m_Properties.addIgnored("foreground");
318    m_Properties.addIgnored("inheritsPopupMenu");
319    m_Properties.addIgnored("inputVerifier");
320    m_Properties.addIgnored("layout");
321    m_Properties.addIgnored("locale");
322    m_Properties.addIgnored("maximumSize");
323    m_Properties.addIgnored("minimumSize");
324    m_Properties.addIgnored("nextFocusableComponent");
325    m_Properties.addIgnored("opaque");
326    m_Properties.addIgnored("preferredSize");
327    m_Properties.addIgnored("requestFocusEnabled");
328    m_Properties.addIgnored("toolTipText");
329    m_Properties.addIgnored("transferHandler");
330    m_Properties.addIgnored("verifyInputWhenFocusTarget");
331    m_Properties.addIgnored("visible");
332
333    // special ignore
334    m_Properties.addIgnored("size");  // otherwise you get an endless loop with Dimension!
335    m_Properties.addIgnored("location");  // otherwise you get an endless loop with Point!
336
337    // allow
338    m_Properties.addAllowed(weka.gui.beans.BeanInstance.class, "x");
339    m_Properties.addAllowed(weka.gui.beans.BeanInstance.class, "y");
340    m_Properties.addAllowed(weka.gui.beans.BeanInstance.class, "bean");
341    m_Properties.addAllowed(weka.gui.beans.Saver.class, "saver");
342    m_Properties.addAllowed(weka.gui.beans.Loader.class, "loader");
343    m_Properties.addAllowed(weka.gui.beans.Saver.class, "relationNameForFilename");
344    if (getDataType() == DATATYPE_LAYOUT)
345      m_Properties.addAllowed(weka.gui.beans.Loader.class, "beanContext");
346    else
347      m_Properties.addIgnored(weka.gui.beans.Loader.class, "beanContext");   // TODO: more classes???
348    m_Properties.addAllowed(weka.gui.beans.Filter.class, "filter");
349    m_Properties.addAllowed(weka.gui.beans.Classifier.class, "wrappedAlgorithm");
350    m_Properties.addAllowed(weka.gui.beans.Clusterer.class, "wrappedAlgorithm");
351    m_Properties.addAllowed(weka.gui.beans.Classifier.class, "executionSlots");
352    m_Properties.addAllowed(weka.gui.beans.Classifier.class, "blockOnLastFold");
353
354    m_Properties.addAllowed(weka.classifiers.Classifier.class, "debug");
355    m_Properties.addAllowed(weka.classifiers.Classifier.class, "options");
356    m_Properties.addAllowed(weka.filters.Filter.class, "options");
357   
358    m_Properties.addAllowed(weka.core.converters.DatabaseSaver.class, "options");
359    m_Properties.addAllowed(weka.core.converters.DatabaseLoader.class, "options");
360    m_Properties.addAllowed(weka.core.converters.TextDirectoryLoader.class, "options");
361
362    // we assume that classes implementing SplitEvaluator also implement OptionHandler
363    m_Properties.addAllowed(weka.experiment.SplitEvaluator.class, "options");
364    // we assume that classes implementing ResultProducer also implement OptionHandler
365    m_Properties.addAllowed(weka.experiment.ResultProducer.class, "options");
366
367    // read/write methods
368    m_CustomMethods.register(this, Color.class, "Color");
369    m_CustomMethods.register(this, Dimension.class, "Dimension");
370    m_CustomMethods.register(this, Font.class, "Font");
371    m_CustomMethods.register(this, Point.class, "Point");
372    m_CustomMethods.register(this, ColorUIResource.class, "ColorUIResource");
373    m_CustomMethods.register(this, FontUIResource.class, "FontUIResource");
374
375    m_CustomMethods.register(this, weka.gui.beans.BeanInstance.class, "BeanInstance");
376    m_CustomMethods.register(this, weka.gui.beans.BeanConnection.class, "BeanConnection");
377    m_CustomMethods.register(this, weka.gui.beans.BeanVisual.class, "BeanVisual");
378    m_CustomMethods.register(this, weka.gui.beans.Saver.class, "BeanSaver");
379    m_CustomMethods.register(this, weka.gui.beans.MetaBean.class, "MetaBean");
380
381    classnames = ConverterUtils.getFileLoaders();
382    for (i = 0; i < classnames.size(); i++)
383      m_CustomMethods.register(this, Class.forName(classnames.get(i)), "Loader");
384    classnames = ConverterUtils.getFileSavers();
385    for (i = 0; i < classnames.size(); i++)
386      m_CustomMethods.register(this, Class.forName(classnames.get(i)), "Saver");
387   
388    // other variables
389    m_BeanInstances          = null;
390    m_BeanInstancesID        = null;
391    m_CurrentMetaBean        = null;
392    m_IgnoreBeanConnections  = true;
393    m_BeanConnectionRelation = null;
394  }
395 
396  /**
397   * traverses over all BeanInstances (or MetaBeans) and stores them in a vector
398   * (recurses into MetaBeans, since the sub-BeanInstances are not visible)
399   * @param list       the BeanInstances/MetaBeans to traverse
400   */
401  protected void addBeanInstances(Vector list) {
402    int             i;
403    BeanInstance    beaninst;
404   
405    for (i = 0; i < list.size(); i++) {
406      if (list.get(i) instanceof BeanInstance) {
407        beaninst = (BeanInstance) list.get(i);
408       
409        m_BeanInstancesID.add(new Integer(m_BeanInstances.size()));
410        m_BeanInstances.add(beaninst);
411       
412        if (beaninst.getBean() instanceof MetaBean)
413          addBeanInstances(((MetaBean) beaninst.getBean()).getBeansInSubFlow());
414      }
415      else if (list.get(i) instanceof MetaBean) {
416        addBeanInstances(((MetaBean) list.get(i)).getBeansInSubFlow());
417      }
418      else {
419        System.out.println("addBeanInstances does not support Vectors of class '" + list.get(i) + "'!");
420      }
421    }
422  }
423 
424  /**
425   * enables derived classes to due some pre-processing on the objects, that's
426   * about to be serialized. Right now it only returns the object.
427   *
428   * @param o the object that is serialized into XML
429   * @return the possibly altered object
430   * @throws Exception if post-processing fails
431   */
432  protected Object writePreProcess(Object o) throws Exception {
433    o = super.writePreProcess(o);
434   
435    // gather all BeanInstances, also the ones in MetaBeans
436    m_BeanInstances   = new Vector();
437    m_BeanInstancesID = new Vector();
438   
439    switch (getDataType()) {
440      case DATATYPE_LAYOUT:
441        addBeanInstances(BeanInstance.getBeanInstances());
442        break;
443
444      case DATATYPE_USERCOMPONENTS:
445        addBeanInstances((Vector) o);
446        break;
447       
448      default:
449        System.out.println("writePreProcess: data type '" + getDataType() + "' is not recognized!");
450        break;
451    }
452   
453    return o;
454  }
455 
456  /**
457   * enables derived classes to add other properties to the DOM tree, e.g.
458   * ones that do not apply to the get/set convention of beans. only implemented
459   * with empty method body.
460   *
461   * @param o the object that is serialized into XML
462   * @throws Exception if post-processing fails
463   */
464  protected void writePostProcess(Object o) throws Exception {
465    Element         root;
466    NodeList        list;
467    Element         conns;
468    Element         child;
469    int             i;
470
471    // since not all BeanConnections get saved to XML (e.g., MetaBeans in the
472    // UserToolBar) if one saves a layout, the numbering in the Vector of the
473    // BeanConnections is not correct. The "name" attribute of the nodes has
474    // to be modified
475    if (getDataType() == DATATYPE_LAYOUT) {
476      root  = m_Document.getDocument().getDocumentElement();
477      conns = (Element) root.getChildNodes().item(INDEX_BEANCONNECTIONS);
478      list  = conns.getChildNodes();
479      for (i = 0; i < list.getLength(); i++) {
480        child = (Element) list.item(i);
481        child.setAttribute(ATT_NAME, "" + i);
482      }
483    }
484  }
485 
486  /**
487   * additional pre-processing can happen in derived classes before the
488   * actual reading from XML (working on the raw XML). right now it does
489   * nothing with the document, only empties the help-vector for the
490   * BeanInstances and reads the IDs for the BeanInstances, s.t. the correct
491   * references can be set again
492   *
493   * @param document the document to pre-process
494   * @return the processed object
495   * @throws Exception if post-processing fails
496   * @see #m_BeanInstances
497   */
498  protected Document readPreProcess(Document document) throws Exception {
499    NodeList        list;
500    int             i;
501    Element         node;
502    String          clsName;
503    Vector          children;
504    int             id;
505    int             n;
506    Element         child;
507   
508    m_BeanInstances   = new Vector();
509    m_BeanInstancesID = new Vector();
510   
511    // get all BeanInstance nodes
512    list    = document.getElementsByTagName("*");
513    clsName = BeanInstance.class.getName();
514    for (i = 0; i < list.getLength(); i++) {
515      node = (Element) list.item(i);
516     
517      // is it a BeanInstance?
518      if (node.getAttribute(ATT_CLASS).equals(clsName)) {
519        children = XMLDocument.getChildTags(node);
520        id       = m_BeanInstancesID.size();
521       
522        // get id-tag (if available)
523        for (n = 0; n < children.size(); n++) {
524          child = (Element) children.get(n);
525          if (child.getAttribute(ATT_NAME).equals(VAL_ID))
526            id = readIntFromXML((Element) child);
527        }
528       
529        m_BeanInstancesID.add(new Integer(id));
530      }
531    }
532   
533    m_BeanInstances.setSize(m_BeanInstancesID.size());
534   
535    // set MetaBean to null
536    m_CurrentMetaBean = null;
537
538    // no BeanConnections -> see readPostProcess(Object)
539    m_IgnoreBeanConnections = true;
540   
541    // reset BeanConnection-Relations
542    m_BeanConnectionRelation = new Hashtable();
543   
544    return document;
545  }
546 
547  /**
548   * puts the given BeanConnection onto the next null in the given Vector,
549   * or at the end of the list, if no null is found.
550   * (during the de-serializing, no BeanConnections are set, only nulls)
551   * @param conn      the connection to add to the list
552   * @param list      the list to add the BeanConnection to
553   */
554  protected void setBeanConnection(BeanConnection conn, Vector list) {
555    int         i;
556    boolean     added;
557   
558    added = false;
559    for (i = 0; i < list.size(); i++) {
560      if (list.get(i) == null) {
561        list.set(i, conn);
562        added = true;
563        break;
564      }
565    }
566   
567    if (!added)
568      list.add(conn);
569  }
570 
571  /**
572   * generates a connection based on the given parameters
573   * @param sourcePos the source position in the m_BeanInstances vector
574   * @param targetPos the target position in the m_BeanInstances vector
575   * @param event the name of the event, i.e., the connection
576   * @param hidden true if the connection is hidden
577   * @return the generated BeanConnection
578   * @throws Exception if something goes wrong
579   */
580  protected BeanConnection createBeanConnection(int sourcePos, int targetPos, String event, boolean hidden) throws Exception {
581    BeanConnection          result;
582    BeanInfo                compInfo;
583    EventSetDescriptor[]    esds;
584    int                     i;
585    BeanInstance            instSource;
586    BeanInstance            instTarget;
587
588    result = null;
589   
590    // was there a connection?
591    if ( (sourcePos == -1) || (targetPos == -1) )
592      return result;
593   
594    instSource = (BeanInstance) m_BeanInstances.get(sourcePos);
595    instTarget = (BeanInstance) m_BeanInstances.get(targetPos);
596   
597    compInfo = Introspector.getBeanInfo(((BeanInstance) m_BeanInstances.get(sourcePos)).getBean().getClass());
598    esds     = compInfo.getEventSetDescriptors();
599
600    for (i = 0; i < esds.length; i++) {
601      if (esds[i].getName().equals(event)) {
602        result = new BeanConnection(instSource, instTarget, esds[i]);
603        ((BeanConnection) result).setHidden(hidden);
604        break;
605      }
606    }
607   
608    return result;
609  }
610 
611  /**
612   * rebuilds all the connections for a certain key in the hashtable.
613   * for the ones being part of a MetaBean, no new instance is built, but only
614   * the reference to the actual BeanConnection set.
615   * @param deserialized    the deserialized knowledgeflow
616   * @param key             the key of the hashtable to rebuild all connections for
617   * @throws Exception if something goes wrong
618   */
619  protected void rebuildBeanConnections(Vector deserialized, Object key) throws Exception {
620    int                     i;
621    int                     n;
622    int                     sourcePos;
623    int                     targetPos;
624    String                  event;
625    boolean                 hidden;
626    Vector                  conns;
627    BeanConnection          conn;
628    StringTokenizer         tok;
629    Vector                  beanconns;
630
631    conns = (Vector) m_BeanConnectionRelation.get(key);
632   
633    // no connections?
634    if (conns == null)
635      return;
636   
637    for (n = 0; n < conns.size(); n++) {
638      tok       = new StringTokenizer(conns.get(n).toString(), ",");
639      conn      = null;
640      sourcePos = Integer.parseInt(tok.nextToken());
641      targetPos = Integer.parseInt(tok.nextToken());
642      event     = tok.nextToken();
643      hidden    = stringToBoolean(tok.nextToken());
644
645      // regular connection? -> new instance
646      // or MetaBean from user toolbar
647      if ( (!(key instanceof MetaBean)) || (getDataType() == DATATYPE_USERCOMPONENTS)) {
648        conn = createBeanConnection(sourcePos, targetPos, event, hidden);
649      }
650      // MetaBean? -> find BeanConnection
651      else {
652        beanconns = BeanConnection.getConnections();
653       
654        for (i = 0; i < beanconns.size(); i++) {
655          conn = (BeanConnection) beanconns.get(i);
656          if (    (conn.getSource() == (BeanInstance) m_BeanInstances.get(sourcePos))
657               && (conn.getTarget() == (BeanInstance) m_BeanInstances.get(targetPos))
658               && (conn.getEventName().equals(event)) ) {
659            break;
660          }
661          conn = null;
662        }
663      }
664     
665      // add the connection to the corresponding list/MetaBean
666      if (key instanceof MetaBean)
667        setBeanConnection(conn, ((MetaBean) key).getAssociatedConnections());
668      else
669        setBeanConnection(conn, (Vector) deserialized.get(INDEX_BEANCONNECTIONS));
670    }
671  }
672 
673  /**
674   * removes the given meta beans from the layout, since they're only listed
675   * in the user toolbar
676   *
677   * @param metabeans         the list of MetaBeans in the user toolbar
678   */
679  protected void removeUserToolBarBeans(Vector metabeans) {
680    int           i;
681    int           n;
682    MetaBean      meta;
683    Vector        subflow;
684    BeanInstance  beaninst;
685   
686    for (i = 0; i < metabeans.size(); i++) {
687      meta    = (MetaBean) metabeans.get(i);
688      subflow = meta.getSubFlow();
689     
690      for (n = 0; n < subflow.size(); n++) {
691        beaninst = (BeanInstance) subflow.get(n);
692        beaninst.removeBean(m_BeanLayout);
693      }
694    }
695  }
696 
697  /**
698   * additional post-processing can happen in derived classes after reading
699   * from XML. re-builds the BeanConnections.
700   *
701   * @param o the object to perform some additional processing on
702   * @return the processed object
703   * @throws Exception if post-processing fails
704   */
705  protected Object readPostProcess(Object o) throws Exception {
706    Enumeration             enm;
707    Vector                  deserialized;
708    Object                  key;
709
710    deserialized = (Vector) super.readPostProcess(o);
711   
712    // rebuild the actual connections
713    rebuildBeanConnections(deserialized, REGULAR_CONNECTION);
714
715    // rebuild the references in the MetaBeans
716    enm = m_BeanConnectionRelation.keys();
717    while (enm.hasMoreElements()) {
718      key = enm.nextElement();
719     
720      // skip the regular connections
721      if (!(key instanceof MetaBean))
722        continue;
723     
724      rebuildBeanConnections(deserialized, key);
725    }
726
727    // remove MetaBean and subflow from BeanInstance (not part of the flow!)
728    if (getDataType() == DATATYPE_USERCOMPONENTS)
729      removeUserToolBarBeans(deserialized);
730   
731    return deserialized;
732  }
733
734  /**
735   * returns the relation for the given MetaBean, for the regular connections,
736   * null has to be used
737   * @param meta      the MetaBean (or null for regular connections) to retrieve
738   *                  the connections for
739   * @return          the associated connections
740   * @see #REGULAR_CONNECTION
741   */
742  protected Vector getBeanConnectionRelation(MetaBean meta) {
743    Vector      result;
744    Object      key;
745   
746    if (meta == null)
747      key = REGULAR_CONNECTION;
748    else
749      key = meta;
750   
751    // not yet in there?
752    if (!m_BeanConnectionRelation.containsKey(key)) {
753      m_BeanConnectionRelation.put(key, new Vector());
754    }
755
756    result = (Vector) m_BeanConnectionRelation.get(key);
757   
758    return result;
759  }
760 
761  /**
762   * adds the given connection-relation for the specified MetaBean (or null in
763   * case of regular connections)
764   * @param meta        the MetaBean (or null for regular connections) to add
765   *                    the relationship for
766   * @param connection  the connection relation to add
767   */
768  protected void addBeanConnectionRelation(MetaBean meta, String connection) {
769    Vector      relations;
770    Object      key;
771   
772    relations = getBeanConnectionRelation(meta);
773   
774    // add relation
775    relations.add(connection);
776   
777    // update
778    if (meta == null)
779      key = REGULAR_CONNECTION;
780    else
781      key = meta;
782    m_BeanConnectionRelation.put(key, relations);
783  }
784 
785  /**
786   * adds the given Color to a DOM structure.
787   *
788   * @param parent the parent of this object, e.g. the class this object is a member of
789   * @param o the Object to describe in XML
790   * @param name the name of the object
791   * @return the node that was created
792   * @throws Exception if the DOM creation fails
793   */
794  public Element writeColor(Element parent, Object o, String name)
795    throws Exception {
796   
797    Element     node;
798    Color       color;
799
800    // for debugging only
801    if (DEBUG)
802       trace(new Throwable(), name);
803   
804    m_CurrentNode = parent;
805   
806    color = (Color) o;
807    node  = addElement(parent, name, color.getClass().getName(), false);
808
809    writeIntToXML(node, color.getRed(), VAL_RED);
810    writeIntToXML(node, color.getGreen(), VAL_GREEN);
811    writeIntToXML(node, color.getBlue(), VAL_BLUE);
812   
813    return node;
814  }
815
816  /**
817   * builds the Color from the given DOM node.
818   *
819   * @param node the associated XML node
820   * @return the instance created from the XML description
821   * @throws Exception if instantiation fails
822   */
823  public Object readColor(Element node) throws Exception {
824    Object      result;
825    Vector      children;
826    Element     child;
827    int         i;
828    int         red;
829    int         green;
830    int         blue;
831    String      name;
832
833    // for debugging only
834    if (DEBUG)
835       trace(new Throwable(), node.getAttribute(ATT_NAME));
836
837    m_CurrentNode = node;
838   
839    result   = null;
840    children = XMLDocument.getChildTags(node);
841    red      = 0;
842    green    = 0;
843    blue     = 0;
844
845    for (i = 0; i < children.size(); i++) {
846      child = (Element) children.get(i);
847      name  = child.getAttribute(ATT_NAME);
848
849      if (name.equals(VAL_RED))
850        red = readIntFromXML(child);
851      else if (name.equals(VAL_GREEN))
852        green = readIntFromXML(child);
853      else if (name.equals(VAL_BLUE))
854        blue = readIntFromXML(child);
855      else
856        System.out.println("WARNING: '" + name
857            + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!");
858    }
859   
860    result = new Color(red, green, blue);
861
862    return result;
863  }
864
865  /**
866   * adds the given Dimension to a DOM structure.
867   *
868   * @param parent the parent of this object, e.g. the class this object is a member of
869   * @param o the Object to describe in XML
870   * @param name the name of the object
871   * @return the node that was created
872   * @throws Exception if the DOM creation fails
873   */
874  public Element writeDimension(Element parent, Object o, String name)
875      throws Exception {
876   
877    Element     node;
878    Dimension   dim;
879
880    // for debugging only
881    if (DEBUG)
882       trace(new Throwable(), name);
883   
884    m_CurrentNode = parent;
885   
886    dim = (Dimension) o;
887    node = addElement(parent, name, dim.getClass().getName(), false);
888
889    writeDoubleToXML(node, dim.getWidth(), VAL_WIDTH);
890    writeDoubleToXML(node, dim.getHeight(), VAL_HEIGHT);
891   
892    return node;
893  }
894
895  /**
896   * builds the Dimension from the given DOM node.
897   *
898   * @param node the associated XML node
899   * @return the instance created from the XML description
900   * @throws Exception if instantiation fails
901   */
902  public Object readDimension(Element node) throws Exception {
903    Object      result;
904    Vector      children;
905    Element     child;
906    int         i;
907    double      width;
908    double      height;
909    String      name;
910
911    // for debugging only
912    if (DEBUG)
913       trace(new Throwable(), node.getAttribute(ATT_NAME));
914
915    m_CurrentNode = node;
916   
917    result   = null;
918    children = XMLDocument.getChildTags(node);
919    width    = 0;
920    height   = 0;
921
922    for (i = 0; i < children.size(); i++) {
923      child = (Element) children.get(i);
924      name  = child.getAttribute(ATT_NAME);
925
926      if (name.equals(VAL_WIDTH))
927        width = readDoubleFromXML(child);
928      else if (name.equals(VAL_HEIGHT))
929        height = readDoubleFromXML(child);
930      else
931        System.out.println("WARNING: '" + name
932            + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!");
933    }
934   
935    result = new Dimension();
936    ((Dimension) result).setSize(width, height);
937
938    return result;
939  }
940
941  /**
942   * adds the given Font to a DOM structure.
943   *
944   * @param parent the parent of this object, e.g. the class this object is a member of
945   * @param o the Object to describe in XML
946   * @param name the name of the object
947   * @return the node that was created
948   * @throws Exception if the DOM creation fails
949   */
950  public Element writeFont(Element parent, Object o, String name)
951      throws Exception {
952   
953    Element     node;
954    Font        font;
955
956    // for debugging only
957    if (DEBUG)
958       trace(new Throwable(), name);
959   
960    m_CurrentNode = parent;
961   
962    font = (Font) o;
963    node = addElement(parent, name, font.getClass().getName(), false);
964
965    invokeWriteToXML(node, font.getName(), VAL_NAME);
966    writeIntToXML(node, font.getStyle(), VAL_STYLE);
967    writeIntToXML(node, font.getSize(), VAL_SIZE);
968   
969    return node;
970  }
971
972  /**
973   * builds the Font from the given DOM node.
974   *
975   * @param node the associated XML node
976   * @return the instance created from the XML description
977   * @throws Exception if instantiation fails
978   */
979  public Object readFont(Element node) throws Exception {
980    Object      result;
981    Vector      children;
982    Element     child;
983    int         i;
984    int         style;
985    int         size;
986    String      name;
987    String      fontname;
988
989    // for debugging only
990    if (DEBUG)
991       trace(new Throwable(), node.getAttribute(ATT_NAME));
992
993    m_CurrentNode = node;
994   
995    result   = null;
996    children = XMLDocument.getChildTags(node);
997    fontname = "";
998    style    = 0;
999    size     = 0;
1000
1001    for (i = 0; i < children.size(); i++) {
1002      child = (Element) children.get(i);
1003      name  = child.getAttribute(ATT_NAME);
1004
1005      if (name.equals(VAL_NAME))
1006        name = (String) invokeReadFromXML(child);
1007      else if (name.equals(VAL_STYLE))
1008        style = readIntFromXML(child);
1009      else if (name.equals(VAL_SIZE))
1010        size = readIntFromXML(child);
1011      else
1012        System.out.println("WARNING: '" + name
1013            + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!");
1014    }
1015   
1016    result = new Font(fontname, style, size);
1017
1018    return result;
1019  }
1020
1021  /**
1022   * adds the given Point to a DOM structure.
1023   *
1024   * @param parent the parent of this object, e.g. the class this object is a member of
1025   * @param o the Object to describe in XML
1026   * @param name the name of the object
1027   * @return the node that was created
1028   * @throws Exception if the DOM creation fails
1029   */
1030  public Element writePoint(Element parent, Object o, String name)
1031      throws Exception {
1032   
1033    Element     node;
1034    Point       p;
1035
1036    // for debugging only
1037    if (DEBUG)
1038       trace(new Throwable(), name);
1039   
1040    m_CurrentNode = parent;
1041   
1042    p    = (Point) o;
1043    node = addElement(parent, name, p.getClass().getName(), false);
1044
1045    writeDoubleToXML(node, p.getX(), VAL_X);
1046    writeDoubleToXML(node, p.getY(), VAL_Y);
1047   
1048    return node;
1049  }
1050
1051  /**
1052   * builds the Point from the given DOM node.
1053   *
1054   * @param node the associated XML node
1055   * @return the instance created from the XML description
1056   * @throws Exception if instantiation fails
1057   */
1058  public Object readPoint(Element node) throws Exception {
1059    Object      result;
1060    Vector      children;
1061    Element     child;
1062    int         i;
1063    double      x;
1064    double      y;
1065    String      name;
1066
1067    // for debugging only
1068    if (DEBUG)
1069       trace(new Throwable(), node.getAttribute(ATT_NAME));
1070
1071    m_CurrentNode = node;
1072   
1073    result   = null;
1074    children = XMLDocument.getChildTags(node);
1075    x        = 0;
1076    y        = 0;
1077
1078    for (i = 0; i < children.size(); i++) {
1079      child = (Element) children.get(i);
1080      name  = child.getAttribute(ATT_NAME);
1081
1082      if (name.equals(VAL_X))
1083        x = readDoubleFromXML(child);
1084      else if (name.equals(VAL_Y))
1085        y = readDoubleFromXML(child);
1086      else
1087        System.out.println("WARNING: '" + name
1088            + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!");
1089    }
1090   
1091    result = new Point();
1092    ((Point) result).setLocation(x, y);
1093
1094    return result;
1095  }
1096
1097  /**
1098   * adds the given ColorUIResource to a DOM structure.
1099   *
1100   * @param parent the parent of this object, e.g. the class this object is a member of
1101   * @param o the Object to describe in XML
1102   * @param name the name of the object
1103   * @return the node that was created
1104   * @throws Exception if the DOM creation fails
1105   */
1106  public Element writeColorUIResource(Element parent, Object o, String name)
1107      throws Exception {
1108   
1109    Element           node;
1110    ColorUIResource   resource;
1111
1112    // for debugging only
1113    if (DEBUG)
1114       trace(new Throwable(), name);
1115   
1116    m_CurrentNode = parent;
1117   
1118    resource = (ColorUIResource) o;
1119    node     = addElement(parent, name, resource.getClass().getName(), false);
1120    invokeWriteToXML(node, new Color(resource.getRGB()), VAL_COLOR);
1121   
1122    return node;
1123  }
1124
1125  /**
1126   * builds the ColorUIResource from the given DOM node.
1127   *
1128   * @param node the associated XML node
1129   * @return the instance created from the XML description
1130   * @throws Exception if instantiation fails
1131   */
1132  public Object readColorUIResource(Element node) throws Exception {
1133    Object      result;
1134    Vector      children;
1135    Element     child;
1136    int         i;
1137    String      name;
1138    Color       color;
1139
1140    // for debugging only
1141    if (DEBUG)
1142       trace(new Throwable(), node.getAttribute(ATT_NAME));
1143
1144    m_CurrentNode = node;
1145   
1146    result   = null;
1147    children = XMLDocument.getChildTags(node);
1148    color    = null;
1149
1150    for (i = 0; i < children.size(); i++) {
1151      child = (Element) children.get(i);
1152      name  = child.getAttribute(ATT_NAME);
1153
1154      if (name.equals(VAL_COLOR))
1155        color = (Color) invokeReadFromXML(child);
1156      else
1157        System.out.println("WARNING: '" + name
1158            + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!");
1159    }
1160   
1161    result = new ColorUIResource(color);
1162
1163    return result;
1164  }
1165
1166  /**
1167   * adds the given FontUIResource to a DOM structure.
1168   *
1169   * @param parent the parent of this object, e.g. the class this object is a member of
1170   * @param o the Object to describe in XML
1171   * @param name the name of the object
1172   * @return the node that was created
1173   * @throws Exception if the DOM creation fails
1174   */
1175  public Element writeFontUIResource(Element parent, Object o, String name)
1176      throws Exception {
1177   
1178    Element           node;
1179    FontUIResource    resource;
1180
1181    // for debugging only
1182    if (DEBUG)
1183       trace(new Throwable(), name);
1184   
1185    m_CurrentNode = parent;
1186   
1187    resource = (FontUIResource) o;
1188    node     = addElement(parent, name, resource.getClass().getName(), false);
1189    invokeWriteToXML(node, new Font(resource.getName(), resource.getStyle(), resource.getSize()), VAL_COLOR);
1190   
1191    return node;
1192  }
1193
1194  /**
1195   * builds the FontUIResource from the given DOM node.
1196   *
1197   * @param node the associated XML node
1198   * @return the instance created from the XML description
1199   * @throws Exception if instantiation fails
1200   */
1201  public Object readFontUIResource(Element node) throws Exception {
1202    Object      result;
1203    Vector      children;
1204    Element     child;
1205    int         i;
1206    String      name;
1207    Font        font;
1208
1209    // for debugging only
1210    if (DEBUG)
1211       trace(new Throwable(), node.getAttribute(ATT_NAME));
1212
1213    m_CurrentNode = node;
1214   
1215    result   = null;
1216    children = XMLDocument.getChildTags(node);
1217    font     = null;
1218
1219    for (i = 0; i < children.size(); i++) {
1220      child = (Element) children.get(i);
1221      name  = child.getAttribute(ATT_NAME);
1222
1223      if (name.equals(VAL_FONT))
1224        font = (Font) invokeReadFromXML(child);
1225      else
1226        System.out.println("WARNING: '" + name
1227            + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!");
1228    }
1229   
1230    result = new FontUIResource(font);
1231
1232    return result;
1233  }
1234
1235  /**
1236   * adds the given BeanInstance to a DOM structure.
1237   *
1238   * @param parent the parent of this object, e.g. the class this object is a member of
1239   * @param o the Object to describe in XML
1240   * @param name the name of the object
1241   * @return the node that was created
1242   * @throws Exception if the DOM creation fails
1243   */
1244  public Element writeBeanInstance(Element parent, Object o, String name)
1245      throws Exception {
1246   
1247    Element         node;
1248    BeanInstance    beaninst;
1249
1250    // for debugging only
1251    if (DEBUG)
1252       trace(new Throwable(), name);
1253   
1254    m_CurrentNode = parent;
1255   
1256    beaninst = (BeanInstance) o;
1257    node     = addElement(parent, name, beaninst.getClass().getName(), false);
1258
1259    writeIntToXML(node, m_BeanInstances.indexOf(beaninst), VAL_ID);
1260    writeIntToXML(node, beaninst.getX() + beaninst.getWidth()  / 2, VAL_X);   // x is thought to be in the center?
1261    writeIntToXML(node, beaninst.getY() + beaninst.getHeight() / 2, VAL_Y);   // y is thought to be in the center?
1262    if (beaninst.getBean() instanceof BeanCommon) {
1263      // write the custom name of this bean
1264      String custName = ((BeanCommon)beaninst.getBean()).getCustomName();
1265      invokeWriteToXML(node, custName, VAL_CUSTOM_NAME);
1266    }
1267    invokeWriteToXML(node, beaninst.getBean(), VAL_BEAN);
1268   
1269    return node;
1270  }
1271
1272  /**
1273   * builds the BeanInstance from the given DOM node.
1274   *
1275   * @param node the associated XML node
1276   * @return the instance created from the XML description
1277   * @throws Exception if instantiation fails
1278   */
1279  public Object readBeanInstance(Element node) throws Exception {
1280    Object          result;
1281    Vector          children;
1282    Element         child;
1283    String          name;
1284    int             i;
1285    int             x;
1286    int             y;
1287    int             id;
1288    Object          bean;
1289    BeanVisual      visual;
1290    BeanInstance    beaninst;
1291
1292    // for debugging only
1293    if (DEBUG)
1294       trace(new Throwable(), node.getAttribute(ATT_NAME));
1295
1296    m_CurrentNode = node;
1297   
1298    result   = null;
1299    children = XMLDocument.getChildTags(node);
1300    id       = -1;
1301    x        = 0;
1302    y        = 0;
1303    bean     = null;
1304    String customName = null;
1305
1306    for (i = 0; i < children.size(); i++) {
1307      child = (Element) children.get(i);
1308      name  = child.getAttribute(ATT_NAME);
1309
1310      if (name.equals(VAL_ID)) {
1311        id = readIntFromXML(child);
1312      } else if (name.equals(VAL_X)) {
1313        x = readIntFromXML(child);
1314      } else if (name.equals(VAL_Y)) {
1315        y = readIntFromXML(child);
1316      } else if (name.equals(VAL_CUSTOM_NAME)) {
1317        customName = (String)invokeReadFromXML(child);
1318      } else if (name.equals(VAL_BEAN)) {
1319        bean = invokeReadFromXML(child);
1320      } else {
1321        System.out.println("WARNING: '" + name
1322            + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!");
1323      }
1324    }
1325   
1326    result   = new BeanInstance(m_BeanLayout, bean, x, y);
1327    beaninst = (BeanInstance) result;
1328   
1329    // set parent of BeanVisual
1330    if (beaninst.getBean() instanceof weka.gui.beans.Visible) {
1331      visual = ((Visible) beaninst.getBean()).getVisual();
1332      visual.setSize(visual.getPreferredSize());
1333      if (visual.getParent() == null) {
1334        ((JPanel) beaninst.getBean()).add(visual);
1335      }
1336    }
1337
1338    if (beaninst.getBean() instanceof BeanCommon &&
1339        customName != null) {
1340      ((BeanCommon)beaninst.getBean()).setCustomName(customName);
1341    }
1342   
1343    // no IDs -> get next null position
1344    if (id == -1) {
1345      for (i = 0; i < m_BeanInstances.size(); i++) {
1346        if (m_BeanInstances.get(i) == null) {
1347          id = ((Integer) m_BeanInstancesID.get(i)).intValue();
1348          break;
1349        }
1350      }
1351    }
1352    // get position for id
1353    i = m_BeanInstancesID.indexOf(new Integer(id));
1354
1355    // keep track of the BeanInstances for reading the connections later on
1356    m_BeanInstances.set(i, result);
1357
1358    // no current MetaBean
1359    m_CurrentMetaBean = null;
1360   
1361    return result;
1362  }
1363
1364  /**
1365   * adds the given BeanConncetion to a DOM structure.
1366   *
1367   * @param parent the parent of this object, e.g. the class this object is a member of
1368   * @param o the Object to describe in XML
1369   * @param name the name of the object
1370   * @return the node that was created
1371   * @throws Exception if the DOM creation fails
1372   */
1373  public Element writeBeanConnection(Element parent, Object o, String name)
1374    throws Exception {
1375   
1376    Element           node;
1377    BeanConnection    beanconn;
1378    int               source;
1379    int               target;
1380    int               sourcePos;
1381    int               targetPos;
1382
1383    // for debugging only
1384    if (DEBUG)
1385       trace(new Throwable(), name);
1386   
1387    m_CurrentNode = parent;
1388   
1389    beanconn = (BeanConnection) o;
1390    node     = null;
1391
1392    // get position
1393    sourcePos = m_BeanInstances.indexOf(beanconn.getSource());
1394    targetPos = m_BeanInstances.indexOf(beanconn.getTarget());
1395   
1396    // get id (if Connection is from a Bean in the UserToolBar, it's not listed! -> ignore it)
1397    if ( (sourcePos > -1) && (targetPos > -1) ) {
1398      source = ((Integer) m_BeanInstancesID.get(sourcePos)).intValue();
1399      target = ((Integer) m_BeanInstancesID.get(targetPos)).intValue();
1400    }
1401    else {
1402       source = -1;
1403       target = -1;
1404    }
1405   
1406    // connection exists in the layout?
1407    if ( (source > -1) && (target > -1) ) {
1408      node = addElement(parent, name, beanconn.getClass().getName(), false);
1409 
1410      writeIntToXML(node, source, VAL_SOURCEID);
1411      writeIntToXML(node, target, VAL_TARGETID);
1412      invokeWriteToXML(node, beanconn.getEventName(), VAL_EVENTNAME);
1413      writeBooleanToXML(node, beanconn.isHidden(), VAL_HIDDEN);
1414    }
1415   
1416    return node;
1417  }
1418
1419  /**
1420   * builds the BeanConnection from the given DOM node.
1421   *
1422   * @param node the associated XML node
1423   * @return the instance created from the XML description
1424   * @throws Exception if instantiation fails
1425   */
1426  public Object readBeanConnection(Element node) throws Exception {
1427    Object                  result;
1428    Vector                  children;
1429    Element                 child;
1430    String                  name;
1431    int                     i;
1432    int                     source;
1433    int                     target;
1434    int                     sourcePos;
1435    int                     targetPos;
1436    String                  event;
1437    boolean                 hidden;
1438
1439    // for debugging only
1440    if (DEBUG)
1441       trace(new Throwable(), node.getAttribute(ATT_NAME));
1442
1443    m_CurrentNode = node;
1444   
1445    result   = null;
1446    children = XMLDocument.getChildTags(node);
1447    source   = 0;
1448    target   = 0;
1449    event    = "";
1450    hidden   = false;
1451
1452    for (i = 0; i < children.size(); i++) {
1453      child = (Element) children.get(i);
1454      name  = child.getAttribute(ATT_NAME);
1455
1456      if (name.equals(VAL_SOURCEID))
1457        source = readIntFromXML(child);
1458      else if (name.equals(VAL_TARGETID))
1459        target = readIntFromXML(child);
1460      else if (name.equals(VAL_EVENTNAME))
1461        event = (String) invokeReadFromXML(child);
1462      else if (name.equals(VAL_HIDDEN))
1463        hidden = readBooleanFromXML(child);
1464      else
1465        System.out.println("WARNING: '" + name
1466            + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!");
1467    }
1468
1469    // get position of id
1470    sourcePos = m_BeanInstancesID.indexOf(new Integer(source));
1471    targetPos = m_BeanInstancesID.indexOf(new Integer(target));
1472   
1473    // do we currently ignore the connections?
1474    // Note: necessary because of the MetaBeans
1475    if (m_IgnoreBeanConnections) {
1476      addBeanConnectionRelation(m_CurrentMetaBean, sourcePos + "," + targetPos + "," + event + "," + hidden);
1477      return result;
1478    }
1479
1480    // generate it normally
1481    result = createBeanConnection(sourcePos, targetPos, event, hidden);
1482
1483    return result;
1484  }
1485 
1486  /**
1487   * adds the given Loader (a bean) to a DOM structure.
1488   *
1489   * @param parent the parent of this object, e.g. the class this object is a member of
1490   * @param o the Object to describe in XML
1491   * @param name the name of the object
1492   * @return the node that was created
1493   * @throws Exception if the DOM creation fails
1494   */
1495  public Element writeBeanLoader(Element parent, Object o, String name)
1496      throws Exception {
1497   
1498    Element                 node;
1499    weka.gui.beans.Loader   loader;
1500
1501    // for debugging only
1502    if (DEBUG)
1503       trace(new Throwable(), name);
1504   
1505    m_CurrentNode = parent;
1506   
1507    loader = (weka.gui.beans.Loader) o;
1508    node   = addElement(parent, name, loader.getClass().getName(), false);
1509
1510    invokeWriteToXML(node, loader.getLoader(), VAL_LOADER);
1511    invokeWriteToXML(node, loader.getBeanContext(), VAL_BEANCONTEXT);
1512   
1513    return node;
1514  }
1515
1516  /**
1517   * adds the given Saver (a bean) to a DOM structure.
1518   *
1519   * @param parent the parent of this object, e.g. the class this object is a member of
1520   * @param o the Object to describe in XML
1521   * @param name the name of the object
1522   * @return the node that was created
1523   * @throws Exception if the DOM creation fails
1524   */
1525  public Element writeBeanSaver(Element parent, Object o, String name)
1526      throws Exception {
1527   
1528    Element                 node;
1529    weka.gui.beans.Saver    saver;
1530
1531    // for debugging only
1532    if (DEBUG)
1533       trace(new Throwable(), name);
1534   
1535    m_CurrentNode = parent;
1536   
1537    saver = (weka.gui.beans.Saver) o;
1538    node   = addElement(parent, name, saver.getClass().getName(), false);
1539    invokeWriteToXML(node, saver.getRelationNameForFilename(), VAL_RELATIONNAMEFORFILENAME);
1540
1541    invokeWriteToXML(node, saver.getSaver(), VAL_SAVER);
1542   
1543    return node;
1544  }
1545 
1546  /**
1547   * adds the given Loader to a DOM structure.
1548   *
1549   * @param parent the parent of this object, e.g. the class this object is a member of
1550   * @param o the Object to describe in XML
1551   * @param name the name of the object
1552   * @return the node that was created
1553   * @throws Exception if the DOM creation fails
1554   */
1555  public Element writeLoader(Element parent, Object o, String name)
1556      throws Exception {
1557   
1558    Element                       node;
1559    weka.core.converters.Loader   loader;
1560    File                          file;
1561    boolean                       known;
1562
1563    // for debugging only
1564    if (DEBUG)
1565       trace(new Throwable(), name);
1566   
1567    m_CurrentNode = parent;
1568   
1569    loader = (weka.core.converters.Loader) o;
1570    node   = addElement(parent, name, loader.getClass().getName(), false);
1571    known  = true;
1572    file   = null;
1573
1574    // file
1575    if (loader instanceof weka.core.converters.AbstractFileLoader)
1576      file = ((weka.core.converters.AbstractFileLoader) loader).retrieveFile();
1577    else
1578      known = false;
1579
1580    if (!known)
1581      System.out.println("WARNING: unknown loader class '" + loader.getClass().getName() + "' - cannot retrieve file!");
1582
1583    Boolean relativeB = null;
1584    if (loader instanceof weka.core.converters.FileSourcedConverter) {
1585      boolean relative = ((weka.core.converters.FileSourcedConverter)loader).getUseRelativePath();
1586      relativeB = new Boolean(relative);
1587    }
1588   
1589    // only save it, if it's a real file!
1590    if ( (file == null) || (file.isDirectory()) ) {
1591      invokeWriteToXML(node, "", VAL_FILE);
1592    } else {
1593      boolean notAbsolute = 
1594        (((weka.core.converters.AbstractFileLoader) loader).getUseRelativePath() ||
1595        (loader instanceof EnvironmentHandler
1596            && Environment.containsEnvVariables(file.getPath())));
1597     
1598      String path = (notAbsolute)
1599        ? file.getPath()
1600        : file.getAbsolutePath();
1601      // Replace any windows file separators with forward slashes (Java under windows can
1602      // read paths with forward slashes (apparantly)
1603      path = path.replace('\\', '/');
1604      invokeWriteToXML(node, path, VAL_FILE);
1605    }
1606    if (relativeB != null) {
1607      invokeWriteToXML(node, relativeB.toString(), VAL_RELATIVE_PATH);
1608    }
1609   
1610    return node;
1611  }
1612
1613  /**
1614   * builds the Loader from the given DOM node.
1615   *
1616   * @param node the associated XML node
1617   * @return the instance created from the XML description
1618   * @throws Exception if instantiation fails
1619   */
1620  public Object readLoader(Element node) throws Exception {
1621    Object      result;
1622    Vector      children;
1623    Element     child;
1624    int         i;
1625    String      name;
1626    String      file;
1627    File        fl;
1628
1629    // for debugging only
1630    if (DEBUG)
1631       trace(new Throwable(), node.getAttribute(ATT_NAME));
1632
1633    m_CurrentNode = node;
1634   
1635    result   = Class.forName(node.getAttribute(ATT_CLASS)).newInstance();
1636    children = XMLDocument.getChildTags(node);
1637    file     = "";
1638    Object relativeB = null;
1639    boolean relative = false;
1640
1641    for (i = 0; i < children.size(); i++) {
1642      child = (Element) children.get(i);
1643      name  = child.getAttribute(ATT_NAME);
1644
1645      if (name.equals(VAL_FILE)) {
1646        file = (String) invokeReadFromXML(child);
1647      } else if (name.equals(VAL_RELATIVE_PATH)) {
1648        relativeB = readFromXML(child);
1649        if (relativeB instanceof Boolean) {
1650          relative = ((Boolean)relativeB).booleanValue();
1651        }
1652      } else {
1653        readFromXML(result, name, child);
1654      }
1655    }
1656
1657    if (result instanceof weka.core.converters.FileSourcedConverter) {
1658      ((weka.core.converters.FileSourcedConverter)result).setUseRelativePath(relative);
1659    }
1660
1661    if (file.equals(""))
1662      file = null;
1663
1664    // set file only, if it exists
1665    if (file != null) {
1666      String tempFile = file;
1667
1668      boolean containsEnv = false;
1669      containsEnv = Environment.containsEnvVariables(file);
1670     
1671      fl = new File(file);     
1672      // only test for existence if the path does not contain environment vars
1673      // (trust that after they are resolved that everything is hunky dory)
1674      if (containsEnv || fl.exists()) {
1675        ((weka.core.converters.AbstractFileLoader) result).setSource(new File(file));
1676      } else {
1677        System.out.println("WARNING: The file '" + tempFile + "' does not exist!");
1678      }
1679    }
1680   
1681    return result;
1682  }
1683
1684  /**
1685   * adds the given Saver to a DOM structure.
1686   *
1687   * @param parent the parent of this object, e.g. the class this object is a member of
1688   * @param o the Object to describe in XML
1689   * @param name the name of the object
1690   * @return the node that was created
1691   * @throws Exception if the DOM creation fails
1692   */
1693  public Element writeSaver(Element parent, Object o, String name)
1694      throws Exception {
1695   
1696    Element                     node;
1697    weka.core.converters.Saver  saver;
1698    File                        file;
1699    String                      prefix;
1700    String                      dir;
1701    boolean                     known;
1702
1703    // for debugging only
1704    if (DEBUG)
1705       trace(new Throwable(), name);
1706   
1707    m_CurrentNode = parent;
1708   
1709    saver  = (weka.core.converters.Saver) o;
1710    node   = addElement(parent, name, saver.getClass().getName(), false);
1711    known  = true;
1712    file   = null;
1713    prefix = "";
1714    dir    = "";
1715
1716    // file
1717    if (saver instanceof weka.core.converters.AbstractFileSaver) {
1718      file   = ((weka.core.converters.AbstractFileSaver) saver).retrieveFile();
1719      prefix = ((weka.core.converters.AbstractFileSaver) saver).filePrefix();
1720      dir    = ((weka.core.converters.AbstractFileSaver) saver).retrieveDir();
1721      // Replace any windows file separators with forward slashes (Java under windows can
1722      // read paths with forward slashes (apparantly)
1723      dir = dir.replace('\\', '/');
1724    }
1725    else {
1726      known = false;
1727    }
1728   
1729    if (!known)
1730      System.out.println("WARNING: unknown saver class '" + saver.getClass().getName() + "' - cannot retrieve file!");
1731
1732    Boolean relativeB = null;
1733    if (saver instanceof weka.core.converters.FileSourcedConverter) {
1734      boolean relative = ((weka.core.converters.FileSourcedConverter)saver).getUseRelativePath();
1735      relativeB = new Boolean(relative);
1736    }
1737   
1738
1739//    if ( (file == null) || (file.isDirectory()) ) {
1740      invokeWriteToXML(node, "",     VAL_FILE);
1741      invokeWriteToXML(node, dir,    VAL_DIR);
1742      invokeWriteToXML(node, prefix, VAL_PREFIX);
1743/*    }
1744    else {
1745      String path = (((weka.core.converters.FileSourcedConverter) saver).getUseRelativePath())
1746        ? file.getPath()
1747        : file.getAbsolutePath();
1748      // Replace any windows file separators with forward slashes (Java under windows can
1749      // read paths with forward slashes (apparantly)
1750      path = path.replace('\\', '/');
1751      invokeWriteToXML(node, path, VAL_FILE);
1752      invokeWriteToXML(node, dir, VAL_DIR);
1753      invokeWriteToXML(node, prefix, VAL_PREFIX);
1754    }*/
1755
1756    if (relativeB != null) {
1757      invokeWriteToXML(node, relativeB.toString(), VAL_RELATIVE_PATH);
1758    }
1759   
1760    return node;
1761  }
1762
1763  /**
1764   * builds the Saver from the given DOM node.
1765   *
1766   * @param node the associated XML node
1767   * @return the instance created from the XML description
1768   * @throws Exception if instantiation fails
1769   */
1770  public Object readSaver(Element node) throws Exception {
1771    Object      result;
1772    Vector      children;
1773    Element     child;
1774    int         i;
1775    String      name;
1776    String      file;
1777    String      dir;
1778    String      prefix;
1779
1780    // for debugging only
1781    if (DEBUG)
1782       trace(new Throwable(), node.getAttribute(ATT_NAME));
1783
1784    m_CurrentNode = node;
1785   
1786    result   = Class.forName(node.getAttribute(ATT_CLASS)).newInstance();
1787    children = XMLDocument.getChildTags(node);
1788    file     = null;
1789    dir      = null;
1790    prefix   = null;
1791
1792    Object relativeB = null;
1793    boolean relative = false;
1794
1795    for (i = 0; i < children.size(); i++) {
1796      child = (Element) children.get(i);
1797      name  = child.getAttribute(ATT_NAME);
1798
1799      if (name.equals(VAL_FILE)) {
1800        file = (String) invokeReadFromXML(child);
1801      } else if (name.equals(VAL_DIR)) {
1802        dir = (String) invokeReadFromXML(child);
1803      } else if (name.equals(VAL_PREFIX)) {
1804        prefix = (String) invokeReadFromXML(child);
1805      } else if (name.equals(VAL_RELATIVE_PATH)) {
1806        relativeB = readFromXML(child);
1807        if (relativeB instanceof Boolean) {
1808          relative = ((Boolean)relativeB).booleanValue();
1809        }
1810      } else {
1811        readFromXML(result, name, child);
1812      }
1813    }
1814
1815    if ( (file != null) && (file.length() == 0) )
1816      file = null;
1817
1818    // savers only get directory and prefix, not file (KnowledgeFlow sets the
1819    // file/destination based on the relation, dir and prefix)
1820    if ( (dir != null) && (prefix != null) ) {
1821      ((weka.core.converters.AbstractFileSaver) result).setDir(dir);
1822      ((weka.core.converters.AbstractFileSaver) result).setFilePrefix(prefix);
1823    }
1824
1825    if (result instanceof weka.core.converters.FileSourcedConverter) {
1826      ((weka.core.converters.FileSourcedConverter)result).setUseRelativePath(relative);
1827    }
1828   
1829    return result;
1830  }
1831
1832  /**
1833   * adds the given BeanVisual to a DOM structure.
1834   *
1835   * @param parent the parent of this object, e.g. the class this object is a member of
1836   * @param o the Object to describe in XML
1837   * @param name the name of the object
1838   * @return the node that was created
1839   * @throws Exception if the DOM creation fails
1840   */
1841  public Element writeBeanVisual(Element parent, Object o, String name)
1842      throws Exception {
1843   
1844    Element         node;
1845    BeanVisual      visual;
1846
1847    // for debugging only
1848    if (DEBUG)
1849       trace(new Throwable(), name);
1850   
1851    m_CurrentNode = parent;
1852   
1853    visual = (BeanVisual) o;
1854    node   = writeToXML(parent, o, name);
1855
1856    // add icon paths
1857    invokeWriteToXML(node, visual.getIconPath(),         VAL_ICONPATH);
1858    invokeWriteToXML(node, visual.getAnimatedIconPath(), VAL_ANIMATEDICONPATH);
1859   
1860    return node;
1861  }
1862
1863  /**
1864   * builds the BeanVisual from the given DOM node.
1865   *
1866   * @param node the associated XML node
1867   * @return the instance created from the XML description
1868   * @throws Exception if instantiation fails
1869   */
1870  public Object readBeanVisual(Element node) throws Exception {
1871    Object      result;
1872    Vector      children;
1873    Element     child;
1874    int         i;
1875    String      name;
1876    String      text;
1877    String      iconPath;
1878    String      animIconPath;
1879
1880    // for debugging only
1881    if (DEBUG)
1882       trace(new Throwable(), node.getAttribute(ATT_NAME));
1883
1884    m_CurrentNode = node;
1885   
1886    result       = null;
1887    children     = XMLDocument.getChildTags(node);
1888    text         = "";
1889    iconPath     = "";
1890    animIconPath = "";
1891
1892    // find text
1893    for (i = 0; i < children.size(); i++) {
1894      child = (Element) children.get(i);
1895      name  = child.getAttribute(ATT_NAME);
1896
1897      if (name.equals(VAL_TEXT))
1898        text = (String) invokeReadFromXML(child);
1899      else if (name.equals(VAL_ICONPATH))
1900        iconPath = (String) invokeReadFromXML(child);
1901      else if (name.equals(VAL_ANIMATEDICONPATH))
1902        animIconPath = (String) invokeReadFromXML(child);
1903    }
1904
1905    result = new BeanVisual(text, iconPath, animIconPath);
1906   
1907    // set rest of properties
1908    for (i = 0; i < children.size(); i++)
1909      readFromXML(result, node.getAttribute(ATT_NAME), (Element) children.get(i));
1910   
1911    return result;
1912  }
1913 
1914  /**
1915   * returns the IDs for the given BeanInstances, i.e., the stored IDs
1916   * in m_BeanInstancesID, based on m_BeanInstances
1917   *
1918   * @param beans       the beans to retrieve the IDs for
1919   * @return            the IDs for the given BeanInstances
1920   * @see #m_BeanInstances
1921   * @see #m_BeanInstancesID
1922   */
1923  protected Vector getIDsForBeanInstances(Vector beans) {
1924    Vector        result;
1925    int           i;
1926    int           pos;
1927   
1928    result = new Vector();
1929
1930    for (i = 0; i < beans.size(); i++) {
1931      pos = m_BeanInstances.indexOf(beans.get(i));
1932      result.add(m_BeanInstancesID.get(pos));
1933    }
1934   
1935    return result;
1936  }
1937 
1938  /**
1939   * adds the given MetaBean to a DOM structure.
1940   *
1941   * @param parent the parent of this object, e.g. the class this object is a member of
1942   * @param o the Object to describe in XML
1943   * @param name the name of the object
1944   * @return the node that was created
1945   * @throws Exception if the DOM creation fails
1946   */
1947  public Element writeMetaBean(Element parent, Object o, String name)
1948      throws Exception {
1949   
1950    Element         node;
1951    MetaBean        meta;
1952
1953    // for debugging only
1954    if (DEBUG)
1955       trace(new Throwable(), name);
1956   
1957    m_CurrentNode = parent;
1958   
1959    meta = (MetaBean) o;
1960    node = writeToXML(parent, o, name);
1961
1962    invokeWriteToXML(node, getIDsForBeanInstances(meta.getBeansInInputs()), VAL_INPUTSID);
1963    invokeWriteToXML(node, getIDsForBeanInstances(meta.getBeansInOutputs()), VAL_OUTPUTSID);
1964   
1965    return node;
1966  }
1967 
1968  /**
1969   * returns a vector with references to BeanInstances according to the IDs
1970   * in the given Vector.
1971   * @param ids       contains the IDs of the BeanInstances
1972   * @return          the corresponding BeanInstances
1973   * @see #m_BeanInstances
1974   * @see #m_BeanInstancesID
1975   */
1976  protected Vector getBeanInstancesForIDs(Vector ids) {
1977    Vector        result;
1978    int           i;
1979    int           pos;
1980   
1981    result = new Vector();
1982   
1983    for (i = 0; i < ids.size(); i++) {
1984      pos = m_BeanInstancesID.indexOf(ids.get(i));
1985      result.add(m_BeanInstances.get(pos));
1986    }
1987   
1988    return result;
1989  }
1990
1991  /**
1992   * builds the MetaBean from the given DOM node.
1993   *
1994   * @param node the associated XML node
1995   * @return the instance created from the XML description
1996   * @throws Exception if instantiation fails
1997   */
1998  public Object readMetaBean(Element node) throws Exception {
1999    Object          result;
2000    Vector          children;
2001    Element         child;
2002    int             i;
2003    String          name;
2004    Vector          inputs;
2005    Vector          outputs;
2006    Vector          coords;
2007    MetaBean        bean;
2008
2009    // for debugging only
2010    if (DEBUG)
2011       trace(new Throwable(), node.getAttribute(ATT_NAME));
2012
2013    m_CurrentNode = node;
2014   
2015    result   = new MetaBean();
2016    children = XMLDocument.getChildTags(node);
2017    inputs   = new Vector();
2018    outputs  = new Vector();
2019    coords   = new Vector();
2020   
2021    // the current MetaBean
2022    m_CurrentMetaBean = (MetaBean) result;
2023
2024    for (i = 0; i < children.size(); i++) {
2025      child = (Element) children.get(i);
2026      name  = child.getAttribute(ATT_NAME);
2027
2028      if (name.equals(VAL_ASSOCIATEDCONNECTIONS))
2029        ((MetaBean) result).setAssociatedConnections((Vector) invokeReadFromXML(child));
2030      else if (name.equals(VAL_INPUTSID))
2031        inputs = (Vector) invokeReadFromXML(child);
2032      else if (name.equals(VAL_OUTPUTSID))
2033        outputs = (Vector) invokeReadFromXML(child);
2034      else if (name.equals(VAL_SUBFLOW))
2035        ((MetaBean) result).setSubFlow((Vector) invokeReadFromXML(child));
2036      else if (name.equals(VAL_ORIGINALCOORDS))
2037        coords = (Vector) invokeReadFromXML(child);
2038      else if (name.equals(VAL_INPUTS))
2039        System.out.println("INFO: '" + name + "' will be restored later.");
2040      else if (name.equals(VAL_OUTPUTS))
2041        System.out.println("INFO: '" + name + "' will be restored later.");
2042      else
2043        readFromXML(result, name, child);
2044    }
2045
2046    bean = (MetaBean) result;
2047   
2048    // set inputs and outputs, after the beans have been instantiated
2049    bean.setInputs(getBeanInstancesForIDs(inputs));
2050    bean.setOutputs(getBeanInstancesForIDs(outputs));
2051    bean.setOriginalCoords(coords);
2052   
2053    return result;
2054  }
2055}
Note: See TracBrowser for help on using the repository browser.