/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * XMLBeans.java * Copyright (C) 2005 University of Waikato, Hamilton, New Zealand */ package weka.gui.beans.xml; import weka.core.converters.ConverterUtils; import weka.core.xml.XMLBasicSerialization; import weka.core.xml.XMLDocument; import weka.core.Environment; import weka.core.EnvironmentHandler; import weka.gui.beans.BeanConnection; import weka.gui.beans.BeanInstance; import weka.gui.beans.BeanVisual; import weka.gui.beans.MetaBean; import weka.gui.beans.Visible; import weka.gui.beans.BeanCommon; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Point; import java.beans.BeanInfo; import java.beans.EventSetDescriptor; import java.beans.Introspector; import java.beans.beancontext.BeanContextSupport; import java.io.File; import java.util.Enumeration; import java.util.Hashtable; import java.util.StringTokenizer; import java.util.Vector; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.FontUIResource; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; /** * This class serializes and deserializes a KnowledgeFlow setup to and fro XML. * <br> * * @author FracPete (fracpete at waikato dot ac dot nz) * @version $Revision: 7155 $ */ public class XMLBeans extends XMLBasicSerialization { /** the value of the id property */ public final static String VAL_ID = "id"; /** the value of the x property */ public final static String VAL_X = "x"; /** the value of the y property */ public final static String VAL_Y = "y"; /** the value of the bean property */ public final static String VAL_BEAN = "bean"; /** the value of the customName property */ public final static String VAL_CUSTOM_NAME = "custom_name"; /** the value of the source property */ public final static String VAL_SOURCEID = "source_id"; /** the value of the target property */ public final static String VAL_TARGETID = "target_id"; /** the value of the eventname property */ public final static String VAL_EVENTNAME = "eventname"; /** the value of the hidden property */ public final static String VAL_HIDDEN = "hidden"; /** the value of the file property */ public final static String VAL_FILE = "file"; /** the value of the dir property */ public final static String VAL_DIR = "dir"; /** the value of the prefix property */ public final static String VAL_PREFIX = "prefix"; public final static String VAL_RELATIVE_PATH = "useRelativePath"; /** the value of the options property */ public final static String VAL_OPTIONS = "options"; /** the value of the saver property */ public final static String VAL_SAVER = "wrappedAlgorithm"; /** the value of the loader property */ public final static String VAL_LOADER = "wrappedAlgorithm"; /** the value of the text property */ public final static String VAL_TEXT = "text"; /** the value of the beanContext property */ public final static String VAL_BEANCONTEXT = "beanContext"; /** the value of the width property */ public final static String VAL_WIDTH = "width"; /** the value of the height property */ public final static String VAL_HEIGHT = "height"; /** the value of the red property */ public final static String VAL_RED = "red"; /** the value of the green property */ public final static String VAL_GREEN = "green"; /** the value of the blue property */ public final static String VAL_BLUE = "blue"; /** the value of the value property */ public final static String VAL_NAME = "name"; /** the value of the style property */ public final static String VAL_STYLE = "style"; /** the value of the location property */ public final static String VAL_LOCATION = "location"; /** the value of the size property */ public final static String VAL_SIZE = "size"; /** the value of the color property */ public final static String VAL_COLOR = "color"; /** the value of the font property */ public final static String VAL_FONT = "font"; /** the value of the iconpath property */ public final static String VAL_ICONPATH = "iconPath"; /** the value of the animatedIconPath property */ public final static String VAL_ANIMATEDICONPATH = "animatedIconPath"; /** the value of the associatedConnections property */ public final static String VAL_ASSOCIATEDCONNECTIONS = "associatedConnections"; /** the value of the input property */ public final static String VAL_INPUTS = "inputs"; /** the value of the input id property */ public final static String VAL_INPUTSID = "inputs_id"; /** the value of the outputs id property */ public final static String VAL_OUTPUTS = "outputs"; /** the value of the outputs property */ public final static String VAL_OUTPUTSID = "outputs_id"; /** the value of the subFlow property */ public final static String VAL_SUBFLOW = "subFlow"; /** the value of the originalCoords property */ public final static String VAL_ORIGINALCOORDS = "originalCoords"; /** the value of the relationNameForFilename property (Saver) */ public final static String VAL_RELATIONNAMEFORFILENAME = "relationNameForFilename"; /** the index in the Vector, where the BeanInstances are stored * (Instances and Connections are stored in a Vector and then serialized) */ public final static int INDEX_BEANINSTANCES = 0; /** the index in the Vector, where the BeanConnections are stored * (Instances and Connections are stored in a Vector and then serialized) */ public final static int INDEX_BEANCONNECTIONS = 1; /** the component that manages the layout of the beans */ protected JComponent m_BeanLayout; /** keeps track of the BeanInstances read so far, used for the BeanConnections */ protected Vector m_BeanInstances; /** keeps track of the BeanInstances read so far, used for the BeanConnections */ protected Vector m_BeanInstancesID; /** whether to ignore the BeanConnection */ protected boolean m_IgnoreBeanConnections; /** the current MetaBean (for the BeanConnections) */ protected MetaBean m_CurrentMetaBean; /** the identifier for regular BeanConnections */ protected final static String REGULAR_CONNECTION = "regular_connection"; /** the relation between Bean and connection, MetaBean BeanConnections * are stored under the reference of the MetaBean, regular connections * are stored under REGULAR_CONNECTION. The relation has the following * format (is a string): sourcePos,targetPos,event,hidden * @see #REGULAR_CONNECTION */ protected Hashtable m_BeanConnectionRelation; /** the data that is about to be read/written contains a complete layout * @see #m_DataType */ public final static int DATATYPE_LAYOUT = 0; /** the data that is about to be read/written contains user-components, i.e., * Metabeans * @see #m_DataType */ public final static int DATATYPE_USERCOMPONENTS = 1; /** the type of data that is be read/written * @see #DATATYPE_LAYOUT * @see #DATATYPE_USERCOMPONENTS */ protected int m_DataType = DATATYPE_LAYOUT; /** the beancontext to use for loading from XML and the beancontext is * null in the bean */ protected BeanContextSupport m_BeanContextSupport = null; /** The index of the vector of bean instances or connections to use. * this corresponds to a tab in the main KnowledgeFlow UI */ protected int m_vectorIndex = 0; /** * initializes the serialization for layouts * * @param layout the component that manages the layout * @param context the bean context support to use * @param tab the index of the vector of bean instances or connections * to use (this corresponds to a visible tab in the main KnowledgeFlow UI) * @throws Exception if initialization fails */ public XMLBeans(JComponent layout, BeanContextSupport context, int tab) throws Exception { this(layout, context, DATATYPE_LAYOUT, tab); } /** * initializes the serialization for different types of data * * @param layout the component that manages the layout * @param context the bean context support to use * @param datatype the type of data to read/write * @throws Exception if initialization fails */ public XMLBeans(JComponent layout, BeanContextSupport context, int datatype, int tab) throws Exception { super(); m_vectorIndex = tab; m_BeanLayout = layout; m_BeanContextSupport = context; setDataType(datatype); } /** * sets what kind of data is to be read/written * @param value the type of data * @see #m_DataType */ public void setDataType(int value) { if (value == DATATYPE_LAYOUT) m_DataType = value; else if (value == DATATYPE_USERCOMPONENTS) m_DataType = value; else System.out.println("DataType '" + value + "' is unknown!"); } /** * returns the type of data that is to be read/written * @return the type of data * @see #m_DataType */ public int getDataType() { return m_DataType; } /** * generates internally a new XML document and clears also the IgnoreList and * the mappings for the Read/Write-Methods * * @throws Exception if something goes wrong */ public void clear() throws Exception { Vector<String> classnames; int i; super.clear(); // ignore: suppress unnecessary GUI stuff // needs to be checked for new Java versions (might introduce new properties) // - works with Java 1.5 m_Properties.addIgnored("UI"); m_Properties.addIgnored("actionMap"); m_Properties.addIgnored("alignmentX"); m_Properties.addIgnored("alignmentY"); m_Properties.addIgnored("autoscrolls"); m_Properties.addIgnored("background"); m_Properties.addIgnored("border"); m_Properties.addIgnored("componentPopupMenu"); m_Properties.addIgnored("debugGraphicsOptions"); m_Properties.addIgnored("doubleBuffered"); m_Properties.addIgnored("enabled"); m_Properties.addIgnored("focusCycleRoot"); m_Properties.addIgnored("focusTraversalPolicy"); m_Properties.addIgnored("focusTraversalPolicyProvider"); m_Properties.addIgnored("focusable"); m_Properties.addIgnored("font"); m_Properties.addIgnored("foreground"); m_Properties.addIgnored("inheritsPopupMenu"); m_Properties.addIgnored("inputVerifier"); m_Properties.addIgnored("layout"); m_Properties.addIgnored("locale"); m_Properties.addIgnored("maximumSize"); m_Properties.addIgnored("minimumSize"); m_Properties.addIgnored("nextFocusableComponent"); m_Properties.addIgnored("opaque"); m_Properties.addIgnored("preferredSize"); m_Properties.addIgnored("requestFocusEnabled"); m_Properties.addIgnored("toolTipText"); m_Properties.addIgnored("transferHandler"); m_Properties.addIgnored("verifyInputWhenFocusTarget"); m_Properties.addIgnored("visible"); // special ignore m_Properties.addIgnored("size"); // otherwise you get an endless loop with Dimension! m_Properties.addIgnored("location"); // otherwise you get an endless loop with Point! // allow m_Properties.addAllowed(weka.gui.beans.BeanInstance.class, "x"); m_Properties.addAllowed(weka.gui.beans.BeanInstance.class, "y"); m_Properties.addAllowed(weka.gui.beans.BeanInstance.class, "bean"); m_Properties.addAllowed(weka.gui.beans.Saver.class, "wrappedAlgorithm"); m_Properties.addAllowed(weka.gui.beans.Loader.class, "wrappedAlgorithm"); m_Properties.addAllowed(weka.gui.beans.Saver.class, "relationNameForFilename"); if (getDataType() == DATATYPE_LAYOUT) m_Properties.addAllowed(weka.gui.beans.Loader.class, "beanContext"); else m_Properties.addIgnored(weka.gui.beans.Loader.class, "beanContext"); // TODO: more classes??? m_Properties.addAllowed(weka.gui.beans.Filter.class, "filter"); m_Properties.addAllowed(weka.gui.beans.Classifier.class, "wrappedAlgorithm"); m_Properties.addAllowed(weka.gui.beans.Clusterer.class, "wrappedAlgorithm"); m_Properties.addAllowed(weka.gui.beans.Classifier.class, "executionSlots"); m_Properties.addAllowed(weka.gui.beans.Classifier.class, "blockOnLastFold"); m_Properties.addAllowed(weka.classifiers.Classifier.class, "debug"); m_Properties.addAllowed(weka.classifiers.Classifier.class, "options"); m_Properties.addAllowed(weka.filters.Filter.class, "options"); m_Properties.addAllowed(weka.core.converters.DatabaseSaver.class, "options"); m_Properties.addAllowed(weka.core.converters.DatabaseLoader.class, "options"); m_Properties.addAllowed(weka.core.converters.TextDirectoryLoader.class, "options"); // we assume that classes implementing SplitEvaluator also implement OptionHandler m_Properties.addAllowed(weka.experiment.SplitEvaluator.class, "options"); // we assume that classes implementing ResultProducer also implement OptionHandler m_Properties.addAllowed(weka.experiment.ResultProducer.class, "options"); // read/write methods m_CustomMethods.register(this, Color.class, "Color"); m_CustomMethods.register(this, Dimension.class, "Dimension"); m_CustomMethods.register(this, Font.class, "Font"); m_CustomMethods.register(this, Point.class, "Point"); m_CustomMethods.register(this, ColorUIResource.class, "ColorUIResource"); m_CustomMethods.register(this, FontUIResource.class, "FontUIResource"); m_CustomMethods.register(this, weka.gui.beans.BeanInstance.class, "BeanInstance"); m_CustomMethods.register(this, weka.gui.beans.BeanConnection.class, "BeanConnection"); m_CustomMethods.register(this, weka.gui.beans.BeanVisual.class, "BeanVisual"); m_CustomMethods.register(this, weka.gui.beans.Saver.class, "BeanSaver"); m_CustomMethods.register(this, weka.gui.beans.MetaBean.class, "MetaBean"); classnames = ConverterUtils.getFileLoaders(); for (i = 0; i < classnames.size(); i++) m_CustomMethods.register(this, Class.forName(classnames.get(i)), "Loader"); classnames = ConverterUtils.getFileSavers(); for (i = 0; i < classnames.size(); i++) m_CustomMethods.register(this, Class.forName(classnames.get(i)), "Saver"); // other variables m_BeanInstances = null; m_BeanInstancesID = null; m_CurrentMetaBean = null; m_IgnoreBeanConnections = true; m_BeanConnectionRelation = null; } /** * traverses over all BeanInstances (or MetaBeans) and stores them in a vector * (recurses into MetaBeans, since the sub-BeanInstances are not visible) * @param list the BeanInstances/MetaBeans to traverse */ protected void addBeanInstances(Vector list) { int i; BeanInstance beaninst; for (i = 0; i < list.size(); i++) { if (list.get(i) instanceof BeanInstance) { beaninst = (BeanInstance) list.get(i); m_BeanInstancesID.add(new Integer(m_BeanInstances.size())); m_BeanInstances.add(beaninst); if (beaninst.getBean() instanceof MetaBean) addBeanInstances(((MetaBean) beaninst.getBean()).getBeansInSubFlow()); } else if (list.get(i) instanceof MetaBean) { addBeanInstances(((MetaBean) list.get(i)).getBeansInSubFlow()); } else { System.out.println("addBeanInstances does not support Vectors of class '" + list.get(i) + "'!"); } } } /** * enables derived classes to due some pre-processing on the objects, that's * about to be serialized. Right now it only returns the object. * * @param o the object that is serialized into XML * @return the possibly altered object * @throws Exception if post-processing fails */ protected Object writePreProcess(Object o) throws Exception { o = super.writePreProcess(o); // gather all BeanInstances, also the ones in MetaBeans m_BeanInstances = new Vector(); m_BeanInstancesID = new Vector(); switch (getDataType()) { case DATATYPE_LAYOUT: addBeanInstances(BeanInstance.getBeanInstances(m_vectorIndex)); break; case DATATYPE_USERCOMPONENTS: addBeanInstances((Vector) o); break; default: System.out.println("writePreProcess: data type '" + getDataType() + "' is not recognized!"); break; } return o; } /** * enables derived classes to add other properties to the DOM tree, e.g. * ones that do not apply to the get/set convention of beans. only implemented * with empty method body. * * @param o the object that is serialized into XML * @throws Exception if post-processing fails */ protected void writePostProcess(Object o) throws Exception { Element root; NodeList list; Element conns; Element child; int i; // since not all BeanConnections get saved to XML (e.g., MetaBeans in the // UserToolBar) if one saves a layout, the numbering in the Vector of the // BeanConnections is not correct. The "name" attribute of the nodes has // to be modified if (getDataType() == DATATYPE_LAYOUT) { root = m_Document.getDocument().getDocumentElement(); conns = (Element) root.getChildNodes().item(INDEX_BEANCONNECTIONS); list = conns.getChildNodes(); for (i = 0; i < list.getLength(); i++) { child = (Element) list.item(i); child.setAttribute(ATT_NAME, "" + i); } } } /** * additional pre-processing can happen in derived classes before the * actual reading from XML (working on the raw XML). right now it does * nothing with the document, only empties the help-vector for the * BeanInstances and reads the IDs for the BeanInstances, s.t. the correct * references can be set again * * @param document the document to pre-process * @return the processed object * @throws Exception if post-processing fails * @see #m_BeanInstances */ protected Document readPreProcess(Document document) throws Exception { NodeList list; int i; Element node; String clsName; Vector children; int id; int n; Element child; m_BeanInstances = new Vector(); m_BeanInstancesID = new Vector(); // get all BeanInstance nodes list = document.getElementsByTagName("*"); clsName = BeanInstance.class.getName(); for (i = 0; i < list.getLength(); i++) { node = (Element) list.item(i); // is it a BeanInstance? if (node.getAttribute(ATT_CLASS).equals(clsName)) { children = XMLDocument.getChildTags(node); id = m_BeanInstancesID.size(); // get id-tag (if available) for (n = 0; n < children.size(); n++) { child = (Element) children.get(n); if (child.getAttribute(ATT_NAME).equals(VAL_ID)) id = readIntFromXML((Element) child); } m_BeanInstancesID.add(new Integer(id)); } } m_BeanInstances.setSize(m_BeanInstancesID.size()); // set MetaBean to null m_CurrentMetaBean = null; // no BeanConnections -> see readPostProcess(Object) m_IgnoreBeanConnections = true; // reset BeanConnection-Relations m_BeanConnectionRelation = new Hashtable(); return document; } /** * puts the given BeanConnection onto the next null in the given Vector, * or at the end of the list, if no null is found. * (during the de-serializing, no BeanConnections are set, only nulls) * @param conn the connection to add to the list * @param list the list to add the BeanConnection to */ protected void setBeanConnection(BeanConnection conn, Vector list) { int i; boolean added; added = false; for (i = 0; i < list.size(); i++) { if (list.get(i) == null) { list.set(i, conn); added = true; break; } } if (!added) list.add(conn); } /** * generates a connection based on the given parameters * @param sourcePos the source position in the m_BeanInstances vector * @param targetPos the target position in the m_BeanInstances vector * @param event the name of the event, i.e., the connection * @param hidden true if the connection is hidden * @return the generated BeanConnection * @throws Exception if something goes wrong */ protected BeanConnection createBeanConnection(int sourcePos, int targetPos, String event, boolean hidden) throws Exception { BeanConnection result; BeanInfo compInfo; EventSetDescriptor[] esds; int i; BeanInstance instSource; BeanInstance instTarget; result = null; // was there a connection? if ( (sourcePos == -1) || (targetPos == -1) ) return result; instSource = (BeanInstance) m_BeanInstances.get(sourcePos); instTarget = (BeanInstance) m_BeanInstances.get(targetPos); compInfo = Introspector.getBeanInfo(((BeanInstance) m_BeanInstances.get(sourcePos)).getBean().getClass()); esds = compInfo.getEventSetDescriptors(); for (i = 0; i < esds.length; i++) { if (esds[i].getName().equals(event)) { result = new BeanConnection(instSource, instTarget, esds[i], m_vectorIndex); ((BeanConnection) result).setHidden(hidden); break; } } return result; } /** * rebuilds all the connections for a certain key in the hashtable. * for the ones being part of a MetaBean, no new instance is built, but only * the reference to the actual BeanConnection set. * @param deserialized the deserialized knowledgeflow * @param key the key of the hashtable to rebuild all connections for * @throws Exception if something goes wrong */ protected void rebuildBeanConnections(Vector deserialized, Object key) throws Exception { int i; int n; int sourcePos; int targetPos; String event; boolean hidden; Vector conns; BeanConnection conn; StringTokenizer tok; Vector beanconns; conns = (Vector) m_BeanConnectionRelation.get(key); // no connections? if (conns == null) return; for (n = 0; n < conns.size(); n++) { tok = new StringTokenizer(conns.get(n).toString(), ","); conn = null; sourcePos = Integer.parseInt(tok.nextToken()); targetPos = Integer.parseInt(tok.nextToken()); event = tok.nextToken(); hidden = stringToBoolean(tok.nextToken()); // regular connection? -> new instance // or MetaBean from user toolbar if ( (!(key instanceof MetaBean)) || (getDataType() == DATATYPE_USERCOMPONENTS)) { conn = createBeanConnection(sourcePos, targetPos, event, hidden); } // MetaBean? -> find BeanConnection else { beanconns = BeanConnection.getConnections(m_vectorIndex); for (i = 0; i < beanconns.size(); i++) { conn = (BeanConnection) beanconns.get(i); if ( (conn.getSource() == (BeanInstance) m_BeanInstances.get(sourcePos)) && (conn.getTarget() == (BeanInstance) m_BeanInstances.get(targetPos)) && (conn.getEventName().equals(event)) ) { break; } conn = null; } } // add the connection to the corresponding list/MetaBean if (key instanceof MetaBean) setBeanConnection(conn, ((MetaBean) key).getAssociatedConnections()); else setBeanConnection(conn, (Vector) deserialized.get(INDEX_BEANCONNECTIONS)); } } /** * removes the given meta beans from the layout, since they're only listed * in the user toolbar * * @param metabeans the list of MetaBeans in the user toolbar */ protected void removeUserToolBarBeans(Vector metabeans) { int i; int n; MetaBean meta; Vector subflow; BeanInstance beaninst; for (i = 0; i < metabeans.size(); i++) { meta = (MetaBean) metabeans.get(i); subflow = meta.getSubFlow(); for (n = 0; n < subflow.size(); n++) { beaninst = (BeanInstance) subflow.get(n); beaninst.removeBean(m_BeanLayout); } } } /** * additional post-processing can happen in derived classes after reading * from XML. re-builds the BeanConnections. * * @param o the object to perform some additional processing on * @return the processed object * @throws Exception if post-processing fails */ protected Object readPostProcess(Object o) throws Exception { Enumeration enm; Vector deserialized; Object key; deserialized = (Vector) super.readPostProcess(o); // rebuild the actual connections rebuildBeanConnections(deserialized, REGULAR_CONNECTION); // rebuild the references in the MetaBeans enm = m_BeanConnectionRelation.keys(); while (enm.hasMoreElements()) { key = enm.nextElement(); // skip the regular connections if (!(key instanceof MetaBean)) continue; rebuildBeanConnections(deserialized, key); } // remove MetaBean and subflow from BeanInstance (not part of the flow!) if (getDataType() == DATATYPE_USERCOMPONENTS) removeUserToolBarBeans(deserialized); return deserialized; } /** * returns the relation for the given MetaBean, for the regular connections, * null has to be used * @param meta the MetaBean (or null for regular connections) to retrieve * the connections for * @return the associated connections * @see #REGULAR_CONNECTION */ protected Vector getBeanConnectionRelation(MetaBean meta) { Vector result; Object key; if (meta == null) key = REGULAR_CONNECTION; else key = meta; // not yet in there? if (!m_BeanConnectionRelation.containsKey(key)) { m_BeanConnectionRelation.put(key, new Vector()); } result = (Vector) m_BeanConnectionRelation.get(key); return result; } /** * adds the given connection-relation for the specified MetaBean (or null in * case of regular connections) * @param meta the MetaBean (or null for regular connections) to add * the relationship for * @param connection the connection relation to add */ protected void addBeanConnectionRelation(MetaBean meta, String connection) { Vector relations; Object key; relations = getBeanConnectionRelation(meta); // add relation relations.add(connection); // update if (meta == null) key = REGULAR_CONNECTION; else key = meta; m_BeanConnectionRelation.put(key, relations); } /** * adds the given Color to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeColor(Element parent, Object o, String name) throws Exception { Element node; Color color; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; color = (Color) o; node = addElement(parent, name, color.getClass().getName(), false); writeIntToXML(node, color.getRed(), VAL_RED); writeIntToXML(node, color.getGreen(), VAL_GREEN); writeIntToXML(node, color.getBlue(), VAL_BLUE); return node; } /** * builds the Color from the given DOM node. * * @param node the associated XML node * @return the instance created from the XML description * @throws Exception if instantiation fails */ public Object readColor(Element node) throws Exception { Object result; Vector children; Element child; int i; int red; int green; int blue; String name; // for debugging only if (DEBUG) trace(new Throwable(), node.getAttribute(ATT_NAME)); m_CurrentNode = node; result = null; children = XMLDocument.getChildTags(node); red = 0; green = 0; blue = 0; for (i = 0; i < children.size(); i++) { child = (Element) children.get(i); name = child.getAttribute(ATT_NAME); if (name.equals(VAL_RED)) red = readIntFromXML(child); else if (name.equals(VAL_GREEN)) green = readIntFromXML(child); else if (name.equals(VAL_BLUE)) blue = readIntFromXML(child); else System.out.println("WARNING: '" + name + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!"); } result = new Color(red, green, blue); return result; } /** * adds the given Dimension to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeDimension(Element parent, Object o, String name) throws Exception { Element node; Dimension dim; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; dim = (Dimension) o; node = addElement(parent, name, dim.getClass().getName(), false); writeDoubleToXML(node, dim.getWidth(), VAL_WIDTH); writeDoubleToXML(node, dim.getHeight(), VAL_HEIGHT); return node; } /** * builds the Dimension from the given DOM node. * * @param node the associated XML node * @return the instance created from the XML description * @throws Exception if instantiation fails */ public Object readDimension(Element node) throws Exception { Object result; Vector children; Element child; int i; double width; double height; String name; // for debugging only if (DEBUG) trace(new Throwable(), node.getAttribute(ATT_NAME)); m_CurrentNode = node; result = null; children = XMLDocument.getChildTags(node); width = 0; height = 0; for (i = 0; i < children.size(); i++) { child = (Element) children.get(i); name = child.getAttribute(ATT_NAME); if (name.equals(VAL_WIDTH)) width = readDoubleFromXML(child); else if (name.equals(VAL_HEIGHT)) height = readDoubleFromXML(child); else System.out.println("WARNING: '" + name + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!"); } result = new Dimension(); ((Dimension) result).setSize(width, height); return result; } /** * adds the given Font to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeFont(Element parent, Object o, String name) throws Exception { Element node; Font font; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; font = (Font) o; node = addElement(parent, name, font.getClass().getName(), false); invokeWriteToXML(node, font.getName(), VAL_NAME); writeIntToXML(node, font.getStyle(), VAL_STYLE); writeIntToXML(node, font.getSize(), VAL_SIZE); return node; } /** * builds the Font from the given DOM node. * * @param node the associated XML node * @return the instance created from the XML description * @throws Exception if instantiation fails */ public Object readFont(Element node) throws Exception { Object result; Vector children; Element child; int i; int style; int size; String name; String fontname; // for debugging only if (DEBUG) trace(new Throwable(), node.getAttribute(ATT_NAME)); m_CurrentNode = node; result = null; children = XMLDocument.getChildTags(node); fontname = ""; style = 0; size = 0; for (i = 0; i < children.size(); i++) { child = (Element) children.get(i); name = child.getAttribute(ATT_NAME); if (name.equals(VAL_NAME)) name = (String) invokeReadFromXML(child); else if (name.equals(VAL_STYLE)) style = readIntFromXML(child); else if (name.equals(VAL_SIZE)) size = readIntFromXML(child); else System.out.println("WARNING: '" + name + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!"); } result = new Font(fontname, style, size); return result; } /** * adds the given Point to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writePoint(Element parent, Object o, String name) throws Exception { Element node; Point p; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; p = (Point) o; node = addElement(parent, name, p.getClass().getName(), false); writeDoubleToXML(node, p.getX(), VAL_X); writeDoubleToXML(node, p.getY(), VAL_Y); return node; } /** * builds the Point from the given DOM node. * * @param node the associated XML node * @return the instance created from the XML description * @throws Exception if instantiation fails */ public Object readPoint(Element node) throws Exception { Object result; Vector children; Element child; int i; double x; double y; String name; // for debugging only if (DEBUG) trace(new Throwable(), node.getAttribute(ATT_NAME)); m_CurrentNode = node; result = null; children = XMLDocument.getChildTags(node); x = 0; y = 0; for (i = 0; i < children.size(); i++) { child = (Element) children.get(i); name = child.getAttribute(ATT_NAME); if (name.equals(VAL_X)) x = readDoubleFromXML(child); else if (name.equals(VAL_Y)) y = readDoubleFromXML(child); else System.out.println("WARNING: '" + name + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!"); } result = new Point(); ((Point) result).setLocation(x, y); return result; } /** * adds the given ColorUIResource to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeColorUIResource(Element parent, Object o, String name) throws Exception { Element node; ColorUIResource resource; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; resource = (ColorUIResource) o; node = addElement(parent, name, resource.getClass().getName(), false); invokeWriteToXML(node, new Color(resource.getRGB()), VAL_COLOR); return node; } /** * builds the ColorUIResource from the given DOM node. * * @param node the associated XML node * @return the instance created from the XML description * @throws Exception if instantiation fails */ public Object readColorUIResource(Element node) throws Exception { Object result; Vector children; Element child; int i; String name; Color color; // for debugging only if (DEBUG) trace(new Throwable(), node.getAttribute(ATT_NAME)); m_CurrentNode = node; result = null; children = XMLDocument.getChildTags(node); color = null; for (i = 0; i < children.size(); i++) { child = (Element) children.get(i); name = child.getAttribute(ATT_NAME); if (name.equals(VAL_COLOR)) color = (Color) invokeReadFromXML(child); else System.out.println("WARNING: '" + name + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!"); } result = new ColorUIResource(color); return result; } /** * adds the given FontUIResource to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeFontUIResource(Element parent, Object o, String name) throws Exception { Element node; FontUIResource resource; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; resource = (FontUIResource) o; node = addElement(parent, name, resource.getClass().getName(), false); invokeWriteToXML(node, new Font(resource.getName(), resource.getStyle(), resource.getSize()), VAL_COLOR); return node; } /** * builds the FontUIResource from the given DOM node. * * @param node the associated XML node * @return the instance created from the XML description * @throws Exception if instantiation fails */ public Object readFontUIResource(Element node) throws Exception { Object result; Vector children; Element child; int i; String name; Font font; // for debugging only if (DEBUG) trace(new Throwable(), node.getAttribute(ATT_NAME)); m_CurrentNode = node; result = null; children = XMLDocument.getChildTags(node); font = null; for (i = 0; i < children.size(); i++) { child = (Element) children.get(i); name = child.getAttribute(ATT_NAME); if (name.equals(VAL_FONT)) font = (Font) invokeReadFromXML(child); else System.out.println("WARNING: '" + name + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!"); } result = new FontUIResource(font); return result; } /** * adds the given BeanInstance to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeBeanInstance(Element parent, Object o, String name) throws Exception { Element node; BeanInstance beaninst; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; beaninst = (BeanInstance) o; node = addElement(parent, name, beaninst.getClass().getName(), false); writeIntToXML(node, m_BeanInstances.indexOf(beaninst), VAL_ID); writeIntToXML(node, beaninst.getX() + beaninst.getWidth() / 2, VAL_X); // x is thought to be in the center? writeIntToXML(node, beaninst.getY() + beaninst.getHeight() / 2, VAL_Y); // y is thought to be in the center? if (beaninst.getBean() instanceof BeanCommon) { // write the custom name of this bean String custName = ((BeanCommon)beaninst.getBean()).getCustomName(); invokeWriteToXML(node, custName, VAL_CUSTOM_NAME); } invokeWriteToXML(node, beaninst.getBean(), VAL_BEAN); return node; } /** * builds the BeanInstance from the given DOM node. * * @param node the associated XML node * @return the instance created from the XML description * @throws Exception if instantiation fails */ public Object readBeanInstance(Element node) throws Exception { Object result; Vector children; Element child; String name; int i; int x; int y; int id; Object bean; BeanVisual visual; BeanInstance beaninst; // for debugging only if (DEBUG) trace(new Throwable(), node.getAttribute(ATT_NAME)); m_CurrentNode = node; result = null; children = XMLDocument.getChildTags(node); id = -1; x = 0; y = 0; bean = null; String customName = null; for (i = 0; i < children.size(); i++) { child = (Element) children.get(i); name = child.getAttribute(ATT_NAME); if (name.equals(VAL_ID)) { id = readIntFromXML(child); } else if (name.equals(VAL_X)) { x = readIntFromXML(child); } else if (name.equals(VAL_Y)) { y = readIntFromXML(child); } else if (name.equals(VAL_CUSTOM_NAME)) { customName = (String)invokeReadFromXML(child); } else if (name.equals(VAL_BEAN)) { bean = invokeReadFromXML(child); } else { System.out.println("WARNING: '" + name + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!"); } } result = new BeanInstance(m_BeanLayout, bean, x, y, m_vectorIndex); beaninst = (BeanInstance) result; // set parent of BeanVisual if (beaninst.getBean() instanceof weka.gui.beans.Visible) { visual = ((Visible) beaninst.getBean()).getVisual(); visual.setSize(visual.getPreferredSize()); if (visual.getParent() == null) { ((JPanel) beaninst.getBean()).add(visual); } } if (beaninst.getBean() instanceof BeanCommon && customName != null) { ((BeanCommon)beaninst.getBean()).setCustomName(customName); } // no IDs -> get next null position if (id == -1) { for (i = 0; i < m_BeanInstances.size(); i++) { if (m_BeanInstances.get(i) == null) { id = ((Integer) m_BeanInstancesID.get(i)).intValue(); break; } } } // get position for id i = m_BeanInstancesID.indexOf(new Integer(id)); // keep track of the BeanInstances for reading the connections later on m_BeanInstances.set(i, result); // no current MetaBean m_CurrentMetaBean = null; return result; } /** * adds the given BeanConncetion to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeBeanConnection(Element parent, Object o, String name) throws Exception { Element node; BeanConnection beanconn; int source; int target; int sourcePos; int targetPos; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; beanconn = (BeanConnection) o; node = null; // get position sourcePos = m_BeanInstances.indexOf(beanconn.getSource()); targetPos = m_BeanInstances.indexOf(beanconn.getTarget()); // get id (if Connection is from a Bean in the UserToolBar, it's not listed! -> ignore it) if ( (sourcePos > -1) && (targetPos > -1) ) { source = ((Integer) m_BeanInstancesID.get(sourcePos)).intValue(); target = ((Integer) m_BeanInstancesID.get(targetPos)).intValue(); } else { source = -1; target = -1; } // connection exists in the layout? if ( (source > -1) && (target > -1) ) { node = addElement(parent, name, beanconn.getClass().getName(), false); writeIntToXML(node, source, VAL_SOURCEID); writeIntToXML(node, target, VAL_TARGETID); invokeWriteToXML(node, beanconn.getEventName(), VAL_EVENTNAME); writeBooleanToXML(node, beanconn.isHidden(), VAL_HIDDEN); } return node; } /** * builds the BeanConnection from the given DOM node. * * @param node the associated XML node * @return the instance created from the XML description * @throws Exception if instantiation fails */ public Object readBeanConnection(Element node) throws Exception { Object result; Vector children; Element child; String name; int i; int source; int target; int sourcePos; int targetPos; String event; boolean hidden; // for debugging only if (DEBUG) trace(new Throwable(), node.getAttribute(ATT_NAME)); m_CurrentNode = node; result = null; children = XMLDocument.getChildTags(node); source = 0; target = 0; event = ""; hidden = false; for (i = 0; i < children.size(); i++) { child = (Element) children.get(i); name = child.getAttribute(ATT_NAME); if (name.equals(VAL_SOURCEID)) source = readIntFromXML(child); else if (name.equals(VAL_TARGETID)) target = readIntFromXML(child); else if (name.equals(VAL_EVENTNAME)) event = (String) invokeReadFromXML(child); else if (name.equals(VAL_HIDDEN)) hidden = readBooleanFromXML(child); else System.out.println("WARNING: '" + name + "' is not a recognized name for " + node.getAttribute(ATT_NAME) + "!"); } // get position of id sourcePos = m_BeanInstancesID.indexOf(new Integer(source)); targetPos = m_BeanInstancesID.indexOf(new Integer(target)); // do we currently ignore the connections? // Note: necessary because of the MetaBeans if (m_IgnoreBeanConnections) { addBeanConnectionRelation(m_CurrentMetaBean, sourcePos + "," + targetPos + "," + event + "," + hidden); return result; } // generate it normally result = createBeanConnection(sourcePos, targetPos, event, hidden); return result; } /** * adds the given Loader (a bean) to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeBeanLoader(Element parent, Object o, String name) throws Exception { Element node; weka.gui.beans.Loader loader; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; loader = (weka.gui.beans.Loader) o; node = addElement(parent, name, loader.getClass().getName(), false); invokeWriteToXML(node, loader.getLoader(), VAL_LOADER); invokeWriteToXML(node, loader.getBeanContext(), VAL_BEANCONTEXT); return node; } /** * adds the given Saver (a bean) to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeBeanSaver(Element parent, Object o, String name) throws Exception { Element node; weka.gui.beans.Saver saver; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; saver = (weka.gui.beans.Saver) o; node = addElement(parent, name, saver.getClass().getName(), false); invokeWriteToXML(node, saver.getRelationNameForFilename(), VAL_RELATIONNAMEFORFILENAME); invokeWriteToXML(node, saver.getSaverTemplate(), VAL_SAVER); return node; } /** * adds the given Loader to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeLoader(Element parent, Object o, String name) throws Exception { Element node; weka.core.converters.Loader loader; File file; boolean known; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; loader = (weka.core.converters.Loader) o; node = addElement(parent, name, loader.getClass().getName(), false); known = true; file = null; // file if (loader instanceof weka.core.converters.AbstractFileLoader) file = ((weka.core.converters.AbstractFileLoader) loader).retrieveFile(); else known = false; if (!known) System.out.println("WARNING: unknown loader class '" + loader.getClass().getName() + "' - cannot retrieve file!"); Boolean relativeB = null; if (loader instanceof weka.core.converters.FileSourcedConverter) { boolean relative = ((weka.core.converters.FileSourcedConverter)loader).getUseRelativePath(); relativeB = new Boolean(relative); } // only save it, if it's a real file! if ( (file == null) || (file.isDirectory()) ) { invokeWriteToXML(node, "", VAL_FILE); } else { boolean notAbsolute = (((weka.core.converters.AbstractFileLoader) loader).getUseRelativePath() || (loader instanceof EnvironmentHandler && Environment.containsEnvVariables(file.getPath()))); String path = (notAbsolute) ? file.getPath() : file.getAbsolutePath(); // Replace any windows file separators with forward slashes (Java under windows can // read paths with forward slashes (apparantly) path = path.replace('\\', '/'); invokeWriteToXML(node, path, VAL_FILE); } if (relativeB != null) { invokeWriteToXML(node, relativeB.toString(), VAL_RELATIVE_PATH); } return node; } /** * builds the Loader from the given DOM node. * * @param node the associated XML node * @return the instance created from the XML description * @throws Exception if instantiation fails */ public Object readLoader(Element node) throws Exception { Object result; Vector children; Element child; int i; String name; String file; File fl; // for debugging only if (DEBUG) trace(new Throwable(), node.getAttribute(ATT_NAME)); m_CurrentNode = node; result = Class.forName(node.getAttribute(ATT_CLASS)).newInstance(); children = XMLDocument.getChildTags(node); file = ""; Object relativeB = null; boolean relative = false; for (i = 0; i < children.size(); i++) { child = (Element) children.get(i); name = child.getAttribute(ATT_NAME); if (name.equals(VAL_FILE)) { file = (String) invokeReadFromXML(child); } else if (name.equals(VAL_RELATIVE_PATH)) { relativeB = readFromXML(child); if (relativeB instanceof Boolean) { relative = ((Boolean)relativeB).booleanValue(); } } else { readFromXML(result, name, child); } } if (result instanceof weka.core.converters.FileSourcedConverter) { ((weka.core.converters.FileSourcedConverter)result).setUseRelativePath(relative); } if (file.equals("")) file = null; // set file only, if it exists if (file != null) { String tempFile = file; boolean containsEnv = false; containsEnv = Environment.containsEnvVariables(file); fl = new File(file); // only test for existence if the path does not contain environment vars // (trust that after they are resolved that everything is hunky dory) if (containsEnv || fl.exists()) { ((weka.core.converters.AbstractFileLoader) result).setSource(new File(file)); } else { System.out.println("WARNING: The file '" + tempFile + "' does not exist!"); } } return result; } /** * adds the given Saver to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeSaver(Element parent, Object o, String name) throws Exception { Element node; weka.core.converters.Saver saver; File file; String prefix; String dir; boolean known; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; saver = (weka.core.converters.Saver) o; node = addElement(parent, name, saver.getClass().getName(), false); known = true; file = null; prefix = ""; dir = ""; // file if (saver instanceof weka.core.converters.AbstractFileSaver) { file = ((weka.core.converters.AbstractFileSaver) saver).retrieveFile(); prefix = ((weka.core.converters.AbstractFileSaver) saver).filePrefix(); dir = ((weka.core.converters.AbstractFileSaver) saver).retrieveDir(); // Replace any windows file separators with forward slashes (Java under windows can // read paths with forward slashes (apparantly) dir = dir.replace('\\', '/'); } else { known = false; } if (!known) System.out.println("WARNING: unknown saver class '" + saver.getClass().getName() + "' - cannot retrieve file!"); Boolean relativeB = null; if (saver instanceof weka.core.converters.FileSourcedConverter) { boolean relative = ((weka.core.converters.FileSourcedConverter)saver).getUseRelativePath(); relativeB = new Boolean(relative); } // if ( (file == null) || (file.isDirectory()) ) { invokeWriteToXML(node, "", VAL_FILE); invokeWriteToXML(node, dir, VAL_DIR); invokeWriteToXML(node, prefix, VAL_PREFIX); /* } else { String path = (((weka.core.converters.FileSourcedConverter) saver).getUseRelativePath()) ? file.getPath() : file.getAbsolutePath(); // Replace any windows file separators with forward slashes (Java under windows can // read paths with forward slashes (apparantly) path = path.replace('\\', '/'); invokeWriteToXML(node, path, VAL_FILE); invokeWriteToXML(node, dir, VAL_DIR); invokeWriteToXML(node, prefix, VAL_PREFIX); }*/ if (relativeB != null) { invokeWriteToXML(node, relativeB.toString(), VAL_RELATIVE_PATH); } return node; } /** * builds the Saver from the given DOM node. * * @param node the associated XML node * @return the instance created from the XML description * @throws Exception if instantiation fails */ public Object readSaver(Element node) throws Exception { Object result; Vector children; Element child; int i; String name; String file; String dir; String prefix; // for debugging only if (DEBUG) trace(new Throwable(), node.getAttribute(ATT_NAME)); m_CurrentNode = node; result = Class.forName(node.getAttribute(ATT_CLASS)).newInstance(); children = XMLDocument.getChildTags(node); file = null; dir = null; prefix = null; Object relativeB = null; boolean relative = false; for (i = 0; i < children.size(); i++) { child = (Element) children.get(i); name = child.getAttribute(ATT_NAME); if (name.equals(VAL_FILE)) { file = (String) invokeReadFromXML(child); } else if (name.equals(VAL_DIR)) { dir = (String) invokeReadFromXML(child); } else if (name.equals(VAL_PREFIX)) { prefix = (String) invokeReadFromXML(child); } else if (name.equals(VAL_RELATIVE_PATH)) { relativeB = readFromXML(child); if (relativeB instanceof Boolean) { relative = ((Boolean)relativeB).booleanValue(); } } else { readFromXML(result, name, child); } } if ( (file != null) && (file.length() == 0) ) file = null; // savers only get directory and prefix, not file (KnowledgeFlow sets the // file/destination based on the relation, dir and prefix) if ( (dir != null) && (prefix != null) ) { ((weka.core.converters.AbstractFileSaver) result).setDir(dir); ((weka.core.converters.AbstractFileSaver) result).setFilePrefix(prefix); } if (result instanceof weka.core.converters.FileSourcedConverter) { ((weka.core.converters.FileSourcedConverter)result).setUseRelativePath(relative); } return result; } /** * adds the given BeanVisual to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeBeanVisual(Element parent, Object o, String name) throws Exception { Element node; BeanVisual visual; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; visual = (BeanVisual) o; node = writeToXML(parent, o, name); // add icon paths invokeWriteToXML(node, visual.getIconPath(), VAL_ICONPATH); invokeWriteToXML(node, visual.getAnimatedIconPath(), VAL_ANIMATEDICONPATH); return node; } /** * builds the BeanVisual from the given DOM node. * * @param node the associated XML node * @return the instance created from the XML description * @throws Exception if instantiation fails */ public Object readBeanVisual(Element node) throws Exception { Object result; Vector children; Element child; int i; String name; String text; String iconPath; String animIconPath; // for debugging only if (DEBUG) trace(new Throwable(), node.getAttribute(ATT_NAME)); m_CurrentNode = node; result = null; children = XMLDocument.getChildTags(node); text = ""; iconPath = ""; animIconPath = ""; // find text for (i = 0; i < children.size(); i++) { child = (Element) children.get(i); name = child.getAttribute(ATT_NAME); if (name.equals(VAL_TEXT)) text = (String) invokeReadFromXML(child); else if (name.equals(VAL_ICONPATH)) iconPath = (String) invokeReadFromXML(child); else if (name.equals(VAL_ANIMATEDICONPATH)) animIconPath = (String) invokeReadFromXML(child); } result = new BeanVisual(text, iconPath, animIconPath); // set rest of properties for (i = 0; i < children.size(); i++) readFromXML(result, node.getAttribute(ATT_NAME), (Element) children.get(i)); return result; } /** * returns the IDs for the given BeanInstances, i.e., the stored IDs * in m_BeanInstancesID, based on m_BeanInstances * * @param beans the beans to retrieve the IDs for * @return the IDs for the given BeanInstances * @see #m_BeanInstances * @see #m_BeanInstancesID */ protected Vector getIDsForBeanInstances(Vector beans) { Vector result; int i; int pos; result = new Vector(); for (i = 0; i < beans.size(); i++) { pos = m_BeanInstances.indexOf(beans.get(i)); result.add(m_BeanInstancesID.get(pos)); } return result; } /** * adds the given MetaBean to a DOM structure. * * @param parent the parent of this object, e.g. the class this object is a member of * @param o the Object to describe in XML * @param name the name of the object * @return the node that was created * @throws Exception if the DOM creation fails */ public Element writeMetaBean(Element parent, Object o, String name) throws Exception { Element node; MetaBean meta; // for debugging only if (DEBUG) trace(new Throwable(), name); m_CurrentNode = parent; meta = (MetaBean) o; node = writeToXML(parent, o, name); invokeWriteToXML(node, getIDsForBeanInstances(meta.getBeansInInputs()), VAL_INPUTSID); invokeWriteToXML(node, getIDsForBeanInstances(meta.getBeansInOutputs()), VAL_OUTPUTSID); return node; } /** * returns a vector with references to BeanInstances according to the IDs * in the given Vector. * @param ids contains the IDs of the BeanInstances * @return the corresponding BeanInstances * @see #m_BeanInstances * @see #m_BeanInstancesID */ protected Vector getBeanInstancesForIDs(Vector ids) { Vector result; int i; int pos; result = new Vector(); for (i = 0; i < ids.size(); i++) { pos = m_BeanInstancesID.indexOf(ids.get(i)); result.add(m_BeanInstances.get(pos)); } return result; } /** * builds the MetaBean from the given DOM node. * * @param node the associated XML node * @return the instance created from the XML description * @throws Exception if instantiation fails */ public Object readMetaBean(Element node) throws Exception { Object result; Vector children; Element child; int i; String name; Vector inputs; Vector outputs; Vector coords; MetaBean bean; // for debugging only if (DEBUG) trace(new Throwable(), node.getAttribute(ATT_NAME)); m_CurrentNode = node; result = new MetaBean(); children = XMLDocument.getChildTags(node); inputs = new Vector(); outputs = new Vector(); coords = new Vector(); // the current MetaBean m_CurrentMetaBean = (MetaBean) result; for (i = 0; i < children.size(); i++) { child = (Element) children.get(i); name = child.getAttribute(ATT_NAME); if (name.equals(VAL_ASSOCIATEDCONNECTIONS)) ((MetaBean) result).setAssociatedConnections((Vector) invokeReadFromXML(child)); else if (name.equals(VAL_INPUTSID)) inputs = (Vector) invokeReadFromXML(child); else if (name.equals(VAL_OUTPUTSID)) outputs = (Vector) invokeReadFromXML(child); else if (name.equals(VAL_SUBFLOW)) ((MetaBean) result).setSubFlow((Vector) invokeReadFromXML(child)); else if (name.equals(VAL_ORIGINALCOORDS)) coords = (Vector) invokeReadFromXML(child); else if (name.equals(VAL_INPUTS)) System.out.println("INFO: '" + name + "' will be restored later."); else if (name.equals(VAL_OUTPUTS)) System.out.println("INFO: '" + name + "' will be restored later."); else readFromXML(result, name, child); } bean = (MetaBean) result; // set inputs and outputs, after the beans have been instantiated bean.setInputs(getBeanInstancesForIDs(inputs)); bean.setOutputs(getBeanInstancesForIDs(outputs)); bean.setOriginalCoords(coords); return result; } }