0001: /*
0002: * <copyright>
0003: *
0004: * Copyright 2000-2004 BBNT Solutions, LLC
0005: * under sponsorship of the Defense Advanced Research Projects
0006: * Agency (DARPA).
0007: *
0008: * You can redistribute this software and/or modify it under the
0009: * terms of the Cougaar Open Source License as published on the
0010: * Cougaar Open Source Website (www.cougaar.org).
0011: *
0012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0023: *
0024: * </copyright>
0025: */
0026:
0027: package org.cougaar.tools.csmart.ui.configbuilder;
0028:
0029: import org.cougaar.tools.csmart.core.cdata.ComponentData;
0030: import org.cougaar.tools.csmart.core.cdata.PropGroupData;
0031: import org.cougaar.tools.csmart.core.cdata.RelationshipData;
0032: import org.cougaar.tools.csmart.core.db.DBUtils;
0033: import org.cougaar.tools.csmart.core.property.BaseComponent;
0034: import org.cougaar.tools.csmart.core.property.ConfigurableComponent;
0035: import org.cougaar.tools.csmart.core.property.ModifiableComponent;
0036: import org.cougaar.tools.csmart.core.property.ModifiableConfigurableComponent;
0037: import org.cougaar.tools.csmart.core.property.PropertiesListener;
0038: import org.cougaar.tools.csmart.core.property.Property;
0039: import org.cougaar.tools.csmart.core.property.PropertyEvent;
0040: import org.cougaar.tools.csmart.core.property.PropertyHelper;
0041: import org.cougaar.tools.csmart.core.property.PropertyListener;
0042: import org.cougaar.tools.csmart.core.property.name.CompositeName;
0043: import org.cougaar.tools.csmart.recipe.CompleteAgentRecipe;
0044: import org.cougaar.tools.csmart.recipe.ComplexRecipeBase;
0045: import org.cougaar.tools.csmart.recipe.ComplexRecipeComponent;
0046: import org.cougaar.tools.csmart.recipe.ComponentCollectionRecipe;
0047: import org.cougaar.tools.csmart.recipe.RecipeQueryProperty;
0048: import org.cougaar.tools.csmart.society.*;
0049: import org.cougaar.tools.csmart.society.ui.AgentUIComponent;
0050: import org.cougaar.tools.csmart.society.ui.AssetUIComponent;
0051: import org.cougaar.tools.csmart.ui.Browser;
0052: import org.cougaar.tools.csmart.ui.experiment.PropTableModelBase;
0053: import org.cougaar.tools.csmart.ui.util.ComboDialog;
0054: import org.cougaar.tools.csmart.ui.viewer.CSMART;
0055: import org.cougaar.util.log.Logger;
0056:
0057: import javax.swing.*;
0058: import javax.swing.event.HyperlinkEvent;
0059: import javax.swing.event.HyperlinkListener;
0060: import javax.swing.event.TreeSelectionEvent;
0061: import javax.swing.event.TreeSelectionListener;
0062: import javax.swing.tree.DefaultMutableTreeNode;
0063: import javax.swing.tree.DefaultTreeCellRenderer;
0064: import javax.swing.tree.DefaultTreeModel;
0065: import javax.swing.tree.TreePath;
0066: import javax.swing.tree.TreeSelectionModel;
0067: import java.awt.*;
0068: import java.awt.event.ActionEvent;
0069: import java.awt.event.MouseAdapter;
0070: import java.awt.event.MouseEvent;
0071: import java.awt.event.MouseListener;
0072: import java.io.IOException;
0073: import java.io.ObjectInputStream;
0074: import java.net.URL;
0075: import java.util.ArrayList;
0076: import java.util.Collections;
0077: import java.util.Enumeration;
0078: import java.util.EventObject;
0079: import java.util.Hashtable;
0080: import java.util.Iterator;
0081: import java.util.List;
0082: import java.util.Set;
0083: import java.util.Vector;
0084:
0085: /**
0086: * Panel that holds the PropertyEditor for editing the properties of a <code>ModifiableConfigurableComponent</code>. <br>
0087: * It will both view a non-editable components, and edit an editable one.<br>
0088: * Note that you may in fact view/edit multiple components at once.
0089: */
0090: public class PropertyEditorPanel extends JPanel implements
0091: PropertiesListener, PropertyListener, TreeSelectionListener,
0092: HyperlinkListener {
0093: JSplitPane configCompPanel;
0094: JTree tree;
0095: JPopupMenu societyMenu;
0096: JPopupMenu bindersMenu;
0097: JPopupMenu componentsMenu;
0098: JPopupMenu pluginsMenu;
0099: //JPopupMenu assetMenu;
0100: JPopupMenu propertyGroupsMenu;
0101: JPopupMenu relationshipsMenu;
0102: JPopupMenu baseComponentMenu;
0103: JPopupMenu baseRecipeComponentMenu;
0104: JPopupMenu agentMenu;
0105: JPopupMenu completeAgentMenu;
0106: JPopupMenu componentCollectionRecipeMenu;
0107:
0108: DefaultMutableTreeNode root;
0109: PropertyTable propertyTable = null;
0110: JScrollPane tableScrollPane;
0111: // correspondence between configurable component and tree node
0112: private Hashtable componentToNode = new Hashtable();
0113: private Hashtable nodeToComponent = new Hashtable();
0114: Hashtable propertyToLabel = new Hashtable();
0115: boolean isEditable;
0116: ModifiableComponent componentToConfigure = null;
0117: private transient Logger log;
0118: // all property groups, including those created by user
0119: Vector propertyGroups = null;
0120: // properties we're listening on, for cleanup
0121: ArrayList listeningOnProperties = new ArrayList();
0122: // well known property groups
0123: Object[] wellKnownPropertyGroups = {
0124: PropGroupData.ITEM_IDENTIFICATION,
0125: PropGroupData.TYPE_IDENTIFICATION, PropGroupData.CLUSTER,
0126: PropGroupData.ORGANIZATION, PropGroupData.MILITARYORG,
0127: PropGroupData.ENTITY, PropGroupData.COMMUNITY,
0128: PropGroupData.ASSIGNMENT, PropGroupData.MAINTENANCE,
0129: PropGroupData.CSSCAPABILITY };
0130: // indices for above
0131: static final int ITEM_IDENTIFICATION = 0;
0132: static final int TYPE_IDENTIFICATION = 1;
0133: static final int CLUSTER = 2;
0134: static final int ENTITY = 3;
0135: static final int COMMUNITY = 4;
0136: static final int MILITARYORG = 5;
0137: static final int ASSIGNMENT = 6;
0138: static final int ORGANIZATION = 7;
0139: static final int MAINTENANCE = 8;
0140: static final int CSSCAPABILITY = 9;
0141:
0142: // actions for use on popup menus
0143: private AbstractAction addAgentAction = new AbstractAction(
0144: "Add Agent") {
0145: public void actionPerformed(ActionEvent e) {
0146: addAgent();
0147: }
0148: };
0149: private AbstractAction addBinderAction = new AbstractAction(
0150: "Add Binder") {
0151: public void actionPerformed(ActionEvent e) {
0152: addBinder();
0153: }
0154: };
0155: private AbstractAction addComponentAction = new AbstractAction(
0156: "Add Other Component") {
0157: public void actionPerformed(ActionEvent e) {
0158: addComponent();
0159: }
0160: };
0161: private AbstractAction addPluginAction = new AbstractAction(
0162: "Add Plugin") {
0163: public void actionPerformed(ActionEvent e) {
0164: addPlugin();
0165: }
0166: };
0167: private AbstractAction addPropertyGroupAction = new AbstractAction(
0168: "Add Property Group") {
0169: public void actionPerformed(ActionEvent e) {
0170: addPropertyGroup();
0171: }
0172: };
0173: private AbstractAction addRelationshipAction = new AbstractAction(
0174: "Add Relationship") {
0175: public void actionPerformed(ActionEvent e) {
0176: addRelationship();
0177: }
0178: };
0179: private AbstractAction addAssetParameterAction = new AbstractAction(
0180: "Add Parameter") {
0181: public void actionPerformed(ActionEvent e) {
0182: addParameter();
0183: }
0184: };
0185: // Used for PropertyGroups, Relationships, Binder, Plugins, Other Components
0186: // For the last three, we really want the argument to be false,
0187: // but within the method it resets it
0188: // if the component is a MiscComponent anyhow
0189: private AbstractAction addParameterAction = new AbstractAction(
0190: "Add Parameter") {
0191: public void actionPerformed(ActionEvent e) {
0192: addParameter(true);
0193: }
0194: };
0195: private AbstractAction deleteAction = new AbstractAction("Delete") {
0196: public void actionPerformed(ActionEvent e) {
0197: removeBaseComponent();
0198: }
0199: };
0200: private AbstractAction addTargetAction = new AbstractAction(
0201: "Override Parent Target") {
0202: public void actionPerformed(ActionEvent e) {
0203: addTarget(true);
0204: }
0205: };
0206:
0207: private AbstractAction addRecipeParameterAction = new AbstractAction(
0208: "Add Parameter") {
0209: public void actionPerformed(ActionEvent e) {
0210: addPropGroupParameter(true);
0211: }
0212: };
0213:
0214: private Object[] societyMenuItems = { addAgentAction };
0215: private Object[] completeAgentMenuItems = { addAgentAction };
0216: private Object[] componentCollectionRecipeMenuItems = {
0217: addAgentAction,
0218: // addBinderAction,
0219: addPluginAction
0220: // FIXME: Maybe do addComponent here?
0221: // addRelationshipAction,
0222: // addPropertyGroupAction
0223: };
0224:
0225: private Object[] bindersMenuItems = { addBinderAction };
0226: private Object[] componentsMenuItems = { addComponentAction };
0227: private Object[] pluginsMenuItems = { addPluginAction };
0228: // private Object[] assetMenuItems = {
0229: // addAssetParameterAction
0230: // };
0231: private Object[] propertyGroupsMenuItems = { addPropertyGroupAction };
0232: private Object[] relationshipsMenuItems = { addRelationshipAction };
0233: private Object[] baseComponentMenuItems = { addParameterAction,
0234: deleteAction };
0235: private Object[] baseRecipeComponentMenuItems = { addTargetAction,
0236: addParameterAction, deleteAction };
0237:
0238: private Object[] agentMenuItems = { deleteAction };
0239:
0240: /**
0241: * Create a <code>PropertyEditorPanel</code> which is
0242: * used to edit or view properties of societies and recipes.
0243: * @param c <code>ModifiableComponent</code> to edit or view
0244: * @param isEditable true if component can be edited
0245: */
0246: public PropertyEditorPanel(ModifiableComponent c, boolean isEditable) {
0247: // caller decides if this panel should allow editing
0248: this .isEditable = isEditable;
0249: // create the panel
0250: configCompPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
0251: setLayout(new BorderLayout());
0252: add(configCompPanel, BorderLayout.CENTER);
0253: componentToConfigure = c;
0254: init();
0255: createLogger();
0256: }
0257:
0258: private void createLogger() {
0259: log = CSMART.createLogger(this .getClass().getName());
0260: }
0261:
0262: /**
0263: * Set component to edit or view; used to re-use a running editor
0264: * to edit or view a different component.
0265: * @param c <code>ModifiableComponent</code> to edit or view
0266: */
0267: public void reinit(ModifiableComponent c) {
0268: componentToConfigure = c;
0269: init();
0270: }
0271:
0272: /**
0273: * Update the page being displayed in the browser.
0274: * @param e <code>HyperlinkEvent</code> containing the URL
0275: */
0276: public void hyperlinkUpdate(HyperlinkEvent e) {
0277: if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
0278: Browser.setPage(e.getURL());
0279: }
0280: }
0281:
0282: private void init() {
0283: if (tree != null)
0284: configCompPanel.remove(tree);
0285: // create tree and model before adding to it
0286: // as the add methods reference the tree and model
0287: root = new DefaultMutableTreeNode("Properties");
0288: tree = new JTree(new DefaultTreeModel(root));
0289: if (!isEditable) {
0290: DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
0291: renderer.setTextNonSelectionColor(Color.gray);
0292: renderer.setTextSelectionColor(Color.gray);
0293: tree.setCellRenderer(renderer);
0294: }
0295: makeTree();
0296: tree.expandPath(new TreePath(root));
0297: tree.setEditable(isEditable);
0298: // don't allow cell editing
0299: tree.setCellEditor(new DefaultCellEditor(new JTextField()) {
0300: public boolean isCellEditable(EventObject e) {
0301: return false;
0302: }
0303: });
0304: tree.getSelectionModel().setSelectionMode(
0305: TreeSelectionModel.SINGLE_TREE_SELECTION);
0306: tree.addTreeSelectionListener(this );
0307: MouseListener myMouseListener = new MouseAdapter() {
0308: public void mouseClicked(MouseEvent e) {
0309: if (e.isPopupTrigger())
0310: displayMenu(e);
0311: }
0312:
0313: public void mousePressed(MouseEvent e) {
0314: if (e.isPopupTrigger())
0315: displayMenu(e);
0316: }
0317:
0318: public void mouseReleased(MouseEvent e) {
0319: if (e.isPopupTrigger())
0320: displayMenu(e);
0321: }
0322: };
0323: tree.addMouseListener(myMouseListener);
0324: // create popup menus to be displayed in tree
0325: societyMenu = new JPopupMenu();
0326: completeAgentMenu = new JPopupMenu();
0327: componentCollectionRecipeMenu = new JPopupMenu();
0328: baseComponentMenu = new JPopupMenu();
0329: baseRecipeComponentMenu = new JPopupMenu();
0330: agentMenu = new JPopupMenu();
0331: bindersMenu = new JPopupMenu();
0332: componentsMenu = new JPopupMenu();
0333: pluginsMenu = new JPopupMenu();
0334: // assetMenu = new JPopupMenu();
0335: propertyGroupsMenu = new JPopupMenu();
0336: relationshipsMenu = new JPopupMenu();
0337: for (int i = 0; i < societyMenuItems.length; i++)
0338: societyMenu.add((Action) societyMenuItems[i]);
0339: for (int i = 0; i < completeAgentMenuItems.length; i++)
0340: completeAgentMenu.add((Action) completeAgentMenuItems[i]);
0341: for (int i = 0; i < componentCollectionRecipeMenuItems.length; i++)
0342: componentCollectionRecipeMenu
0343: .add((Action) componentCollectionRecipeMenuItems[i]);
0344: for (int i = 0; i < baseComponentMenuItems.length; i++)
0345: baseComponentMenu.add((Action) baseComponentMenuItems[i]);
0346: for (int i = 0; i < baseRecipeComponentMenuItems.length; i++)
0347: baseRecipeComponentMenu
0348: .add((Action) baseRecipeComponentMenuItems[i]);
0349: for (int i = 0; i < agentMenuItems.length; i++)
0350: agentMenu.add((Action) agentMenuItems[i]);
0351: for (int i = 0; i < bindersMenuItems.length; i++)
0352: bindersMenu.add((Action) bindersMenuItems[i]);
0353: for (int i = 0; i < componentsMenuItems.length; i++)
0354: componentsMenu.add((Action) componentsMenuItems[i]);
0355: for (int i = 0; i < pluginsMenuItems.length; i++)
0356: pluginsMenu.add((Action) pluginsMenuItems[i]);
0357: // for (int i = 0; i < assetMenuItems.length; i++)
0358: // assetMenu.add((Action)assetMenuItems[i]);
0359: for (int i = 0; i < propertyGroupsMenuItems.length; i++)
0360: propertyGroupsMenu.add((Action) propertyGroupsMenuItems[i]);
0361: for (int i = 0; i < relationshipsMenuItems.length; i++)
0362: relationshipsMenu.add((Action) relationshipsMenuItems[i]);
0363: configCompPanel.setLeftComponent(new JScrollPane(tree));
0364: propertyTable = new PropertyTable(isEditable);
0365: // don't allow user to reorder columns
0366: propertyTable.getTableHeader().setReorderingAllowed(false);
0367: if (!isEditable) {
0368: propertyTable.setForeground(Color.gray);
0369: }
0370: tableScrollPane = new JScrollPane(propertyTable);
0371: JPanel rightPanel = new JPanel(new BorderLayout());
0372: rightPanel.add(tableScrollPane);
0373: // only add description if user can edit the properties
0374: if (isEditable) {
0375: URL url = componentToConfigure.getDescription();
0376: if (url != null) {
0377: JTextPane pane = new JTextPane();
0378: try {
0379: pane.setEditable(false);
0380: pane.addHyperlinkListener(this );
0381: pane.setPage(url);
0382: rightPanel.add(pane, BorderLayout.NORTH);
0383: } catch (IOException ioe) {
0384: if (log.isErrorEnabled()) {
0385: log.error("Exception", ioe);
0386: }
0387: }
0388: } else {
0389: JLabel pane = new JLabel("No description available");
0390: rightPanel.add(pane, BorderLayout.NORTH);
0391: }
0392: }
0393: configCompPanel.setRightComponent(rightPanel);
0394: componentToConfigure.addPropertiesListener(this );
0395: configCompPanel.validate();
0396: configCompPanel.setDividerLocation(200);
0397: }
0398:
0399: /**
0400: * Make a tree from the property names in the selected configurable
0401: * component.
0402: */
0403:
0404: private void makeTree() {
0405: // get the list of configurable components to represent in the tree
0406: List components = new ArrayList();
0407: components.add(componentToConfigure);
0408: // for each configurable component
0409: for (int i = 0; i < components.size(); i++) {
0410: ModifiableComponent component = (ModifiableComponent) components
0411: .get(i);
0412: // determine where to put component in tree
0413: ModifiableComponent parentComponent = (ModifiableComponent) component
0414: .getParent();
0415: DefaultMutableTreeNode parentNode = root;
0416: if (parentComponent != null) {
0417: parentNode = (DefaultMutableTreeNode) componentToNode
0418: .get(parentComponent);
0419: if (parentNode == null)
0420: parentNode = root;
0421: }
0422: // add the component to the tree
0423: createTreeNode(component, parentNode);
0424: // add its children to the list of components to put in the tree
0425: int nChildren = component.getChildCount();
0426: for (int j = 0; j < nChildren; j++)
0427: components.add(component.getChild(j));
0428: }
0429: }
0430:
0431: /**
0432: * Display user interface components for property names in a table.
0433: * Called when user makes a selection in the tree.
0434: */
0435:
0436: private void displayComponents(PropertyTreeNode node) {
0437: ModifiableComponent component = (ModifiableComponent) nodeToComponent
0438: .get(node);
0439: for (Iterator i = component.getLocalPropertyNames(); i
0440: .hasNext();) {
0441: CompositeName propName = (CompositeName) i.next();
0442: Property property = component.getProperty(propName);
0443: if (property != null) {
0444: node.addPropertyName(propName);
0445: addTableEntryForProperty(property);
0446: }
0447: }
0448: }
0449:
0450: /**
0451: * Add table entry for a property.
0452: */
0453: private void addTableEntryForProperty(Property property) {
0454: propertyTable.addProperty(property);
0455: property.addPropertyListener(this );
0456: listeningOnProperties.add(property);
0457: }
0458:
0459: /**
0460: * PropertiesListener interface.
0461: */
0462:
0463: /**
0464: * A property was added by the configurable component.
0465: * This method is defined in the <code>PropertiesListener</code> interface.
0466: * Add the property name to the tree.
0467: * If the parent property name is selected in the tree,
0468: * then add an user interface component for this property
0469: * to the current display, otherwise the user interface component
0470: * is created when the parent property name is selected from the tree.
0471: * @param e <code>PropertyEvent</code> describing the property added
0472: */
0473: public void propertyAdded(PropertyEvent e) {
0474: Property prop = e.getProperty();
0475: // get the tree node for this property's configurable component
0476: ModifiableComponent cc = (ModifiableComponent) prop
0477: .getConfigurableComponent();
0478: PropertyTreeNode node = (PropertyTreeNode) componentToNode
0479: .get(cc);
0480: CompositeName name = prop.getName();
0481: if (node == null) {
0482: if (log.isErrorEnabled()) {
0483: log.error("No node for component: " + cc);
0484: }
0485: return;
0486: }
0487: if (node.addPropertyName(name)) {
0488: TreePath path = tree.getSelectionPath();
0489: if (path == null)
0490: return;
0491: // if it's a property of the selected tree node, then display it now
0492: PropertyTreeNode selectedNode = (PropertyTreeNode) path
0493: .getLastPathComponent();
0494: if (selectedNode.equals(node)) {
0495: if (log.isDebugEnabled()) {
0496: log.debug("PropertyBuilder: Property added: "
0497: + name);
0498: }
0499: addTableEntryForProperty(prop);
0500: }
0501: }
0502: }
0503:
0504: /**
0505: * A property was removed by the configurable component.
0506: * This method is defined in the <code>PropertiesListener</code> interface.
0507: * Remove the user interface component for the property and remove the
0508: * property from the tree, only if the property is found.
0509: * If we get notified because the property of a child node was removed,
0510: * this does the right thing -- i.e. it ignores the remove notification
0511: * because it doesn't find the specified property in the properties
0512: * for the tree node.
0513: * @param e <code>PropertyEvent</code> describing the property removed
0514: */
0515: public void propertyRemoved(PropertyEvent e) {
0516: Property prop = e.getProperty();
0517: ModifiableComponent cc = (ModifiableComponent) prop
0518: .getConfigurableComponent();
0519: PropertyTreeNode node = (PropertyTreeNode) componentToNode
0520: .get(cc);
0521: CompositeName name = prop.getName();
0522: if (node.removePropertyName(name)) {
0523: TreePath path = tree.getSelectionPath();
0524: if (path == null)
0525: return;
0526: PropertyTreeNode selectedNode = (PropertyTreeNode) path
0527: .getLastPathComponent();
0528: if (selectedNode.equals(node)) {
0529: if (log.isDebugEnabled()) {
0530: log.debug("PropertyBuilder: Property removed: "
0531: + prop.getName());
0532: }
0533: removeTableEntryForProperty(prop);
0534: }
0535: }
0536: }
0537:
0538: /**
0539: * End PropertiesListener interface.
0540: */
0541:
0542: /**
0543: * Remove table entry for a property, if it exists.
0544: */
0545: private void removeTableEntryForProperty(Property property) {
0546: propertyTable.removeProperty(property);
0547: property.removePropertyListener(this );
0548: listeningOnProperties.remove(property);
0549: }
0550:
0551: /**
0552: * The value of a property changed.
0553: * This method is defined in the <code>PropertyListener</code> interface.
0554: * If the configurable component (as opposed to the UI) initiates a change
0555: * then set the new value in the user inteface (table).
0556: * @param e <code>PropertyEvent</code> describing the property changed
0557: */
0558: public void propertyValueChanged(PropertyEvent e) {
0559: Property p = e.getProperty();
0560: p.removePropertyListener(this );
0561: listeningOnProperties.remove(p);
0562: int row = ((PropTableModelBase) (propertyTable.getModel()))
0563: .getRowForProperty(p);
0564: if (row != -1) {
0565:
0566: Object value = null;
0567: if (p.isValueSet())
0568: value = p.getValue();
0569: else
0570: value = "<not set>";
0571: Object valueInTable = propertyTable.getValueAt(row, 1);
0572: if (valueInTable.equals(value)) {
0573: p.addPropertyListener(this );
0574: listeningOnProperties.add(p);
0575: return; // don't need to update
0576: }
0577: propertyTable.setValueAt(p.getValue(), row, 1);
0578: propertyTable.revalidate();
0579: propertyTable.repaint();
0580: }
0581: p.addPropertyListener(this );
0582: listeningOnProperties.add(p);
0583: }
0584:
0585: /**
0586: * Some aspect of a property changed (i.e. new label, default value,
0587: * class or allowed values).
0588: * This method is defined in the <code>PropertyListener</code> interface.
0589: * Currently not implemented.
0590: * @param e <code>PropertyEvent</code> describing the property changed
0591: */
0592: public void propertyOtherChanged(PropertyEvent e) {
0593: // TODO: handle DEFAULTVALUE_CHANGED, LABEL_CHANGED,
0594: // CLASS_CHANGED, ALLOWEDVALUES_CHANGED
0595: }
0596:
0597: /**
0598: * End PropertyListener interface.
0599: */
0600:
0601: /**
0602: * TreeSelectionListener interface.
0603: */
0604:
0605: /**
0606: * If tree selection changes, update list of user interface components
0607: * displayed. Part of the <code>TreeSelectionListener</code> interface.
0608: * @param event the tree selection event describing the selection change
0609: */
0610: public void valueChanged(TreeSelectionEvent event) {
0611: TreePath path = event.getPath();
0612: if (path == null)
0613: return;
0614: Object o = path.getLastPathComponent();
0615: if (o instanceof PropertyTreeNode) {
0616: // stop any editing in progress in table and accept the value
0617: stopEditing();
0618: propertyTable.removeAll(); // clear what was displayed
0619: if (event.isAddedPath()) // display parameters for new selection
0620: displayComponents((PropertyTreeNode) o);
0621: }
0622: }
0623:
0624: /**
0625: * End TreeSelectionListener interface.
0626: */
0627:
0628: /**
0629: * Display popup menu with actions appropriate for the selected tree node.
0630: */
0631:
0632: private void displayMenu(MouseEvent e) {
0633: // the path to the node the mouse is pointing at
0634: TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
0635: if (selPath == null)
0636: return;
0637: tree.setSelectionPath(selPath);
0638: int x = e.getX();
0639: int y = e.getY();
0640: // show menu for type of node selected
0641: Object o = nodeToComponent.get(selPath.getLastPathComponent());
0642: if (o instanceof SocietyComponent)
0643: societyMenu.show(tree, x, y);
0644: else if (o instanceof ContainerComponent) {
0645: String name = ((ModifiableComponent) o).getShortName();
0646: if (name.equals("Binders"))
0647: bindersMenu.show(tree, x, y);
0648: else if (name.equals("Plugins"))
0649: pluginsMenu.show(tree, x, y);
0650: else if (name.equals("Other Components"))
0651: componentsMenu.show(tree, x, y);
0652: else if (name.equals("Relationships"))
0653: relationshipsMenu.show(tree, x, y);
0654: else if (name.equals("Property Groups"))
0655: propertyGroupsMenu.show(tree, x, y);
0656: } else if (o instanceof AssetComponent) {
0657: // Bug 1883: Don't allow deleting the AssetData, since you can't
0658: // add it back in again...
0659: //agentMenu.show(tree, x, y);
0660: } else if (o instanceof AgentComponent)
0661: agentMenu.show(tree, x, y);
0662: else if (o instanceof RelationshipComponent)
0663: agentMenu.show(tree, x, y);
0664: else if (o instanceof ComplexRecipeComponent) {
0665: if (o instanceof CompleteAgentRecipe)
0666: completeAgentMenu.show(tree, x, y);
0667: else if (o instanceof ComponentCollectionRecipe)
0668: componentCollectionRecipeMenu.show(tree, x, y);
0669: } else if (o instanceof BaseComponent) {
0670: // Need to see if the Parent is a ComponentCollectionRecipe.
0671: if (nodeToComponent.get(selPath.getParentPath()
0672: .getLastPathComponent()) instanceof ComponentCollectionRecipe)
0673: baseRecipeComponentMenu.show(tree, x, y);
0674: else
0675: baseComponentMenu.show(tree, x, y);
0676: } else if (o == null) {
0677: if (log.isInfoEnabled()) {
0678: log.info("No menu item for null component (root?).");
0679: }
0680: } else if (log.isInfoEnabled())
0681: log.info("No menu for component of class: " + o);
0682: }
0683:
0684: /**
0685: * Actions invoked from popup menu.
0686: */
0687:
0688: /**
0689: * Query the user for the name of the agent.
0690: * Create a component for the agent, and a tree node
0691: * representing the agent, and add it to the society node in the tree.
0692: * Create components and add tree nodes for Binders, Plugins and AssetData
0693: * folders.
0694: */
0695:
0696: private void addAgent() {
0697: DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) tree
0698: .getSelectionPath().getLastPathComponent();
0699: ModifiableComponent society = (ModifiableComponent) nodeToComponent
0700: .get(selNode);
0701:
0702: String name = (String) JOptionPane.showInputDialog(this ,
0703: "Enter Agent Name", "Agent Name",
0704: JOptionPane.QUESTION_MESSAGE, null, null, "");
0705: if (name == null)
0706: return;
0707:
0708: name = name.trim();
0709: if (name.equals(""))
0710: return;
0711:
0712: if (society instanceof ComplexRecipeComponent) {
0713: while (name.equals(society.getFullName().toString())) {
0714: if (log.isInfoEnabled())
0715: log
0716: .info("Cant add agent to Complex recipe with same name as recipe: "
0717: + name);
0718: name = (String) JOptionPane.showInputDialog(this ,
0719: "Enter Agent Name different from Recipe name",
0720: "Agent Name", JOptionPane.QUESTION_MESSAGE,
0721: null, null, name);
0722: if (name == null)
0723: return;
0724:
0725: name = name.trim();
0726: if (name.equals(""))
0727: return;
0728: }
0729: }
0730:
0731: AgentComponent agentComponent = (AgentComponent) new AgentUIComponent(
0732: name);
0733: // put the node in the tree before adding properties to it
0734: society.addChild(agentComponent);
0735: PropertyTreeNode agentNode = createTreeNode(agentComponent,
0736: selNode);
0737: agentComponent.initProperties();
0738: tree.setSelectionPath(tree.getSelectionPath()
0739: .pathByAddingChild(agentNode));
0740: addContainerComponent(agentNode, agentComponent,
0741: "Other Components");
0742: addContainerComponent(agentNode, agentComponent, "Binders");
0743: addContainerComponent(agentNode, agentComponent, "Plugins");
0744: AssetComponent asset = (AssetComponent) new AssetUIComponent();
0745: agentComponent.addChild(asset);
0746: PropertyTreeNode assetNode = createTreeNode(asset, agentNode);
0747: asset.initProperties();
0748: addContainerComponent(assetNode, asset, "Property Groups");
0749: addContainerComponent(assetNode, asset, "Relationships");
0750: }
0751:
0752: private void addContainerComponent(
0753: DefaultMutableTreeNode parentNode, BaseComponent parent,
0754: String name) {
0755: ContainerComponent containerComponent = (ContainerComponent) new ContainerBase(
0756: name);
0757: parent.addChild(containerComponent);
0758: createTreeNode(containerComponent, parentNode);
0759: containerComponent.initProperties();
0760: }
0761:
0762: /**
0763: * Remove base component from parent
0764: * and remove tree branch or node representing that base component.
0765: */
0766:
0767: private void removeBaseComponent() {
0768: DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) tree
0769: .getSelectionPath().getLastPathComponent();
0770: ModifiableComponent cc = (ModifiableComponent) nodeToComponent
0771: .get(selNode);
0772: Object parent = cc.getParent();
0773: if (parent != null && parent instanceof ModifiableComponent)
0774: ((ModifiableComponent) parent).removeChild(cc);
0775: // remove agent and subnodes from the tree
0776: removeTreeNodes(selNode);
0777: }
0778:
0779: /**
0780: * Query the user for the name of the bindere.
0781: * Create a component for the binder, and a tree node
0782: * representing the binder, and add it to the agent node in the tree.
0783: */
0784: private void addBinder() {
0785: Enumeration components = componentToNode.keys();
0786: ArrayList binderNames = new ArrayList();
0787: ArrayList binderClasses = new ArrayList();
0788: while (components.hasMoreElements()) {
0789: Object o = components.nextElement();
0790: if (o instanceof BinderComponent) {
0791: BinderComponent binder = (BinderComponent) o;
0792: String name = ((BaseComponent) binder).getShortName();
0793: if (name == null)
0794: continue;
0795: if (name.trim().equals(""))
0796: continue;
0797: // if name is prefixed with an agentname|, strip it off
0798: int index = name.indexOf('|');
0799: if (index != -1)
0800: name = name.substring(index + 1);
0801: if (!binderNames.contains(name)) {
0802: binderNames.add(name);
0803: binderClasses.add(binder.getComponentClassName());
0804: }
0805: }
0806: }
0807: // add in binder names and classes from the database
0808: Set dbBinderClasses = DBUtils.dbGetBinderClasses();
0809: for (Iterator i = dbBinderClasses.iterator(); i.hasNext();) {
0810: String dbBinderClass = (String) i.next();
0811: if (!binderClasses.contains(dbBinderClass)) {
0812: binderClasses.add(dbBinderClass);
0813: }
0814: }
0815:
0816: ArrayList sortedClasses = (ArrayList) binderClasses.clone();
0817: Collections.sort(sortedClasses);
0818: String className = (String) ComboDialog.showDialog(this ,
0819: "Select Binder or Enter New Class", new Vector(
0820: sortedClasses));
0821: if (className == null)
0822: return;
0823: className = className.trim();
0824: if (className.length() == 0)
0825: return;
0826: BinderComponent binder = new BinderBase(className, className,
0827: null);
0828: addBaseComponent(binder);
0829: binder.setComponentType(ComponentData.AGENTBINDER);
0830: }
0831:
0832: /**
0833: * Query the user for the name of the component.
0834: * Create a component for it, and a tree node
0835: * representing the component, and add it to the agent node in the tree.
0836: */
0837: private void addComponent() {
0838: // FIXME: Get the class from the user
0839: // and provide a drop-down, just like for plugins...
0840:
0841: // Also, get the component type from the user, using a drop
0842: // down that lists at least plugin, 2 binders
0843:
0844: String name = (String) JOptionPane.showInputDialog(this ,
0845: "Enter Component Name", "Component Name",
0846: JOptionPane.QUESTION_MESSAGE, null, null, "");
0847: if (name == null)
0848: return;
0849: name = name.trim();
0850: if (name.length() == 0)
0851: return;
0852: MiscComponent binder = new ComponentBase(name);
0853: addBaseComponent(binder);
0854: }
0855:
0856: /**
0857: * Query the user for the name of the plugin.
0858: * Create a component for the plugin, and a tree node
0859: * representing the plugin, and add it to the agent node in the tree.
0860: */
0861:
0862: private void addPlugin() {
0863: // get plugins from all existing agents
0864: Enumeration components = componentToNode.keys();
0865: ArrayList pluginNames = new ArrayList();
0866: ArrayList pluginClasses = new ArrayList();
0867: while (components.hasMoreElements()) {
0868: Object o = components.nextElement();
0869: if (o instanceof PluginComponent) {
0870: PluginComponent plugin = (PluginComponent) o;
0871: String name = ((BaseComponent) plugin).getShortName();
0872: if (name == null)
0873: continue;
0874: name = name.trim();
0875: if (name.equals(""))
0876: continue;
0877: // if name is prefixed with an agentname|, strip it off
0878: int index = name.indexOf('|');
0879: if (index != -1)
0880: name = name.substring(index + 1);
0881: if (!pluginNames.contains(name)) {
0882: pluginNames.add(name);
0883: pluginClasses.add(plugin.getComponentClassName());
0884: }
0885: }
0886: }
0887: // add in plugin names and classes from database
0888: Set dbPluginClasses = DBUtils.dbGetPluginClasses();
0889: for (Iterator i = dbPluginClasses.iterator(); i.hasNext();) {
0890: String dbPluginClass = (String) i.next();
0891: if (!pluginClasses.contains(dbPluginClass)) {
0892: pluginClasses.add(dbPluginClass);
0893: }
0894: }
0895:
0896: ArrayList sortedClasses = (ArrayList) pluginClasses.clone();
0897: Collections.sort(sortedClasses);
0898: String className = (String) ComboDialog.showDialog(this ,
0899: "Select Plugin or Enter New Class", new Vector(
0900: sortedClasses));
0901: if (className == null)
0902: return;
0903: className = className.trim();
0904: if (className.length() == 0)
0905: return;
0906:
0907: PluginComponent plugin = (PluginComponent) new PluginBase(
0908: className, className, null);
0909: addBaseComponent(plugin);
0910: }
0911:
0912: /**
0913: * Add base component to the component in the selected node.
0914: * Init the properties of the base component.
0915: * Make the new component be the selected node.
0916: */
0917: private void addBaseComponent(BaseComponent bc) {
0918: DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) tree
0919: .getSelectionPath().getLastPathComponent();
0920: BaseComponent parentBC = (BaseComponent) nodeToComponent
0921: .get(selNode);
0922: if (parentBC.getChild(bc.getFullName()) != null) {
0923: if (log.isDebugEnabled()) {
0924: log.debug("Duplicate Names, adjusting....");
0925: }
0926: bc.setName(bc.getFullName()
0927: + String.valueOf(parentBC.getChildCount()));
0928: }
0929:
0930: parentBC.addChild(bc);
0931: if (log.isDebugEnabled()) {
0932: log.debug("Adding Child: " + bc.getFullName());
0933: }
0934: DefaultMutableTreeNode newNode = createTreeNode(bc, selNode);
0935: bc.initProperties();
0936: tree.setSelectionPath(tree.getSelectionPath()
0937: .pathByAddingChild(newNode));
0938: }
0939:
0940: /**
0941: * Create component and tree node for new property group.
0942: */
0943: private void addPropertyGroup() {
0944: if (propertyGroups == null) {
0945: propertyGroups = new Vector(wellKnownPropertyGroups.length);
0946: for (int i = 0; i < wellKnownPropertyGroups.length; i++)
0947: propertyGroups.add(wellKnownPropertyGroups[i]);
0948: }
0949: String pgName = (String) ComboDialog.showDialog(this ,
0950: "Property Group", propertyGroups);
0951: if (pgName == null)
0952: return;
0953: int index = propertyGroups.indexOf(pgName);
0954: if (index == -1) {
0955: pgName = pgName.trim();
0956: if (pgName.length() == 0)
0957: return;
0958: }
0959: PropGroupData pgData = new PropGroupData(pgName);
0960: PropGroupComponent pg = (PropGroupComponent) new PropGroupBase(
0961: pgData);
0962: addBaseComponent(pg);
0963: // for each of the well defined properties
0964: // add the appropriate parameters
0965: if (index >= 0 && index < wellKnownPropertyGroups.length)
0966: setParameters(pg, index);
0967: else
0968: propertyGroups.add(pgName); // user defined property group
0969: }
0970:
0971: /**
0972: * Create component and tree node for new relationship.
0973: */
0974: private void addRelationship() {
0975: Vector relationships = new Vector();
0976:
0977: // DefaultMutableTreeNode selNode =
0978: // (DefaultMutableTreeNode)tree.getSelectionPath().getLastPathComponent();
0979: // relationship configurable components are created from relationship data
0980: RelationshipData relData = new RelationshipData();
0981:
0982: if (componentToConfigure instanceof ComplexRecipeComponent) {
0983: Set agentNames = DBUtils.dbGetAgentNames();
0984: for (Iterator i = agentNames.iterator(); i.hasNext();) {
0985: relationships.add((String) i.next());
0986: }
0987: } else {
0988:
0989: AgentComponent[] agents = ((SocietyComponent) componentToConfigure)
0990: .getAgents();
0991: for (int i = 0; i < agents.length; i++)
0992: relationships.add(agents[i].getShortName());
0993: }
0994: String relName = (String) ComboDialog.showDialog(this ,
0995: "Relationship With Agent", relationships);
0996: if (relName == null)
0997: return;
0998: int index = relationships.indexOf(relName);
0999: if (index == -1) {
1000: relName = relName.trim();
1001: if (relName.length() == 0)
1002: return;
1003: }
1004: relData.setSupported(relName);
1005: relData.setItemId(relName);
1006: relData.setType("");
1007: relData.setRole("");
1008:
1009: RelationshipComponent relationship = new RelationshipBase(
1010: relData);
1011: addBaseComponent(relationship);
1012: }
1013:
1014: /**
1015: * Add parameters for well know properties.
1016: */
1017: private void setParameters(ModifiableComponent pg, int pgIndex) {
1018: switch (pgIndex) {
1019: case ITEM_IDENTIFICATION:
1020: pg.addProperty("ItemIdentification (String)", "");
1021: pg.addProperty("Nomenclature (String)", "");
1022: pg.addProperty("AlternateItemIdentification (String)", "");
1023: break;
1024: case TYPE_IDENTIFICATION:
1025: pg.addProperty("TypeIdentification (String)", "UTC/RTOrg");
1026: break;
1027: case CLUSTER:
1028: // type is enclosed in parens and appended to name
1029: pg.addProperty("MessageAddress (MessageAddress)", "");
1030: break;
1031: case ENTITY:
1032: break;
1033: case COMMUNITY:
1034: // pg.addProperty("TimeSpan (TimeSpan)", "");
1035: // pg.addProperty("Communities (??)", "");
1036: break;
1037: case MILITARYORG:
1038: break;
1039: case ASSIGNMENT:
1040: break;
1041: case ORGANIZATION:
1042: // Service (Service)
1043: pg.addProperty("Service (Service)", "");
1044: // Agency (Agency)
1045: pg.addProperty("Agency (Agency)", "");
1046: // Roles (Collection<Role>)
1047: pg.addProperty("Roles (Role)", "");
1048: break;
1049: case MAINTENANCE:
1050: break;
1051: case CSSCAPABILITY:
1052: break;
1053: default:
1054: break;
1055: }
1056: }
1057:
1058: /**
1059: * Add a parameter to a configurable component. Invoked when the
1060: * user selects a tree node and invokes the "Add Parameter" option from
1061: * the pop-up menu. Note that this simply adds the parameter to the
1062: * configurable component corresponding to the tree node. It relies
1063: * on listeners that were previously set up on the configurable components
1064: * to update the user interface.
1065: */
1066: private void addParameter() {
1067: addParameter(true);
1068: }
1069:
1070: private void addParameter(boolean getName) {
1071: DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) tree
1072: .getSelectionPath().getLastPathComponent();
1073: ModifiableComponent cc = (ModifiableComponent) nodeToComponent
1074: .get(selNode);
1075:
1076: if (cc instanceof MiscComponent)
1077: getName = false;
1078:
1079: String name = "";
1080: if (getName) {
1081: name = (String) JOptionPane.showInputDialog(this ,
1082: "Enter Parameter Name", "Parameter Name",
1083: JOptionPane.QUESTION_MESSAGE, null, null, name);
1084: if (name == null)
1085: return;
1086: name = name.trim(); // trim white space
1087: if (name.length() == 0)
1088: return;
1089: }
1090:
1091: String type = "";
1092: if (cc instanceof PropGroupComponent) {
1093: type = (String) JOptionPane.showInputDialog(this ,
1094: "Enter Parameter Type", "Parameter Type",
1095: JOptionPane.QUESTION_MESSAGE, null, null, "String");
1096: type = type.trim();
1097: name = name + " (" + type + ")";
1098: // FIXME: How do we handle getting a PG MultiVal?
1099: }
1100:
1101: String value = (String) JOptionPane.showInputDialog(this ,
1102: "Enter Parameter Value", "Parameter Value",
1103: JOptionPane.QUESTION_MESSAGE, null, null, "");
1104: if (value == null)
1105: return;
1106: value = value.trim(); // trim white space
1107: if (value.length() == 0)
1108: return;
1109:
1110: // Allow lists
1111: Object realValue = null;
1112: if (value.startsWith("[") && value.endsWith("]")) {
1113: realValue = PropertyHelper.convertStringToArrayList(value);
1114: } else if (value.startsWith("{") && value.endsWith("}")) {
1115: realValue = PropertyHelper.convertStringToArray(value);
1116: } else {
1117: realValue = value;
1118: }
1119:
1120: if (getName) {
1121: // FIXME: See if the name is unique. If not, then what?
1122: cc.addProperty(name, realValue);
1123: } else {
1124: cc.addProperty(generateName((ConfigurableComponent) cc),
1125: realValue);
1126: }
1127: }
1128:
1129: private void addPropGroupParameter() {
1130: addPropGroupParameter(true);
1131: }
1132:
1133: private void addPropGroupParameter(boolean getName) {
1134: DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) tree
1135: .getSelectionPath().getLastPathComponent();
1136: ModifiableComponent cc = (ModifiableComponent) nodeToComponent
1137: .get(selNode);
1138:
1139: if (cc instanceof MiscComponent)
1140: getName = false;
1141:
1142: String name = "";
1143: if (getName) {
1144: name = (String) JOptionPane.showInputDialog(this ,
1145: "Enter Parameter Name", "Parameter Name",
1146: JOptionPane.QUESTION_MESSAGE, null, null, name);
1147: if (name == null)
1148: return;
1149: name = name.trim(); // trim white space
1150: if (name.length() == 0)
1151: return;
1152: }
1153:
1154: String type = "";
1155: type = (String) JOptionPane.showInputDialog(this ,
1156: "Enter Parameter Type", "Parameter Type",
1157: JOptionPane.QUESTION_MESSAGE, null, null, type);
1158: type = type.trim();
1159: name = name + " (" + type + ")";
1160:
1161: String value = (String) JOptionPane.showInputDialog(this ,
1162: "Enter Parameter Value", "Parameter Value",
1163: JOptionPane.QUESTION_MESSAGE, null, null, "");
1164: if (value == null)
1165: return;
1166: value = value.trim(); // trim white space
1167: if (value.length() == 0)
1168: return;
1169:
1170: // Allow lists
1171: Object realValue = null;
1172: if (value.startsWith("[") && value.endsWith("]")) {
1173: realValue = PropertyHelper.convertStringToArrayList(value);
1174: } else if (value.startsWith("{") && value.endsWith("}")) {
1175: realValue = PropertyHelper.convertStringToArray(value);
1176: } else {
1177: realValue = value;
1178: }
1179:
1180: if (getName) {
1181: cc.addProperty(name, realValue);
1182: } else {
1183: cc.addProperty(generateName((ConfigurableComponent) cc),
1184: realValue);
1185: }
1186: }
1187:
1188: private void addTarget() {
1189: addTarget(true);
1190: }
1191:
1192: private void addTarget(boolean getName) {
1193: DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) tree
1194: .getSelectionPath().getLastPathComponent();
1195: ModifiableConfigurableComponent cc = (ModifiableConfigurableComponent) nodeToComponent
1196: .get(selNode);
1197: cc.addProperty(new RecipeQueryProperty(cc,
1198: ComplexRecipeBase.PROP_TARGET_COMPONENT_QUERY,
1199: "recipeQuerySelectNothing"));
1200: cc.getProperty(ComplexRecipeBase.PROP_TARGET_COMPONENT_QUERY)
1201: .setPropertyClass(String.class);
1202: }
1203:
1204: private String generateName(ConfigurableComponent cc) {
1205: // get all properties
1206: Iterator i = cc.getSortedLocalPropertyNames();
1207: // find the highest numbered property of the form param-x
1208: int lastParamNumber = -1;
1209: while (i.hasNext()) {
1210: String name = ((CompositeName) i.next()).last().toString();
1211: int index = name.indexOf("param-");
1212: if (index == -1)
1213: continue;
1214: int curNum = -1;
1215: try {
1216: curNum = Integer.parseInt(name.substring(index + 6));
1217: } catch (NumberFormatException nfe) {
1218: //System.out.println("NFE: " + nfe);
1219: // just ignore
1220: }
1221: if (curNum > lastParamNumber)
1222: lastParamNumber = curNum;
1223: }
1224: // generate next highest numbered name
1225: lastParamNumber++;
1226: String name = "param-" + String.valueOf(lastParamNumber);
1227: return name;
1228: }
1229:
1230: /**
1231: * Create a tree node for the configurable component,
1232: * and add it to the parent tree node.
1233: * Also, put the component and the new node in hashtables to facilitate
1234: * matching tree nodes to components.
1235: * Return the new tree node.
1236: */
1237: private PropertyTreeNode createTreeNode(BaseComponent component,
1238: DefaultMutableTreeNode parentNode) {
1239: PropertyTreeNode newNode = new PropertyTreeNode(component
1240: .getFullName());
1241: if (component instanceof AssetComponent
1242: || component instanceof ContainerComponent)
1243: newNode.setLeaf(false);
1244: DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
1245: model.insertNodeInto(newNode, parentNode, parentNode
1246: .getChildCount());
1247: componentToNode.put(component, newNode);
1248: nodeToComponent.put(newNode, component);
1249: return newNode;
1250: }
1251:
1252: /**
1253: * Remove node and its children from tree and
1254: * remove node and its children from the hashtables.
1255: */
1256:
1257: private void removeTreeNodes(DefaultMutableTreeNode nodeToRemove) {
1258: Enumeration nodesToRemove = nodeToRemove
1259: .depthFirstEnumeration();
1260: while (nodesToRemove.hasMoreElements()) {
1261: DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodesToRemove
1262: .nextElement();
1263: ModifiableComponent cc = (ModifiableComponent) nodeToComponent
1264: .get(node);
1265: componentToNode.remove(cc);
1266: nodeToComponent.remove(node);
1267: }
1268: DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
1269: model.removeNodeFromParent(nodeToRemove);
1270: }
1271:
1272: /**
1273: * Stop editing in table and accept changes.
1274: */
1275:
1276: public void stopEditing() {
1277: int row = propertyTable.getEditingRow();
1278: int column = propertyTable.getEditingColumn();
1279: if (row != -1 && column != -1)
1280: propertyTable.getCellEditor(row, column).stopCellEditing();
1281: }
1282:
1283: /**
1284: * Remove this object as a listener on the configurable component.
1285: */
1286:
1287: public void exit() {
1288: componentToConfigure.removePropertiesListener(this );
1289: for (int i = 0; i < listeningOnProperties.size(); i++)
1290: ((Property) listeningOnProperties.get(i))
1291: .removePropertyListener(this );
1292: }
1293:
1294: private void readObject(ObjectInputStream ois) throws IOException,
1295: ClassNotFoundException {
1296: ois.defaultReadObject();
1297: createLogger();
1298: }
1299:
1300: }
|