components/visual-panels/usermgr/src/java/vpanels/app/usermgr/com/oracle/solaris/vp/panels/usermgr/client/swing/AuthRightsPanel.java
changeset 1305 d11b04684351
equal deleted inserted replaced
1304:428fd83fdeb2 1305:d11b04684351
       
     1 /*
       
     2  * CDDL HEADER START
       
     3  *
       
     4  * The contents of this file are subject to the terms of the
       
     5  * Common Development and Distribution License (the "License").
       
     6  * You may not use this file except in compliance with the License.
       
     7  *
       
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
     9  * or http://www.opensolaris.org/os/licensing.
       
    10  * See the License for the specific language governing permissions
       
    11  * and limitations under the License.
       
    12  *
       
    13  * When distributing Covered Code, include this CDDL HEADER in each
       
    14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    15  * If applicable, add the following below this CDDL HEADER, with the
       
    16  * fields enclosed by brackets "[]" replaced with your own identifying
       
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    18  *
       
    19  * CDDL HEADER END
       
    20  */
       
    21 
       
    22 /*
       
    23  * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
       
    24  */
       
    25 
       
    26 package com.oracle.solaris.vp.panels.usermgr.client.swing;
       
    27 
       
    28 import javax.swing.*;
       
    29 import javax.swing.event.*;
       
    30 import javax.swing.tree.*;
       
    31 import javax.swing.border.*;
       
    32 
       
    33 import java.awt.*;
       
    34 import java.awt.event.*;
       
    35 import java.util.*;
       
    36 
       
    37 import com.oracle.solaris.vp.util.misc.finder.Finder;
       
    38 
       
    39 /**
       
    40  * SMC code adapted for Visual Panels
       
    41  *
       
    42  * Rights Profiles Panel for Rights Settings
       
    43  */
       
    44 public class AuthRightsPanel extends JPanel {
       
    45 
       
    46 
       
    47     public static Arranger profPanel;
       
    48     private static DblTreeNode srcRoot;
       
    49     private static DblTreeNode dstRoot;
       
    50     private DefaultTreeModel srcModel, dstModel;
       
    51 
       
    52     private DblTreeNode [] profNodes;
       
    53     private ProfTreeNode [] profTreeNodes;
       
    54 
       
    55     private ProfTreeNode currProfTreeNode;
       
    56     private DblTreeNode currDblTreeNode;
       
    57 
       
    58     private String targetRightName;
       
    59     private String targetRight;
       
    60     private JPanel securityPanel;
       
    61 
       
    62     private UserManagedObject userObj = null;
       
    63     private UserMgrPanelDescriptor panelDesc = null;
       
    64 
       
    65     private Vector vAllRightObjs = null;
       
    66 
       
    67     private boolean isProfListOK = true;
       
    68 
       
    69     /**
       
    70      * Constructs a panel to contain supplementary rights properties for
       
    71      * the right object.
       
    72      */
       
    73     public AuthRightsPanel(UserMgrPanelDescriptor panelDesc,
       
    74         UserManagedObject userObj) {
       
    75 
       
    76 	super();
       
    77 	this.panelDesc = panelDesc;
       
    78 	this.userObj = userObj;
       
    79 
       
    80 	createGui();
       
    81 	loadProfiles();
       
    82     } // constructor
       
    83 
       
    84 
       
    85     /**
       
    86      * Method for creating GUI
       
    87      */
       
    88     private void createGui() {
       
    89 
       
    90 	// Set the panel layout
       
    91 	GridBagConstraints gbc = new GridBagConstraints();
       
    92 	this.setLayout(new GridBagLayout());
       
    93 
       
    94 	// Excluded and Included rights panel
       
    95    	securityPanel = null;
       
    96 
       
    97 	profPanel = new Arranger("usermgr.advanced.auth_rights.available",
       
    98 		"usermgr.advanced.auth_rights.granted");
       
    99 
       
   100 	Dimension dimension = new Dimension(200, 300);
       
   101 	profPanel.srcTree.setCellRenderer(new ProfileRenderer(this));
       
   102 	profPanel.srcTree.setVisibleRowCount(10);
       
   103 	profPanel.srcTree.setSize(dimension);
       
   104 
       
   105 	profPanel.dstTree.setCellRenderer(new ProfileRenderer(this));
       
   106 	profPanel.dstTree.setVisibleRowCount(10);
       
   107 	profPanel.dstTree.setSize(dimension);
       
   108 
       
   109 	Constraints.constrain(this, profPanel,
       
   110 		0, 0, 1, 1,
       
   111 		gbc.BOTH, gbc.CENTER,
       
   112 		1.0, 1.0, 10, 10, 10, 10);
       
   113 
       
   114     } // end createGui
       
   115 
       
   116 
       
   117     /**
       
   118      * Load the Source and Destination trees for rights excluded and
       
   119      * included lists.
       
   120      */
       
   121     private void loadProfiles() {
       
   122 
       
   123 	// Reset the data models. So old data is discarded
       
   124 	profPanel.resetModels();
       
   125 
       
   126 
       
   127 	// Initialize the excluded rights list with all profiles
       
   128 	// except for the current one, since a profile can not be
       
   129 	// assigned to itself. Note that all profiles are created
       
   130 	// as top-level profiles.
       
   131 
       
   132 	vAllRightObjs = getAvailableProfs();
       
   133 
       
   134 	srcModel = (DefaultTreeModel) profPanel.srcTree.getModel();
       
   135 	srcRoot = (DblTreeNode) srcModel.getRoot();
       
   136 
       
   137 	dstModel = (DefaultTreeModel) profPanel.dstTree.getModel();
       
   138 	dstRoot = (DblTreeNode) dstModel.getRoot();
       
   139 
       
   140 	profNodes = new DblTreeNode[vAllRightObjs.size()];
       
   141 	profTreeNodes = new ProfTreeNode[vAllRightObjs.size()];
       
   142 
       
   143 	int n = 0;
       
   144 	Enumeration e = vAllRightObjs.elements();
       
   145 
       
   146 	// Build an array of tree nodes that can be used for sorting.
       
   147 
       
   148 	while (e.hasMoreElements()) {
       
   149 	    String rightObj = (String)e.nextElement();
       
   150 	    String rightName = rightObj;
       
   151 
       
   152 	    profTreeNodes[n] = new ProfTreeNode(rightObj);
       
   153 
       
   154 	    n++;
       
   155 	}
       
   156 
       
   157 	// Sort the list of ProfTreeNode objects.
       
   158 
       
   159 	if (profTreeNodes.length > 1) {
       
   160 	    NodeCompare comp = new NodeCompare();
       
   161 	    Sort.sort(profTreeNodes, comp);
       
   162 	}
       
   163 
       
   164 	// With the sorted tree nodes, now we build the src tree.
       
   165 	for (int i = 0; i < profTreeNodes.length; i++) {
       
   166 	    profNodes[i] = new DblTreeNode((Object)profTreeNodes[i]);
       
   167 
       
   168 	    srcModel.insertNodeInto(profNodes[i], srcRoot, i);
       
   169 	    TreePath nodepath = new TreePath(profNodes[i].getPath());
       
   170 	    // Make initial display of excluded list
       
   171 	    profPanel.srcTree.scrollPathToVisible(nodepath);
       
   172 	}
       
   173 
       
   174 
       
   175 	// Set TreeModel listeners
       
   176 	srcModel.addTreeModelListener(new TreeModelListener() {
       
   177 
       
   178 	    public void treeNodesInserted(TreeModelEvent e) {
       
   179 		enableProfileChoices(e);
       
   180 	    }
       
   181 
       
   182 	    public void treeNodesRemoved(TreeModelEvent e) {
       
   183 		disableProfileChoices(e);
       
   184 	    }
       
   185 
       
   186 	    public void treeNodesChanged(TreeModelEvent e) {}
       
   187 
       
   188 	    public void treeStructureChanged(TreeModelEvent e) {}
       
   189 
       
   190 	});
       
   191 
       
   192 	dstModel.addTreeModelListener(new TreeModelListener() {
       
   193 
       
   194 	    public void treeNodesInserted(TreeModelEvent e) {
       
   195 		updateDstTree(e);
       
   196 	    }
       
   197 
       
   198 	    public void treeNodesRemoved(TreeModelEvent e) {
       
   199 		updateDstTree(e);
       
   200 	    }
       
   201 
       
   202 	    public void treeNodesChanged(TreeModelEvent e) {}
       
   203 
       
   204 	    public void treeStructureChanged(TreeModelEvent e) {}
       
   205 
       
   206 	});
       
   207 
       
   208 	// Build subprofiles recursively
       
   209 	for (int i = 0; i < profNodes.length; i++) {
       
   210 	    rebuildSubProfiles(profNodes[i], profNodes[i]);
       
   211 	}
       
   212 
       
   213 	String [] subProfList = null;
       
   214 
       
   215 	// Get the list of profiles that are assigned to current user/role
       
   216 	// (in user_attr entry).
       
   217 	String rights = userObj.getAuthRights();
       
   218 	if (rights != null) {
       
   219 	    subProfList = userObj.getAuthRights().split(",");
       
   220 	}
       
   221 
       
   222 	profPanel.setInitSelection();
       
   223 	if (rights == null || subProfList == null) {
       
   224 	    return;
       
   225 	}
       
   226 
       
   227 	// Move subprofiles of current profile from excluded list
       
   228 	// to included list.
       
   229 	// Note that a dimmed profile will stay dimmed after the move.
       
   230 	// Therefore, a user can not "unassign" a dimmed profile on the
       
   231 	// included list.
       
   232 
       
   233 
       
   234 	for (int j = 0; j < subProfList.length; j++) {
       
   235 	    boolean foundSubProf = false;
       
   236 
       
   237 	    int count = 0;
       
   238 	    for (int i = 0; i < profNodes.length; i++) {
       
   239 		String profString = profNodes[i].toString();
       
   240 
       
   241 		if (profString.equals(subProfList[j])) {
       
   242 		    foundSubProf = true;
       
   243 		    count = i;
       
   244 		    break;
       
   245 		}
       
   246 
       
   247 	    }
       
   248 
       
   249 	    if (foundSubProf) {
       
   250 		profPanel.initLeaf(profPanel.srcTree,
       
   251 		    profPanel.dstTree, profNodes[count]);
       
   252 	    }
       
   253 	}
       
   254 
       
   255 	profPanel.setInitSelection();
       
   256 
       
   257     } // end loadProfiles
       
   258 
       
   259 
       
   260     private void updateDstTree(TreeModelEvent e) {
       
   261 
       
   262 	Vector<DblTreeNode> inclProfsVec = new Vector<DblTreeNode>();
       
   263 	Enumeration inclProfsEnum = dstRoot.breadthFirstEnumeration();
       
   264 
       
   265 	while (inclProfsEnum.hasMoreElements()) {
       
   266 	    DblTreeNode node = (DblTreeNode)inclProfsEnum.nextElement();
       
   267 	    inclProfsVec.addElement(node);
       
   268 	    node.setConflict(false);
       
   269 	}
       
   270 
       
   271 	// Maintain included names as array as optimization
       
   272 
       
   273 	DblTreeNode [] inclProfs = new DblTreeNode[inclProfsVec.size()];
       
   274 	inclProfsVec.copyInto(inclProfs);
       
   275 
       
   276 	if (inclProfs.length < 2)
       
   277 	    return;
       
   278 
       
   279 	for (int i = 0; i < inclProfs.length; i++) {
       
   280 	    String testString = inclProfs[i].toString();
       
   281 
       
   282 	    for (int j = i + 1; j < inclProfs.length; j++) {
       
   283 		if (testString.equals(inclProfs[j].toString())) {
       
   284 		    inclProfs[j].setConflict(true);
       
   285 		    inclProfs[i].setConflict(true);
       
   286 		    TreeNode [] nodes = inclProfs[j].getPath();
       
   287 		    DblTreeNode parentProf = (DblTreeNode)nodes[1];
       
   288 		    parentProf.setConflict(true);
       
   289 		}
       
   290 	    }
       
   291 	}
       
   292 
       
   293     } // end updateDstTree
       
   294 
       
   295 
       
   296     private void enableProfileChoices(TreeModelEvent e) {
       
   297 
       
   298 	// Get names of currently included profiles
       
   299 	if (e.getPath().length > 1)
       
   300 	    return;
       
   301 
       
   302 	Vector<String> inclProfsVec = new Vector<String>();
       
   303 	Enumeration inclProfs = dstRoot.depthFirstEnumeration();
       
   304 
       
   305 	while (inclProfs.hasMoreElements()) {
       
   306 	    inclProfsVec.addElement(inclProfs.nextElement().toString());
       
   307 	}
       
   308 
       
   309 	// Maintain included names as array as optimization
       
   310 
       
   311 	String [] inclProfNames = new String[inclProfsVec.size()];
       
   312 	inclProfsVec.copyInto(inclProfNames);
       
   313 
       
   314 	// Look for excluded list items needing updating
       
   315 
       
   316 	Enumeration topProfs = srcRoot.children();
       
   317 	while (topProfs.hasMoreElements()) {
       
   318 	    DblTreeNode nextTop = (DblTreeNode)topProfs.nextElement();
       
   319 	    boolean matchFound = false;
       
   320 	    Enumeration exclProfs = nextTop.depthFirstEnumeration();
       
   321 
       
   322 	    while (exclProfs.hasMoreElements()) {
       
   323 		String testString = exclProfs.nextElement().toString();
       
   324 		for (int i = 0; i < inclProfNames.length; i++) {
       
   325 		    if (testString.equals(inclProfNames[i])) {
       
   326 			matchFound = true;
       
   327 			break;
       
   328 		    }
       
   329 		}
       
   330 		if (matchFound)
       
   331 		    break;
       
   332 	    }
       
   333 
       
   334 	    // A Profile hierarchy needs to be enabled
       
   335 
       
   336 	    if (!matchFound) {
       
   337 		exclProfs = nextTop.depthFirstEnumeration();
       
   338 		while (exclProfs.hasMoreElements()) {
       
   339 		    DblTreeNode onNode =
       
   340 			(DblTreeNode) exclProfs.nextElement();
       
   341 		    onNode.setConflict(false);
       
   342 		}
       
   343 		nextTop.setConflict(false);
       
   344 	    }
       
   345 	}
       
   346 
       
   347     } // end enableProfileChoices
       
   348 
       
   349 
       
   350     private void disableProfileChoices(TreeModelEvent e) {
       
   351 
       
   352 	if (e.getPath().length > 1)
       
   353 	    return;
       
   354 
       
   355 	Object[] children = e.getChildren();
       
   356 	DblTreeNode node = (DblTreeNode)children[0];
       
   357 	Enumeration kids = node.breadthFirstEnumeration();
       
   358 	while (kids.hasMoreElements()) {
       
   359 	    disableRecursively((DblTreeNode)kids.nextElement());
       
   360 	}
       
   361 
       
   362     } // end disableProfileChoices
       
   363 
       
   364 
       
   365     private void disableRecursively(DblTreeNode node) {
       
   366 
       
   367 	String testString = node.toString();
       
   368 	Enumeration exclProfs = srcRoot.breadthFirstEnumeration();
       
   369 	while (exclProfs.hasMoreElements()) {
       
   370 	    DblTreeNode exclNode = (DblTreeNode)exclProfs.nextElement();
       
   371 	    if (testString.equals(exclNode.toString())) {
       
   372 		TreeNode [] nodes = exclNode.getPath();
       
   373 
       
   374 		DblTreeNode parentProf = (DblTreeNode)nodes[1];
       
   375 		if (!parentProf.isConflict()) {
       
   376 		    parentProf.setConflict(true);
       
   377 		    exclNode.setConflict(true);
       
   378     		}
       
   379 	    }
       
   380 	}
       
   381 
       
   382     } // end disableRecursively
       
   383 
       
   384 
       
   385     private void rebuildSubProfiles(DblTreeNode profNode, DblTreeNode topNode) {
       
   386 
       
   387 	// First unlink the old children
       
   388 	int childCount = profNode.getChildCount();
       
   389 	for (int i = 0; i < childCount; i++) {
       
   390 	    DblTreeNode child = (DblTreeNode) srcModel.getChild(profNode, 0);
       
   391 	    srcModel.removeNodeFromParent(child);
       
   392 	}
       
   393 
       
   394 	// Then recursively construct new nodes for all the children
       
   395 	DblTreeNode childNode;
       
   396 	int i = 0;
       
   397 	Enumeration topList = topNode.breadthFirstEnumeration();
       
   398 
       
   399 	// Find sub-profile list in RightObj of cached tree node
       
   400 	ProfTreeNode pTreeNode = (ProfTreeNode)profNode.getUserObject();
       
   401 	String rObj = pTreeNode.getRightObj();
       
   402 	// ProfAttrObj targetProfAttr = rObj.getProfAttr();
       
   403 
       
   404 	String [] profList = null; // targetProfAttr.getProfNames();
       
   405 
       
   406 	if (profList == null)
       
   407 	    return;
       
   408 
       
   409 	for (int k = 0; k < profList.length; k++) {
       
   410 	    String name = profList[k];
       
   411 
       
   412 	    // Prevent infinite recursive loops
       
   413 	    boolean cyclic = false;
       
   414 	    while (topList.hasMoreElements()) {
       
   415 		if (name.equals(topList.nextElement().toString())) {
       
   416 		    cyclic = true;
       
   417 		    // Mark the parent as cyclic
       
   418 		    topNode.setCyclic(true);
       
   419 		    Enumeration dupNodes = topNode.breadthFirstEnumeration();
       
   420 		    while (dupNodes.hasMoreElements()) {
       
   421 			childNode = (DblTreeNode)dupNodes.nextElement();
       
   422 			if (name.equals(childNode.toString())) {
       
   423 			    childNode.setCyclic(true);
       
   424 			}
       
   425 		    }
       
   426 		    break;
       
   427 		}
       
   428 	    }
       
   429 
       
   430 	    for (int j = 0; j < profTreeNodes.length; j++) {
       
   431 		if (name.equals(profTreeNodes[j].toString())) {
       
   432 		    childNode = new DblTreeNode((Object)profTreeNodes[j]);
       
   433 
       
   434 		    srcModel.insertNodeInto(childNode, profNode, i++);
       
   435 		    childNode.setEnabled(false);
       
   436 		    if (cyclic)
       
   437 			childNode.setCyclic(true);
       
   438 		    else
       
   439 			rebuildSubProfiles(childNode, topNode);
       
   440 		}
       
   441 	    }
       
   442 	}
       
   443 
       
   444     } // end rebuildSubProfiles
       
   445 
       
   446 
       
   447     public String updateRightSubProps(String rightObj) {
       
   448 
       
   449 	if (isProfListOK) {
       
   450 	    Vector<String> vAssignedProfs = new Vector<String>();
       
   451 
       
   452 	    // Get the first generation children that are assigned to
       
   453 	    // current profile.
       
   454 	    DblTreeNode root = (DblTreeNode)dstModel.getRoot();
       
   455 	    Enumeration kids;
       
   456 	    kids = root.children();
       
   457 
       
   458 	    while (kids.hasMoreElements()) {
       
   459 		DblTreeNode childNode;
       
   460 		childNode = (DblTreeNode)kids.nextElement();
       
   461 		vAssignedProfs.addElement(childNode.toString());
       
   462 	    }
       
   463 
       
   464 	    // ProfAttrObj profAttr = rightObj.getProfAttr();
       
   465 	    // profAttr.setProfNamesVector(vAssignedProfs);
       
   466 	}
       
   467 	return (rightObj);
       
   468 
       
   469     } // end updateRightSubProps
       
   470 
       
   471     public Vector<String> getAssignedProfs() {
       
   472 	Vector<String> vAssignedProfs = new Vector<String>();
       
   473 
       
   474 	if (!isProfListOK) {
       
   475 	    return vAssignedProfs;
       
   476 	}
       
   477 
       
   478 	// Get the first generation children that are assigned to
       
   479 	// current profile.
       
   480 	DblTreeNode root = (DblTreeNode)dstModel.getRoot();
       
   481 	Enumeration kids;
       
   482 	kids = root.children();
       
   483 	while (kids.hasMoreElements()) {
       
   484 	    DblTreeNode childNode;
       
   485 	    childNode = (DblTreeNode)kids.nextElement();
       
   486 	    vAssignedProfs.addElement(childNode.toString());
       
   487 	}
       
   488 
       
   489 	return vAssignedProfs;
       
   490     }
       
   491 
       
   492     private Vector<String> getAvailableProfs() {
       
   493         Vector<String> rights = new Vector<String>();
       
   494 	for (String s : panelDesc.getProfiles()) {
       
   495 	    rights.add(s);
       
   496 
       
   497 	}
       
   498     	return (rights);
       
   499     }
       
   500 
       
   501     public void setUser(UserManagedObject userObj) {
       
   502     	this.userObj = userObj;
       
   503 	loadProfiles();
       
   504     }
       
   505 
       
   506     public UserManagedObject updateUser() {
       
   507         Vector<String> vProfs = getAssignedProfs();
       
   508 	String profStr;
       
   509 
       
   510 	if (vProfs.size() > 0) {
       
   511 		profStr = vProfs.elementAt(0);
       
   512 	} else {
       
   513 		profStr = "";
       
   514 	}
       
   515 
       
   516 	for (int i = 1; i < vProfs.size(); i++) {
       
   517 	    profStr = profStr.concat(",");
       
   518 	    profStr = profStr.concat(vProfs.elementAt(i));
       
   519         }
       
   520 
       
   521 	userObj.getAuthRightsProperty().setValue(profStr);
       
   522 
       
   523 	return (userObj);
       
   524     }
       
   525 
       
   526 
       
   527 
       
   528 class ProfileRenderer extends DefaultTreeCellRenderer {
       
   529 
       
   530     private boolean selected;
       
   531     Icon warningIcon;
       
   532     AuthRightsPanel rightsPanel;
       
   533 
       
   534     public ProfileRenderer(AuthRightsPanel rightsPanel) {
       
   535 
       
   536 	this.rightsPanel = rightsPanel;
       
   537 	setClosedIcon(null);
       
   538 	setOpenIcon(null);
       
   539 	setLeafIcon(null);
       
   540     	warningIcon = Finder.getIcon("images/warning.gif");
       
   541 
       
   542     }
       
   543 
       
   544 
       
   545     public Component getTreeCellRendererComponent(
       
   546 	JTree tree,
       
   547 	Object value,
       
   548 	boolean selected,
       
   549 	boolean expanded,
       
   550 	boolean leaf,
       
   551 	int row,
       
   552 	boolean hasFocus) {
       
   553 
       
   554 	FocusEvent e = null;
       
   555 
       
   556 	this.selected = selected;
       
   557 
       
   558 	DefaultTreeCellRenderer cr =
       
   559 	    (DefaultTreeCellRenderer)tree.getCellRenderer();
       
   560 	cr.setLeafIcon(null);
       
   561 	DblTreeNode node = (DblTreeNode)value;
       
   562 
       
   563 	if (node.getParent() == null) {
       
   564 	    // maybe the same as row == 0
       
   565 	    setText(node.toString());
       
   566 
       
   567 	} else if (node.getUserObject() instanceof ProfTreeNode) {
       
   568 	    ProfTreeNode profsdef = (ProfTreeNode)node.getUserObject();
       
   569 	    setText(profsdef.toString());
       
   570 	    // setIcon(actionIcon);
       
   571 
       
   572 	    if (node.isConflict())
       
   573 		if (tree == rightsPanel.profPanel.dstTree)
       
   574 		    cr.setLeafIcon(warningIcon);
       
   575 	}
       
   576 
       
   577 	super.getTreeCellRendererComponent(tree, value, selected, expanded,
       
   578 	    leaf, row, hasFocus);
       
   579 
       
   580 	return this;
       
   581 
       
   582     } // end getTreeCellRendererComponent
       
   583 
       
   584 }
       
   585 
       
   586 class ProfTreeNode {
       
   587 
       
   588     String name;
       
   589     String rightObj = null;
       
   590 
       
   591     public ProfTreeNode(String rightObj) {
       
   592 	this.rightObj = rightObj;
       
   593 	this.name = rightObj;
       
   594     }
       
   595 
       
   596     public String getRightObj() {
       
   597 	return rightObj;
       
   598     }
       
   599 
       
   600     public String toString() {
       
   601 	return name;
       
   602     }
       
   603 
       
   604 }
       
   605 
       
   606 class NodeCompare implements Compare {
       
   607 
       
   608     /**
       
   609      * The compare method compares two ProfTreeNode objects by comparing
       
   610      * their profile names.  The parameters are specified as Object class
       
   611      * objects for QuickSort.
       
   612      *
       
   613      * @param   a	The first Node.
       
   614      * @param   b	The second Node.
       
   615      *
       
   616      */
       
   617     public final int doCompare(Object a, Object b) {
       
   618 
       
   619 	ProfTreeNode e1, e2;
       
   620 	String e1Name, e2Name;
       
   621 
       
   622 	e1 = (ProfTreeNode)a;
       
   623 	e2 = (ProfTreeNode)b;
       
   624 	e1Name = e1.toString();
       
   625 	e2Name = e2.toString();
       
   626 	return (e1Name.compareTo(e2Name));
       
   627 
       
   628     }
       
   629 
       
   630 }
       
   631 }