package __MASA_PACKAGE_thisagent;
//import __MASA_PACKAGE_thisagent__(*);
//import __MASA_PACKAGE_agentSystem__(AgentSystem.*);
import __MASA_PACKAGE_agent__(ASManagementAgent.*);
import __MASA_PACKAGE_agent__(*);
import __MASA_PACKAGE_agentSystem__(*);
import __MASA_PACKAGE__(tools.NameWrapper);
import __MASA_PACKAGE_CfMAF__(AgentStatus);
import org.omg.CosNaming.*;
import java.awt.*;
import java.applet.*;
import java.util.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import com.sun.java.swing.text.*;
import com.sun.java.swing.table.*;
import com.sun.java.swing.tree.*;
import com.sun.java.swing.event.*;
import org.omg.CosEventComm.*;
import org.omg.CosEventChannelAdmin.*;
/**
* This is the applet of the RegionManagementAgent.
* <br>Its main use is to display a split window the left half of which showing the currently active
* agent systems, the right half listing the agents loaded into these agent systems. One can also
* use the applet to call up the webpages/applets of the different agents and agent systems. Agents can be
* tranferred from one agent system to another.
*
* @author Stefan Gerber
*/
public class RegionManagementAgentApplet extends AgentApplet
{
/*
* CORBA reference to the agent system
*/
private AgentSystemService _ass;
private ASManagementAgent _asm;
private RegionManagementAgent _rma;
private JSplitPane splitpane;
private JScrollPane tree_panel;
private JScrollPane leaf_panel;
private DefaultMutableTreeNode root;
private JTree tree;
private DefaultTreeModel treemodel;
private AppletTableModel myModel;
private JTable agentTable;
private JPopupMenu popup;
private int row; //is set by the ListSelectionListener of agentTable
private Vector as_names; //needed primarily for invoking CommonAppletHelpers.show_migrate_menu()
private DefaultMutableTreeNode selected_node; //is set by the TreeSelectionListener of tree
private JPopupMenu as_popup;
private JButton updateTreeButton;
private JButton updateListButton;
private JPanel left_panel;
private JPanel right_panel;
private PushConsumerImpl pushConsumer;
/**
* Initialize this applet and connect to ASManagementAgent and RegionManagementAgent.
* <br>Sets and displays all JFC components and calls various methods to get initial information
* about the agent systems and their agents (e.g. list of active agent systems, list of agents loaded
* in the currently selected agent system)
*
* @see ASManagementAgent
*/
public void init() {
// Set layout to GridBag
GridBagLayout gridBag = new GridBagLayout();
getContentPane().setLayout(gridBag);
GridBagConstraints c_root = new GridBagConstraints();
// Connect to appropriate agent system
try {
org.omg.CORBA.Object obj = initCORBA("AgentSystemService");
_ass = AgentSystemServiceHelper.narrow(obj);
}
catch(java.net.MalformedURLException e) {
System.err.println(e.toString()+"\n");
}
catch(java.io.IOException ioe) {
System.err.println(ioe.toString()+"\n");
}
//get CORBA reference of the own agent system's ASManagementAgent
try {
org.omg.CORBA.Object objekt = initCORBA("ASManagementAgent");
_asm = ASManagementAgentHelper.narrow(objekt);
}
catch(java.net.MalformedURLException e) {
System.err.println(e.toString()+"\n");
}
catch(java.io.IOException ioe) {
System.err.println(ioe.toString()+"\n");
}
//get CORBA reference of the own RegionManagementAgent
try {
org.omg.CORBA.Object objekt = initCORBA("RegionManagementAgent");
_rma = RegionManagementAgentHelper.narrow(objekt);
}
catch(java.net.MalformedURLException e) {
System.err.println(e.toString()+"\n");
}
catch(java.io.IOException ioe) {
System.err.println(ioe.toString()+"\n");
}
// test if ASManagementAgent has been found
// if not, then display warning message
if (_asm == null) {
JOptionPane.showMessageDialog(null, "ASManagementAgent could not be found.\nPlease load it and restart the applet.");
}
else {
/***********************************************************
******* Panel for the tree ****************
***********************************************************/
//Create tree of currently active agent systems
create_tree();
//panel to the left which contains the tree
tree_panel = new JScrollPane(tree, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
tree_panel.setBorder(BorderFactory.createTitledBorder("Agent Systems & Co"));
//create Button that updates the agentsystems-tree
updateTreeButton = new JButton("update manually");
updateTreeButton.setMnemonic('u');
updateTreeButton.setToolTipText("update tree of agent systems manually");
updateTreeButton.setActionCommand("button");
updateTreeButton.setBackground(new Color(12632256));
updateTreeButton.setMargin(new Insets(2,2,2,2));
updateTreeButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
update_tree();
}
}
);
// Set layout of left_panel to GridBag
GridBagLayout left_gridBag = new GridBagLayout();
GridBagConstraints panel_constraints = new GridBagConstraints();
//create the panel that will contain the agentsystems-tree and the button(s)
left_panel = new JPanel(left_gridBag);
/***********************************************************
******* Panel for the agent table ****************
***********************************************************/
//Creating the table showing the agents of the selected system
myModel = new AppletTableModel();
myModel.AppletTableModel(); //create a new vector
agentTable = new JTable(myModel);
agentTable.setSelectionMode((new DefaultListSelectionModel()).SINGLE_SELECTION);
myModel.addTableModelListener(agentTable);
//add PopupMenu and MouseListener to agentTable
popup = create_popup();
//the global variabel row is set to the number of the row in agentTable selected by the user
MouseListener ml_table = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
String selected_cell = (String) selected_node.getUserObject();
if (!(selected_cell.equals("global")) &&
!(selected_cell.equals("voyager"))) { //if global or voyager are not selected
if (e.isPopupTrigger()) {
//right mouse button clicked
row = agentTable.rowAtPoint(e.getPoint()); //get row on which Mouse is located on
//check if agent is mobile
String impl_agents = CommonAppletHelpers.retrieve_implemented_agents_file(_ass.getURL());
java.util.StringTokenizer agent_tokenizer = new java.util.StringTokenizer(impl_agents);
String agent_type = new String();
while (agent_tokenizer.hasMoreTokens()) {
if ((agent_tokenizer.nextToken()).equals((String) myModel.getValueAt(row,0))) {
//if selected agent has been found in the list of implemented agents
agent_type = agent_tokenizer.nextToken(); //this is the agent´s package
agent_type = agent_tokenizer.nextToken(); //this is the agent´s type
break;
}
}
//then find out if selected agent is mobile
if (agent_type.equals("StationaryAgent")) { //agent cannot be migrated
//get menuitem "migrate" and disable it
JMenuItem mi = (JMenuItem) popup.getComponentAtIndex(0);
mi.setEnabled(false);
} else {
//get menuitem "migrate" and enable it
JMenuItem mi = (JMenuItem) popup.getComponentAtIndex(0);
mi.setEnabled(true);
}
popup.show(e.getComponent(), e.getX(), e.getY());
}
//if agent is double-clicked then show its webpage/applet
if (e.getClickCount() == 2) {
//Double Click
show_agents_webpage();
}
}
}
};
agentTable.addMouseListener(ml_table);
//create panel which contains agentTable
leaf_panel = new JScrollPane(agentTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
leaf_panel.setBorder(BorderFactory.createTitledBorder("Agents in selected agent aystem"));
//create Button that updates the list of agents
updateListButton = new JButton("update manually");
updateListButton.setMnemonic('p');
updateListButton.setToolTipText("update list of agents in selected agent system manually");
updateListButton.setActionCommand("button");
updateListButton.setBackground(new Color(12632256));
updateListButton.setMargin(new Insets(2,2,2,2));
updateListButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
list_agent_names();
}
}
);
// Set layout of right_panel to GridBag
GridBagLayout right_gridBag = new GridBagLayout();
//create the panel that will contain the list of agents and the button(s)
right_panel = new JPanel(right_gridBag);
/***********************************************************
******* add the components to their panels ****************
***********************************************************/
panel_constraints.fill = GridBagConstraints.BOTH;
panel_constraints.gridwidth = GridBagConstraints.REMAINDER;
panel_constraints.gridx = 0;
panel_constraints.weightx = 1;
panel_constraints.weighty = 1;
left_gridBag.setConstraints(tree_panel, panel_constraints);
left_panel.add(tree_panel);
right_gridBag.setConstraints(leaf_panel, panel_constraints);
right_panel.add(leaf_panel);
panel_constraints.fill = GridBagConstraints.HORIZONTAL;
panel_constraints.gridwidth = GridBagConstraints.REMAINDER;
panel_constraints.gridx = 0;
panel_constraints.weightx = 1;
panel_constraints.weighty = 0;
left_gridBag.setConstraints(updateTreeButton, panel_constraints);
left_panel.add(updateTreeButton);
right_gridBag.setConstraints(updateListButton, panel_constraints);
right_panel.add(updateListButton);
//create the splitpane to contain right_panel and left_panel
splitpane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left_panel, right_panel);
//splitpane.setDividerLocation(0.4); //ignored by JVM, reported Bug
splitpane.setPreferredSize(new Dimension(280, 520)); //workaround
splitpane.setBorder(BorderFactory.createLineBorder(new Color(255,255,255).lightGray, 5));
c_root.fill = GridBagConstraints.BOTH;
c_root.gridx = 0;
c_root.gridwidth = GridBagConstraints.REMAINDER;
c_root.gridheight = GridBagConstraints.REMAINDER;
c_root.weightx = c_root.weighty = 1.0;
gridBag.setConstraints(splitpane, c_root);
//add splitpane to Applet
getContentPane().add(splitpane);
//create pushConsumer and connect it to the ASManagementAgent
//needed to react to events from CORBA event service
create_pushConsumer();
}
}
/**
* Defines what´s to be done when applet is terminated.
* <br>Disconnects pushConsumer that has been registered with the ASManagementAgent
*/
public void destroy() {
try {
_asm.disconnect_push_consumer(pushConsumer.id);
} catch (Exception e) {
System.err.println("\n\nRegionManagementAgentApplet: Could not disconnect pushConsumer");
e.printStackTrace();
}
}
/**
* Opens a new browser window and displays the webpage of the agent system specified by "as".
* <br>The URL is achieved using the RegionManagementAgent method "get_AS_URL()", because the applet
* cannot communicate with an agent system not located on the same machine.
*
* @param as name of the agent system
*/
public void show_agentsystems_webpage(String as) {
try {
//generate URL of selected Agent system's webserver
java.net.URL url_target = new java.net.URL(_rma.get_AS_URL(as));
//Open new browser window and show agent system's webpage (titled "as")
getAppletContext().showDocument(url_target, as);
} catch (java.net.MalformedURLException mfe) {
mfe.printStackTrace();
}
}
/**
* Opens a new browser window and displays the webpage of the selected agent.
* <br>The URL is achieved using CommonAppletHelpers.getAgentURL(). This method is called
* when the user selects the appropriate menu item from the context menu of an agent.
*/
public void show_agents_webpage() {
//get name of selected agent. "row" has been set when right mouse button was clicked on the agent
String agent_identity = (String) myModel.getValueAt(row,0);
try {
//get the URL of the selected agent.
java.net.URL agent_url = CommonAppletHelpers.getAgentURL(agent_identity, _rma.get_AS_URL((String) selected_node.getUserObject()));
getAppletContext().showDocument(agent_url, agent_identity); //open another browser window and show agent's webpage
}
catch (Exception eaw) {
eaw.printStackTrace();
}
}
/**
* Creates and returns the popup menu for the tree of active agent systems.
* <br>The menu is shown, when the user right-clicks on an agent system in the tree.
*
* @param as name of agent system
* @return JPopupMenu for the agent system
*/
public JPopupMenu create_as_popup(final String as) {
JPopupMenu popup = new JPopupMenu();
//define menu item that will show the selected agent system´s webpage
JMenuItem mi = new JMenuItem("Show webpage");
mi.setActionCommand("show_webpage");
mi.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
show_agentsystems_webpage(as);
}
}
);
popup.add(mi);
JMenuItem mi2 = new JMenuItem("Terminate agent system");
mi2.setActionCommand("terminate_agent_system");
mi2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
try {
//give the user a last chance to cancel
int answer = JOptionPane.showConfirmDialog(null, "Do you really want to terminate this agent system?", "Warning!", JOptionPane.YES_NO_OPTION);
if (answer == JOptionPane.NO_OPTION) {
return;
}
_rma.terminate_agent_system(as);
} catch (Exception exc) {
exc.printStackTrace();
System.err.println("\nRegionManagementAgentApplet: terminate_agent_system failed!");
}
}
}
);
popup.add(mi2);
return popup;
}
/**
* Creates and returns the popup menu for the list of agents in the selected agent system.
* <br>The menu is shown, when the user right-clicks on an agent in the table.
*
* @return JPopupMenu for the agents
*/
public JPopupMenu create_popup() {
//define menu item that initiates transfer of an agent
JPopupMenu popup = new JPopupMenu();
JMenuItem mi = new JMenuItem("Migrate agent");
mi.setActionCommand("migrate");
mi.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
migrate_agent();
}
}
);
popup.add(mi);
//define menu item that will show the selected agent´s webpage
JMenuItem mi2 = new JMenuItem("Show webpage");
mi2.setActionCommand("Show_Webpage");
mi2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
show_agents_webpage();
}
}
);
popup.add(mi2);
return popup;
}
/**
* Transfers the agent selected in agentTable to another agent system.
* <br>This method is called when the user selects "Migrate Agent" from the context menu of an agent
* in the agentTable. The user is first presented with a dialogue where he can select the target
* agent system. After he has chosen the target the agent is transferred to it. This is done using
* the RegionManagementAgent because the applet cannot communicate with an agent system not located on
* the same machine.
*
* @see CommonAppletHelpers
*/
public void migrate_agent() {
//get the name of the selected agent
String agent_identity = (String) myModel.getValueAt(row,0);
//check if RegionManagementAgent is to be migrated and warn user
if(agent_identity.equals("RegionManagementAgent")) {
int answer = JOptionPane.showConfirmDialog(null, "Do you really want to migrate the RegionManagementAgent?\nThis applet would no longer work correctly\nif it belongs to this agent!", "Warning!", JOptionPane.YES_NO_OPTION);
if (answer == JOptionPane.NO_OPTION) {
return;
}
}
//get target agent system.
String target = CommonAppletHelpers.show_migrate_menu(this, agent_identity, as_names);
//initialize agentsystemservice object
String as = (String) selected_node.getUserObject(); //get name of agent system represented by the node
_rma.migrate_agent(agent_identity, target, as);
}
/**
* Sets up the tree of agent systems.
* <br>This method is called only once in the init() method of this applet. It identifies all currently
* active agent systems (via ASManagementAgent) and sets up the tree and its TreeModel with this
* information. In addition to this it generates a TreeSelectionListener and a MouseListener for
* the tree.
*/
public void create_tree() {
//set up tree components
root = new DefaultMutableTreeNode("Agent System Context");
treemodel = new DefaultTreeModel(root);
tree = new JTree(treemodel);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
//add a tree selection listener
//if a node is selected then the global variable "selected_node" is set to it and the list of
//agents in the agent system represented by this node is generated.
tree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
selected_node = (DefaultMutableTreeNode) (e.getPath().getLastPathComponent());
list_agent_names();
}
}
);
//create MouseListener for the tree
MouseListener ml_tree = new MouseAdapter() {
public void mousePressed(MouseEvent e)
{
TreePath tp = tree.getPathForLocation(e.getX(), e.getY());
tree.setSelectionPath(tp);
DefaultMutableTreeNode node = (DefaultMutableTreeNode) (tp.getLastPathComponent());
String as = (String) node.getUserObject(); //get name of agent system
if (!(as.equals("global")) &&
!(as.equals("voyager")) &&
!(as.equals("Agent System Context"))) {
if (e.getClickCount() == 2) {
//if double clicked then show the webpage for the agent system
show_agentsystems_webpage(as);
}
if (e.isPopupTrigger()) {
//if right clicked then show popup menu
as_popup = create_as_popup(as); //create Popup Menu
as_popup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
};
tree.addMouseListener(ml_tree);
//get list of active agent systems from ASManagementAgent and add it to the tree
String agentsystems[] = _asm.identify_agentsystems();
as_names = new java.util.Vector(0,1); //needed for CommonAppletHelpers.show_migrate_menu()
int n_o_t = agentsystems.length;
for (int i=0; i<n_o_t; i++) {
as_names.addElement(agentsystems[i]);
root.add(new DefaultMutableTreeNode(as_names.elementAt(i)));
}
//repaint the tree
treemodel.reload();
}
/**
* Refreshes the tree showing the active agent systems.
* <br>Invoked by the update-agent-system-list button. It fetches the list of active agent systems
* from the ASManagementAgent (because the applet cannot communicate with the CORBA name service
* directly) and recreates the tree with it.
*/
public void update_tree() {
root = new DefaultMutableTreeNode("Agent System Context"); //create a new root
//get list of active agent systems from ASManagementAgent and add it to the tree
String agentsystems[] = _asm.identify_agentsystems();
as_names = new java.util.Vector(0,1); //needed for CommonAppletHelpers.show_migrate_menu()
int n_o_t = agentsystems.length;
for (int i=0; i<n_o_t; i++) {
as_names.addElement(agentsystems[i]);
root.add(new DefaultMutableTreeNode(as_names.elementAt(i)));
}
treemodel.setRoot(root);
selected_node = (DefaultMutableTreeNode) treemodel.getChild(root, 0);
//repaint the tree
treemodel.reload();
}
/**
* Retrieves a list of agents on the selected agent system.
* <br>When the user selects an agent system in the tree this method is invoked by the tree´s
* TreeSelectionListener. It uses the RegionManagementAgent to get the list of agents in this agent system
* (because the applet cannot communicate with the CORBA name service directly), replaces the old
* information in the agentTable with it and repaints the table.
*/
public void list_agent_names() {
myModel.AppletTableModel(); //create new data vector
String agents[] = _rma.list_agent_names((String) selected_node.getUserObject());
int n_o_t = agents.length;
for (int i=0; i<n_o_t; i++) {
myModel.addValue(agents[i]);
}
getContentPane().validate();
leaf_panel.repaint();
agentTable.repaint();
}
/**
* Create a PushConsumer and register it with the ASManagementAgent.
* <br>The pushConsumer is then provided with CORBA events and reacts appropriately
*/
public void create_pushConsumer() {
try {
// create PushConsumer
pushConsumer = new PushConsumerImpl();
org.omg.CORBA.ORB orb =
CommonAppletHelpers.initialize_orb_for_push_consumer();
//use the Portable Object Adapter (POA) to register the object with the ORB
orb.connect(pushConsumer);
//register pushConsumer with the ASManagementAgent and retrieve the ID
//It is later used to disconnect the pushConsumer from the asm again
pushConsumer.id = _asm.connect_push_consumer(pushConsumer);
} catch (Exception el) {
el.printStackTrace();
}
}
/**
* Implements the PushConsumer that is connected to the ASManagementAgent.
* <br>The applet connects an instance of this class to the ASManagementAgent on startup. The agent calls
* the PushConsumer´s push() method when a CORBA event is registered and supplies the event data. The
* push() method defined in this class finds out which CORBA event occurred and reacts appropriately.
*
* @see ASManagementAgent
* @author Stefan Gerber
*/
class PushConsumerImpl extends _PushConsumerImplBase {
String[] event_data;
public int id = 0; //id of this pushConsumer, needed for disconnection from ASManagementAgent
public PushConsumerImpl()
{
System.err.println("\n\nRegionManagementAgentApplet: PushConsumer created");
}
public void push(org.omg.CORBA.Any any)
{
event_data = new String[5];
CosNotification.StructuredEvent se = CosNotification.StructuredEventHelper.extract(any);
event_data[0] = se.header.fixed_header.event_type.domain_name;
event_data[1] = se.header.fixed_header.event_type.type_name; //AgentUp/AgentDown/agentSystemUp/agentSystemDown
event_data[2] = se.filterable_data[0].value.extract_string(); //agent_type
event_data[3] = se.filterable_data[1].value.extract_string(); //agent_name/agent_system_ame
event_data[4] = se.filterable_data[2].value.extract_string(); //event_channel_name
if (event_data[1].equals("agentSystemUp")) { //new agent system was started
//add the name of the agent system to the as_names vector and to the tree
as_names.addElement(event_data[3]);
root.add(new DefaultMutableTreeNode(as_names.lastElement()));
//refresh the tree
treemodel.reload();
} else if (event_data[1].equals("agentSystemDown")) { //agent system was shut down
//select another node if selected_node is agentsystem to be removed
DefaultMutableTreeNode new_node = new DefaultMutableTreeNode();
if (((String) selected_node.getUserObject()).equals(event_data[3])) {
new_node = (DefaultMutableTreeNode) root.getChildBefore(selected_node);
if (new_node == null) {
//selected_node is already first child
new_node = (DefaultMutableTreeNode) root.getChildAfter(selected_node);
}
tree.setSelectionPath(new TreePath(new_node.getPath()));
}
//remove the agent system from as_names Vector
as_names.removeElement(event_data[3]);
//remove agent system from the tree
DefaultMutableTreeNode as_node;
for(int i = 0; i < root.getChildCount(); i++) { //scanning the tree for the node to remove
as_node = (DefaultMutableTreeNode) root.getChildAt(i);
if (((String) as_node.getUserObject()).equals(event_data[3])) { //node found
root.remove(as_node);
break;
}
}
//refresh tree
treemodel.reload();
} else if (event_data[1].equals("AgentUp")) { //new agent is up
//if agent system currently shown in agentTable equals the agent system where the new agent
//has been started up then add new agent to agentTable
if (((String) selected_node.getUserObject()).equals(event_data[0])) {
myModel.addValue(event_data[3]);
}
} else if (event_data[1].equals("AgentDown")) { //agent is down
//if agent system currently shown in agentTable equals the agent system where the agent
//has been terminated then remove agent from agentTable
if (((String) selected_node.getUserObject()).equals(event_data[0])) {
myModel.rmValue(myModel.whereis(event_data[3]));
}
}
}
public void disconnect_push_consumer() {
try {
// Initialize the ORB.
//org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
// Initialize the BOA.
//org.omg.CORBA.BOA boa = orb.BOA_init();
System.err.println("\n\nDisconnecting push_consumer...\n");
//boa.exit_impl_ready();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
/**
* TableModel managing the list of loaded agents in the selected agent system.
* <br>One column is defined, which contains the names of the currently loaded agents in the
* agent system selected in the tree.
*
* @see AbstractTableModel
* @author Stefan Gerber
*/
class AppletTableModel extends AbstractTableModel {
String[] columnNames = {"Agents"};
Vector data;
public void AppletTableModel()
{
data = new Vector(0,1);
}
public int getColumnCount()
{
return columnNames.length;
}
public int getRowCount()
{
return data.size();
}
public String getColumnName (int col)
{
return columnNames[col];
}
public Object getValueAt(int row, int col)
{
return (String) data.elementAt(row);
}
public void setValueAt(Object value, int row, int col)
{
data.setElementAt((String) value, row);
fireTableCellUpdated(row, col);
}
public void addValue(String value)
{
data.addElement(value);
fireTableRowsInserted(data.size()-1, data.size()-1);
}
public void rmValue(int row)
{
data.removeElementAt(row);
fireTableRowsDeleted(row, row);
}
//returns the row number where agent "an" is located
public int whereis(String an) {
for (int i=0; i<data.size(); i++) {
if (an.equals((String) data.elementAt(i))) return i;
}
return (-1);
}
}
}