diff --git a/tools/cooja/config/cooja_applet.config b/tools/cooja/config/cooja_applet.config index 7dc057cab..86d985f8d 100644 --- a/tools/cooja/config/cooja_applet.config +++ b/tools/cooja/config/cooja_applet.config @@ -2,4 +2,4 @@ se.sics.cooja.GUI.MOTETYPES = se.sics.cooja.motes.DisturberMoteType se.sics.cooj se.sics.cooja.GUI.PLUGINS = se.sics.cooja.plugins.VisState se.sics.cooja.plugins.VisTraffic se.sics.cooja.plugins.LogListener se.sics.cooja.plugins.MoteInformation se.sics.cooja.plugins.MoteInterfaceViewer se.sics.cooja.plugins.VariableWatcher se.sics.cooja.plugins.EventListener se.sics.cooja.plugins.RadioLogger se.sics.cooja.mspmote.plugins.MspCodeWatcher se.sics.cooja.mspmote.plugins.MspStackWatcher se.sics.cooja.mspmote.plugins.MspCycleWatcher se.sics.cooja.GUI.IP_DISTRIBUTORS = se.sics.cooja.ipdistributors.RandomIPDistributor se.sics.cooja.ipdistributors.SpatialIPDistributor se.sics.cooja.ipdistributors.IdIPDistributor se.sics.cooja.GUI.POSITIONERS = se.sics.cooja.positioners.RandomPositioner se.sics.cooja.positioners.LinearPositioner se.sics.cooja.positioners.EllipsePositioner se.sics.cooja.positioners.ManualPositioner -se.sics.cooja.GUI.RADIOMEDIUMS = se.sics.cooja.radiomediums.UDGM se.sics.cooja.radiomediums.SilentRadioMedium se.sics.mrm.MRM +se.sics.cooja.GUI.RADIOMEDIUMS = se.sics.cooja.radiomediums.UDGM se.sics.cooja.radiomediums.DirectedGraphMedium se.sics.mrm.MRM se.sics.cooja.radiomediums.SilentRadioMedium diff --git a/tools/cooja/config/cooja_default.config b/tools/cooja/config/cooja_default.config index fa706d2c5..e33ebab31 100644 --- a/tools/cooja/config/cooja_default.config +++ b/tools/cooja/config/cooja_default.config @@ -34,4 +34,4 @@ se.sics.cooja.GUI.MOTETYPES = se.sics.cooja.motes.DisturberMoteType se.sics.cooj se.sics.cooja.GUI.PLUGINS = se.sics.cooja.plugins.VisState se.sics.cooja.plugins.VisBattery se.sics.cooja.plugins.VisTraffic se.sics.cooja.plugins.LogListener se.sics.cooja.plugins.MoteInformation se.sics.cooja.plugins.MoteInterfaceViewer se.sics.cooja.plugins.VariableWatcher se.sics.cooja.plugins.EventListener se.sics.cooja.plugins.RadioLogger se.sics.cooja.plugins.ScriptRunner se.sics.cooja.GUI.IP_DISTRIBUTORS = se.sics.cooja.ipdistributors.RandomIPDistributor se.sics.cooja.ipdistributors.SpatialIPDistributor se.sics.cooja.ipdistributors.IdIPDistributor se.sics.cooja.GUI.POSITIONERS = se.sics.cooja.positioners.RandomPositioner se.sics.cooja.positioners.LinearPositioner se.sics.cooja.positioners.EllipsePositioner se.sics.cooja.positioners.ManualPositioner -se.sics.cooja.GUI.RADIOMEDIUMS = se.sics.cooja.radiomediums.UDGM se.sics.cooja.radiomediums.SilentRadioMedium +se.sics.cooja.GUI.RADIOMEDIUMS = se.sics.cooja.radiomediums.UDGM se.sics.cooja.radiomediums.DirectedGraphMedium se.sics.cooja.radiomediums.SilentRadioMedium diff --git a/tools/cooja/java/se/sics/cooja/plugins/DGRMConfigurator.java b/tools/cooja/java/se/sics/cooja/plugins/DGRMConfigurator.java new file mode 100644 index 000000000..618603c42 --- /dev/null +++ b/tools/cooja/java/se/sics/cooja/plugins/DGRMConfigurator.java @@ -0,0 +1,335 @@ +package se.sics.cooja.plugins; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.util.Observable; +import java.util.Observer; +import javax.swing.DefaultCellEditor; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JSpinner; +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.SpinnerNumberModel; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellEditor; + +import org.apache.log4j.Logger; + +import se.sics.cooja.ClassDescription; +import se.sics.cooja.GUI; +import se.sics.cooja.Mote; +import se.sics.cooja.PluginType; +import se.sics.cooja.Simulation; +import se.sics.cooja.VisPlugin; +import se.sics.cooja.radiomediums.DirectedGraphMedium; + +/** + * @author Fredrik Osterlind + */ +@ClassDescription("DGRM Configurator") +@PluginType(PluginType.SIM_PLUGIN) +public class DGRMConfigurator extends VisPlugin { + private static Logger logger = Logger.getLogger(DGRMConfigurator.class); + + private final static int IDX_SRC = 0; + private final static int IDX_DST = 1; + private final static int IDX_RATIO = 2; + private final static int IDX_DELAY = 3; + private final static int IDX_DEL = 4; + private final static String[] columns = new String[] { + "Source", "Destination", "Success Ratio (%)", "Delay (ms)", "Delete" + }; + + private GUI gui = null; + private DirectedGraphMedium radioMedium = null; + private Observer radioMediumObserver; + private JTable graphTable = null; + private JComboBox combo = new JComboBox(); + + public DGRMConfigurator(Simulation sim, GUI gui) { + super("DGRM Configurator", gui); + + this.gui = gui; + + radioMedium = (DirectedGraphMedium) sim.getRadioMedium(); + + /* Listen for graph updates */ + radioMedium.addRadioMediumObserver(radioMediumObserver = new Observer() { + public void update(Observable obs, Object obj) { + model.fireTableDataChanged(); + } + }); + + /* Represent directed graph by table */ + graphTable = new JTable(model) { + public TableCellEditor getCellEditor(int row, int column) { + if (column == IDX_RATIO) { + combo.removeAllItems(); + combo.addItem(1.0); + combo.addItem(0.9); + combo.addItem(0.8); + combo.addItem(0.7); + combo.addItem(0.6); + combo.addItem(0.5); + combo.addItem(0.4); + combo.addItem(0.3); + combo.addItem(0.2); + combo.addItem(0.1); + combo.addItem(0.1); + combo.addItem(0.0); + } + if (column == IDX_DELAY) { + combo.removeAllItems(); + combo.addItem(1); + combo.addItem(2); + combo.addItem(3); + combo.addItem(4); + combo.addItem(5); + } + + return super.getCellEditor(row, column); + } + public String getToolTipText(MouseEvent e) { + java.awt.Point p = e.getPoint(); + int row = rowAtPoint(p); + int col = convertColumnIndexToModel(columnAtPoint(p)); + + /* TODO */ + return super.getToolTipText(); + } + }; + combo.setEditable(true); + graphTable.getColumnModel().getColumn(2).setCellRenderer(new DefaultTableCellRenderer() { + public void setValue(Object value) { + if (!(value instanceof Double)) { + setText(value.toString()); + return; + } + double v = ((Double) value).doubleValue(); + setText((Math.round(v*1000.0) / 10.0) + "%"); + } + }); + graphTable.getColumnModel().getColumn(3).setCellRenderer(new DefaultTableCellRenderer() { + public void setValue(Object value) { + if (!(value instanceof Long)) { + setText(value.toString()); + return; + } + long v = ((Long) value).longValue(); + setText(v + " ms"); + } + }); + graphTable.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(combo)); + graphTable.getColumnModel().getColumn(3).setCellEditor(new DefaultCellEditor(combo)); + + graphTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); + graphTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + JButton button = new JButton("Add"); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + doAddLink(); + } + }); + final JScrollPane scrollPane = new JScrollPane(graphTable); + getContentPane().setLayout(new BorderLayout()); + add(BorderLayout.CENTER, scrollPane); + add(BorderLayout.SOUTH, button); + + model.fireTableDataChanged(); + } + + private void doAddLink() { + JComboBox source = new JComboBox(); + for (int i=0; i < gui.getSimulation().getMotesCount(); i++) { + source.addItem(gui.getSimulation().getMote(i)); + } + + JComboBox dest = new JComboBox(); + for (int i=0; i < gui.getSimulation().getMotesCount(); i++) { + dest.addItem(gui.getSimulation().getMote(i)); + } + dest.addItem("ALL"); + + JSpinner ratio = new JSpinner(new SpinnerNumberModel(1.0, 0.0, 1.0, 0.01)); + JSpinner delay = new JSpinner(new SpinnerNumberModel(0, 0, 100, 1)); + + /* User input */ + Object description[] = { + columns[0], + source, + columns[1], + dest, + columns[2], + ratio, + columns[3], + delay + }; + JOptionPane optionPane = new JOptionPane(); + optionPane.setMessage(description); + optionPane.setMessageType(JOptionPane.QUESTION_MESSAGE); + String options[] = new String[] {"Cancel", "Add"}; + optionPane.setOptions(options); + optionPane.setInitialValue(options[1]); + JDialog dialog = optionPane.createDialog(gui.getTopParentContainer(), title); + dialog.setTitle("Add new link"); + dialog.setVisible(true); + if (optionPane.getValue() == null || !optionPane.getValue().equals("Add")) { + return; + } + + /* Register new edge with radio medium */ + DirectedGraphMedium.Edge newEdge; + if (dest.getSelectedItem() instanceof Mote) { + newEdge = new DirectedGraphMedium.Edge( + (Mote) source.getSelectedItem(), + (Mote) dest.getSelectedItem(), + ((Number)ratio.getValue()).doubleValue(), + ((Number)delay.getValue()).longValue() + ); + } else { + newEdge = new DirectedGraphMedium.Edge( + (Mote) source.getSelectedItem(), + ((Number)ratio.getValue()).doubleValue(), + ((Number)delay.getValue()).longValue() + ); + } + radioMedium.addEdge(newEdge); + model.fireTableDataChanged(); + } + + private void doRemoveLink(DirectedGraphMedium.Edge edge) { + radioMedium.removeEdge(edge); + model.fireTableDataChanged(); + } + + final AbstractTableModel model = new AbstractTableModel() { + public String getColumnName(int column) { + if (column < 0 || column >= columns.length) { + logger.fatal("Unknown column: " + column); + return ""; + } + return columns[column]; + } + + public int getRowCount() { + return radioMedium.getEdges().length; + } + + public int getColumnCount() { + return columns.length; + } + + public Object getValueAt(int row, int column) { + if (row < 0 || row >= radioMedium.getEdges().length) { + logger.fatal("Unknown row: " + row); + return ""; + } + if (column < 0 || column >= columns.length) { + logger.fatal("Unknown column: " + column); + return ""; + } + + DirectedGraphMedium.Edge edge = radioMedium.getEdges()[row]; + if (column == IDX_SRC) { + if (edge.source == null) { + return "?"; + } + return edge.source; + } + if (column == IDX_DST) { + if (edge.dest == null) { + return "ALL"; + } + return edge.dest; + } + if (column == IDX_RATIO) { + return edge.successRatio; + } + if (column == IDX_DELAY) { + return edge.delay; + } + if (column == IDX_DEL) { + return new Boolean(false); + } + + logger.debug("Column data not implemented: " + column); + return "?"; + } + + public void setValueAt(Object value, int row, int column) { + if (row < 0 || row >= radioMedium.getEdges().length) { + logger.fatal("Unknown row: " + row); + return; + } + if (column < 0 || column >= columns.length) { + logger.fatal("Unknown column: " + column); + return; + } + + DirectedGraphMedium.Edge edge = radioMedium.getEdges()[row]; + if (column == IDX_RATIO) { + /* Success ratio */ + edge.successRatio = ((Number)value).doubleValue(); + radioMedium.setEdgesDirty(); + return; + } + if (column == IDX_DELAY) { + /* Propagation delay */ + edge.delay = ((Number)value).longValue(); + radioMedium.setEdgesDirty(); + return; + } + if (column == IDX_DEL) { + /* Delete link */ + doRemoveLink(edge); + return; + } + super.setValueAt(value, row, column); + } + + public boolean isCellEditable(int row, int column) { + if (row < 0 || row >= radioMedium.getEdges().length) { + return false; + } + + Mote sourceMote = radioMedium.getEdges()[row].source; + if (column == IDX_SRC) { + gui.signalMoteHighlight(sourceMote); + return false; + } + if (column == IDX_DST) { + if (radioMedium.getEdges()[row].dest != null) { + gui.signalMoteHighlight(radioMedium.getEdges()[row].dest); + } + return false; + } + if (column == IDX_RATIO) { + return true; + } + if (column == IDX_DELAY) { + return true; + } + if (column == IDX_DEL) { + return true; + } + return false; + } + + public Class getColumnClass(int c) { + return getValueAt(0, c).getClass(); + } + }; + + public void closePlugin() { + radioMedium.deleteRadioMediumObserver(radioMediumObserver); + } + +} diff --git a/tools/cooja/java/se/sics/cooja/radiomediums/DirectedGraphMedium.java b/tools/cooja/java/se/sics/cooja/radiomediums/DirectedGraphMedium.java new file mode 100644 index 000000000..0b04f58cb --- /dev/null +++ b/tools/cooja/java/se/sics/cooja/radiomediums/DirectedGraphMedium.java @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2009, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: DirectedGraphMedium.java,v 1.1 2009/02/24 15:29:52 fros4943 Exp $ + */ + +package se.sics.cooja.radiomediums; + +import java.util.*; + +import org.jdom.Element; +import org.apache.log4j.Logger; + +import se.sics.cooja.*; +import se.sics.cooja.interfaces.*; +import se.sics.cooja.plugins.DGRMConfigurator; + +/** + * @author Fredrik Osterlind + */ +@ClassDescription("Directed Graph Radio Medium (DGRM)") +public class DirectedGraphMedium extends AbstractRadioMedium { + private static Logger logger = Logger.getLogger(DirectedGraphMedium.class); + + /* Signal strengths in dBm. + * Approx. values measured on TmoteSky */ + public static final double SS_NOTHING = -100; + public static final double SS_STRONG = -10; + public static final double SS_WEAK = -95; + + private Simulation simulation; + private boolean edgesDirty = false; + private Random random = null; + + private DirectedGraphMedium.Edge edges[] = new DirectedGraphMedium.Edge[0]; + + public DirectedGraphMedium(Simulation simulation) { + super(simulation); + random = simulation.getRandomGenerator(); + + setEdgesDirty(); + + /* Register visualizer plugin */ + simulation.getGUI().registerTemporaryPlugin(DGRMConfigurator.class); + + this.simulation = simulation; + } + + public void addEdge(Edge e) { + DirectedGraphMedium.Edge newEdges[] = new DirectedGraphMedium.Edge[edges.length+1]; + System.arraycopy(edges, 0, newEdges, 0, edges.length); + + newEdges[newEdges.length-1] = e; + edges = newEdges; + setEdgesDirty(); + + ((AbstractRadioMedium.RadioMediumObservable) + this.getRadioMediumObservable()).setRadioMediumChangedAndNotify(); + } + + public void removeEdge(Edge edge) { + ArrayList list = new ArrayList(); + for (DirectedGraphMedium.Edge e: edges) { + list.add(e); + } + if (!list.contains(edge)) { + logger.fatal("Cannot remove edge: " + edge); + return; + } + list.remove(edge); + DirectedGraphMedium.Edge newEdges[] = new DirectedGraphMedium.Edge[list.size()]; + list.toArray(newEdges); + edges = newEdges; + setEdgesDirty(); + + ((AbstractRadioMedium.RadioMediumObservable) + this.getRadioMediumObservable()).setRadioMediumChangedAndNotify(); + } + + public void setEdgesDirty() { + edgesDirty = true; + } + + public Edge[] getEdges() { + return edges; + } + + public void registerMote(Mote mote, Simulation sim) { + super.registerMote(mote, sim); + + for (Edge edge: edges) { + if (edge.delayedLoadConfig != null) { + boolean ok = edge.setConfigXML(edge.delayedLoadConfig, sim); + if (ok) { + edge.delayedLoadConfig = null; + } + return; + } + } + + setEdgesDirty(); + } + + public void unregisterMote(Mote mote, Simulation sim) { + super.unregisterMote(mote, sim); + + for (Edge edge: edges) { + if (edge.source == mote || edge.dest == mote) { + removeEdge(edge); + } + } + + setEdgesDirty(); + } + + private class DestinationRadio { + Radio radio; + double ratio; + long delay; + + public DestinationRadio(Radio dest, double ratio, long delay) { + this.radio = dest; + + this.ratio = ratio; + this.delay = delay; + } + + public String toString() { + return radio.getMote().toString(); + } + } + + /* Used for optimizing lookup time */ + private Hashtable edgesTable = new Hashtable(); + + private void analyzeEdges() { + Hashtable> newTable = + new Hashtable>(); + + /* Fill edge hash table with all edges */ + for (Edge edge: edges) { + if (edge.source == null) { + return; /* Still dirty, wait until all edges are loaded */ + } + + ArrayList destRadios; + if (!newTable.containsKey(edge.source.getInterfaces().getRadio())) { + /* Create new source */ + destRadios = new ArrayList(); + } else { + /* Extend source radio with another destination */ + destRadios = newTable.get(edge.source.getInterfaces().getRadio()); + } + + DestinationRadio destRadio; + if (edge.dest == null) { + /* All radios */ + Vector allRadios = getRegisteredRadios(); + for (Radio r: allRadios) { + destRadio = new DestinationRadio(r, edge.successRatio, edge.delay); + destRadios.add(destRadio); + } + } else { + destRadio = new DestinationRadio(edge.dest.getInterfaces().getRadio(), edge.successRatio, edge.delay); + destRadios.add(destRadio); + } + + newTable.put(edge.source.getInterfaces().getRadio(), destRadios); + } + + /* Convert to arrays */ + Hashtable newTable2 = new Hashtable(); + Enumeration sources = newTable.keys(); + while (sources.hasMoreElements()) { + Radio source = sources.nextElement(); + ArrayList list = newTable.get(source); + DestinationRadio[] arr = new DestinationRadio[list.size()]; + list.toArray(arr); + newTable2.put(source, arr); + } + + this.edgesTable = newTable2; + edgesDirty = false; + } + + public RadioConnection createConnections(Radio source) { + if (edgesDirty) { + analyzeEdges(); + } + + /* Create new radio connection using edge hash table */ + DestinationRadio[] destinations = edgesTable.get(source); + if (destinations == null || destinations.length == 0) { + /* No destinations */ + /*logger.info(sendingRadio + ": No dest");*/ + return new RadioConnection(source); + } + + logger.info(source + ": " + destinations.length + " potential destinations"); + RadioConnection newConn = new RadioConnection(source); + for (DestinationRadio dest: destinations) { + if (dest.radio == source) { + /* Fail: cannot receive our own transmission */ + logger.info(source + ": Fail, receiver is sender"); + continue; + } + + if (dest.ratio < 1.0 && random.nextDouble() > dest.ratio) { + logger.info(source + ": Fail, randomly"); + continue; + } + + if (dest.radio.isReceiving()) { + /* Fail: radio is already actively receiving */ + logger.info(source + ": Fail, receiving"); + newConn.addInterfered(dest.radio); + + /* We will also interfere with the other connection */ + dest.radio.interfereAnyReception(); + RadioConnection otherConnection = null; + for (RadioConnection conn : getActiveConnections()) { + for (Radio dstRadio : conn.getDestinations()) { + if (dstRadio == dest.radio) { + otherConnection = conn; + break; + } + } + } + if (otherConnection != null) { + otherConnection.removeDestination(dest.radio); + otherConnection.addInterfered(dest.radio); + } + continue; + } + + if (dest.radio.isInterfered()) { + /* Fail: radio is interfered in another connection */ + logger.info(source + ": Fail, interfered"); + newConn.addInterfered(dest.radio); + continue; + } + + /* Success: radio starts receiving */ + logger.info(source + ": OK: " + dest.radio); + newConn.addDestination(dest.radio, dest.delay); + } + + return newConn; + } + + public void updateSignalStrengths() { + if (edgesDirty) { + analyzeEdges(); + } + + for (Radio radio : getRegisteredRadios()) { + radio.setCurrentSignalStrength(SS_NOTHING); + } + + for (RadioConnection conn : getActiveConnections()) { + conn.getSource().setCurrentSignalStrength(SS_STRONG); + for (Radio dstRadio : conn.getDestinations()) { + dstRadio.setCurrentSignalStrength(SS_STRONG); + } + } + + for (RadioConnection conn : getActiveConnections()) { + for (Radio intfRadio : conn.getInterfered()) { + intfRadio.setCurrentSignalStrength(SS_WEAK); + if (!intfRadio.isInterfered()) { + intfRadio.interfereAnyReception(); + } + } + } + + } + + public Collection getConfigXML() { + Vector config = new Vector(); + Element element; + + for (Edge edge: edges) { + element = new Element("edge"); + element.addContent(edge.getConfigXML()); + config.add(element); + } + + return config; + } + + public boolean setConfigXML(final Collection configXML, boolean visAvailable) { + random = simulation.getRandomGenerator(); + + for (Element element : configXML) { + if (element.getName().equals("edge")) { + Edge edge = new Edge(null, null, 0, 0); + edge.delayedLoadConfig = element.getChildren(); + addEdge(edge); + } + } + + setEdgesDirty(); + return true; + } + + public static class Edge { + public Mote source = null; + public Mote dest = null; /* null: all motes*/ + public double successRatio = 1.0; /* Link success ratio (per packet). */ + public long delay = 0; /* Propagation delay (milliseconds). */ + + public Edge(Mote source, double ratio, long delay) { + this.source = source; + this.successRatio = ratio; + this.delay = delay; + + this.dest = null; + } + + public Edge(Mote source, Mote dest, double ratio, long delay) { + this.source = source; + this.successRatio = ratio; + this.delay = delay; + + this.dest = dest; + } + + public Collection delayedLoadConfig = null; /* Used for restoring edges from config */ + public Collection getConfigXML() { + Vector config = new Vector(); + Element element; + + element = new Element("src"); + element.setText(source.toString()); + config.add(element); + + element = new Element("dest"); + if (dest == null) { + element.setText("ALL"); + } else { + element.setText(dest.toString()); + } + config.add(element); + + element = new Element("ratio"); + element.setText("" + successRatio); + config.add(element); + + element = new Element("delay"); + element.setText("" + delay); + config.add(element); + + return config; + } + public boolean setConfigXML(Collection configXML, Simulation simulation) { + for (Element element : configXML) { + if (element.getName().equals("src")) { + String moteDescription = element.getText(); + + boolean foundMote = false; + for (int i=0; i < simulation.getMotesCount(); i++) { + if (moteDescription.equals(simulation.getMote(i).toString())) { + foundMote = true; + source = simulation.getMote(i); + break; + } + } + + if (!foundMote) { + return false; + } + } + + if (element.getName().equals("dest")) { + String moteDescription = element.getText(); + + if (moteDescription.equals("ALL")) { + dest = null; /* ALL */ + } else { + boolean foundMote = false; + for (int i=0; i < simulation.getMotesCount(); i++) { + if (moteDescription.equals(simulation.getMote(i).toString())) { + foundMote = true; + dest = simulation.getMote(i); + break; + } + } + if (!foundMote) { + return false; + } + } + } + + if (element.getName().equals("ratio")) { + successRatio = Double.parseDouble(element.getText()); + } + + if (element.getName().equals("delay")) { + delay = Long.parseLong(element.getText()); + } + + } + return true; + } + } + +}