📄 smarttree.java
字号:
{
clearTree();
setRoot(dn);
addCutting(rootDNBase, en);
}
}
catch (NamingException e)
{
CBUtility.error(CBIntText.get("threaded broker error: "), e);
} // XXXTHREAD
}
/**
* removes a SmartNode and its children from the tree.
* Only affects the GUI tree - does nothing to the underlying data.
*
* @param apex the root of the subtree to be deleted (may be a leaf).
*/
protected void deleteTreeNode(SmartNode apex)
{
treeModel.removeNodeFromParent(apex);
}
/**
* changes the RDN of a tree node to the lowest level
* RDN of the supplied DN.
* (usually to mirror a change in the underlying DIT)
*
* @param node the node to modify
* @param newDN the DN providing the new lowest level RDN
* to modify the node RDN to.
*/
public void renameTreeNode(SmartNode node, DN newDN)
{
node.update(newDN.getLowestRDN());
}
/**
* moves a subtree (may be a leaf) to a
* new position. This only modifies the
* tree, it <i>does not</i> modify the
* underlying directory.
*
* @param node the node to move.
* @param to the DN of the position to move it to.
*/
public void moveTreeNode(SmartNode node, DN to)
{
DN from = treeModel.getDNForNode(node);
if (from.sharesParent(to)) // we may only need to do a rename...
{
renameTreeNode(node, to);
}
else
{
// step 1; remove node from old position
SmartNode parent = (SmartNode) node.getParent();
treeModel.removeNodeFromParent(node);
treeModel.nodeStructureChanged(parent);
// step 2: modify the nodes RDN
node.update(to.getLowestRDN());
// step 3: add it to new position
parent = treeModel.getNodeForDN(to.parentDN());
if (parent.getChildCount() == 1 && ((SmartNode) parent.getChildAt(0)).isDummy())
{
return; // tree hasn't been read from the directory yet - wait until it is before adding anything
}
parent.add(node);
parent.sort();
treeModel.nodeStructureChanged(parent);
}
}
/**
* This copies a tree node and its children to a newly
* created tree node with the given name, <i>without affecting
* the underlying directory</i>.
*
* @param node the tree node to copy data from
* @param to the name of the new tree node to create and, if
* necessary, populate.
*/
public void copyTreeNode(SmartNode node, DN to)
{
// find the parent corresponding to the target DN
SmartNode parent = treeModel.getNodeForDN(to.parentDN());
// sanity check
if (parent == null)
{
CBUtility.error(this, CBIntText.get("unable to copy node {0}.", new String[]{node.toString()}), null);
return;
}
// copy the node (and children) and note the resulting node created
SmartNode newCopy = copyTreeNodes(node, parent);
// see if the newly created node has the right RDN
// (it may not if it has been changed to avoid a 'copy'ing
// name collision.
if (newCopy.getRDN().equals(to.getLowestRDN()) == false)
{
// we must be doing a 'copy' with a naming problem, so
// update the newCopy node with it's new, unique RDN.
newCopy.update(to.getLowestRDN());
}
parent.sort();
// signal a change to the tree for a display update...
treeModel.nodeStructureChanged(parent);
}
/**
* Copies the node 'from' (creating a new node to hold the copy),
* adding it as a child to 'toParent',
* and recursively copies all the children held by 'from' into
* the newly created copy.
* This only affects the tree, <i>not</i> the directory.
*
* @param from the node to copy.
* @param toParent the node which receives the from node as a child.
* @return the copy of from that is added to toParent
*/
public SmartNode copyTreeNodes(SmartNode from, SmartNode toParent)
{
SmartNode fromCopy = new SmartNode(from); // make copy of 'from' called 'fromCopy
/*
* Time saver/Bug Fix - don't bother updating the tree
* if the parent hasn't had its children read yet.
*/
if (toParent.hasDummy())
return fromCopy;
toParent.add(fromCopy); // add 'fromCopy' to 'toParent'
Enumeration children = from.children(); // find children of 'from'
while (children.hasMoreElements())
{
SmartNode child = (SmartNode) children.nextElement();
copyTreeNodes(child, fromCopy); // and add them recursively to 'fromCopy'
}
fromCopy.sort();
return fromCopy;
}
/**
* fully expands all nodes of the tree.
* (Mainly used for debugging; this could take an
* unreasonable time if used on a large production
* directory.)
*/
public void expandAll()
{
int rows = 0;
while (rows != getRowCount()) // i.e. tree is still expanding...
{
rows = getRowCount();
for (int i = 0; i < rows; i++)
expandRow(i);
}
}
/**
* This makes the internal tree object available, in case
* different cell editors/renderers and so on need to be
* registered.
*
* @return the internal tree object
*/
public JTree getTree()
{
return this;
}
/**
* Starts the process of making a new entry. As an aid to the user,
* it tries to find any children of the current node, and if it can
* find such, it uses them as a template for the new object.
*/
public void makeNewEntry(DN parentDN)
{
if (treeDataSource.getSchemaOps() == null)
{
JOptionPane.showMessageDialog(owner, CBIntText.get("Because there is no schema currently published by the\ndirectory, adding a new entry is unavailable."), CBIntText.get("No Schema"), JOptionPane.INFORMATION_MESSAGE);
return;
}
else
{
// step 1: find a child to use as a template
SmartNode parent = treeModel.getNodeForDN(parentDN);
DN childDN = null;
if (parent == null)
{
log.warning("unable to find " + parentDN + " in tree!");
return;
}
if (parent.getChildCount() > 0)
{
SmartNode child = (SmartNode) parent.getChildAt(0);
if ((child != null) && (child.isDummy() == false))
{
RDN childRDN = child.getRDN();
childDN = new DN(parentDN);
try
{
childDN.addChildRDN(childRDN);
}
catch (InvalidNameException e)
{
log.log(Level.WARNING, "ERROR: makeNewEntry(DN parentDN) " + parentDN, e);
}
}
else // children are not currently displayed - send of a query to get them...
{
refresh(parentDN);
}
}
// step 2: find a datasink that can handle a partially created entry
DataSink editor = null;
for (int i = 0; i < treeDataSinks.size(); i++)
{
if (((DataSink) treeDataSinks.get(i)).canCreateEntry())
editor = (DataSink) treeDataSinks.get(i);
}
if (editor == null)
{
CBUtility.error("Unable to create a new entry!", new Exception("No available entry editors"));
return;
}
// step 3: open a NewEntryWin (see) and pass the found child to it.
NewEntryWin userData = new NewEntryWin(parentDN, childDN, treeDataSource, editor, owner);
userData.setSize(400, 300);
CBUtility.center(userData, owner); // TE: centres window.
userData.setVisible(true);
}
}
/*
public boolean exists(DN nodeDN)
{
if (nodeDN == null) return false;
try
{
return treeDataSource.exists(nodeDN).getStatus();
} catch (NamingException e) {CBUtility.error("threaded broker error: ", e); } // XXXTHREAD
return false;
}
*/
/**
* Returns the current popup tool.
* This is used by the menu bar and others to trigger edits
* etc, since all that functionality lives in SmartPopupTool.
*/
public SmartPopupTool getPopupTool()
{
return popupTreeTool;
}
public void registerEventPublisher(JXplorerEventGenerator gen)
{
eventPublisher = gen;
}
public void fireJXplorerEvent(JXplorerEvent e)
{
if (eventPublisher != null)
eventPublisher.fireJXplorerEvent(e);
}
public boolean isModifiable()
{
return treeDataSource.isModifiable();
}
public DirContext getDirContext()
{
return (treeDataSource == null) ? null : treeDataSource.getDirContext();
}
/**
* This files a request with the directory broker to modify (move / delete / add)
* an entry. If oldEntry is null this is an add, if newEntry is null it is a
* delete, otherwise it is (when called by the tree) usually a rename.
*/
public void modifyEntry(DXEntry oldEntry, DXEntry newEntry)
{
if (oldEntry == null && newEntry == null) return; // nothing to do.
treeDataSource.modifyEntry(oldEntry, newEntry); // queue directory request
}
/**
* This files a request with the directory broker to copy a node or subtree.
*/
//XXX This should be done in the thread that actually does the operation - it is
//XXX possible for the user to 'beat' this method by quickly copying multiples of
//XXX the same entry. Also, it produces extra naming attributes.
public void copyTree(DN oldNodeDN, DN newNodeDN)
{
// 'copy'ing a tree means placing the old tree *under*
// the newly selected tree... hence deepen 'activeDN' by
// one new level. (i.e. copying ou=eng,o=uni,c=au moved
// to o=biz,c=au requires activeDN extended to ou=eng,o=biz,c=au before move
// * first check name is not already there; if it is, create a
// unique name of the form "copy [(n)] of ..." first.
// * if adding this to the *display* tree fails display error message.
// * if directory mod fails, clean up display tree...
String uniqueRDN = treeModel.getUniqueCopyRDN(newNodeDN, oldNodeDN);
// check not recursively pasting
try
{
newNodeDN.addChildRDN(uniqueRDN);
}
catch (javax.naming.InvalidNameException e)
{
CBUtility.error(this, CBIntText.get("Unable to add {0} due to bad name", new String[]{newNodeDN.toString()}), e);
return;
}
treeDataSource.copyTree(oldNodeDN, newNodeDN); // queue directory request
}
/**
* Displays the result of a expand result, triggered from the data listener.
* This (should) run from the directory connection thread.
*
* @param result the directory read result
*/
protected void displayExpandedNodeResult(DataQuery result)
{
// 1) Find node for result
SmartNode node = treeModel.getNodeForDN(result.requestDN());
if (node == null)
{
node = addNode(result.requestDN());
}
try
{
// XXX EXTREME HACKINESS AS WE TRY TO SIMULTANEOUSLY SATISFY RICK AND SCOTT'S CONFLICTING REQUIREMENTS
// 1b) Special Hack for structural nodes to make work nicely for both x500 and ldap...
/**
* What a debacle. If null prefix router has knowledge of democorp (o=democorp,c=au) then a list of 'root' fails
* horribly, because no-one has the node 'c=au'. So we hack it to not delete root nodes even if it gets zero
* results from a list. Whoo hoo. *But*, we still need to keep it all clear in the circumstance that it is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -