📄 smarttree.java
字号:
* just an empty dsa with a null root. So we have to check IF the node is a 'base DN' type node (alwaysRefresh())
* AND we got no search results THEN if it is an empty DSA (only has a single dummy child) close things up,
* OTHERWISE keep the 'fake' node (e.g. c=AU).
**/
if (node.isAlwaysRefresh() && result.getEnumeration().size() == 0)
{
if (node.getChildCount() != 1 || ((SmartNode) node.getChildAt(0)).isDummy() == false)
{
return; // don't remove structural nodes children, even if server returns no entries. Assume server is wrong. (for Scott)
}
}
// 2) clear old data
node.removeAllChildren();
// 3) add new data
addCutting(node, result.getEnumeration());
// XXX (another) pki hack
if (node == getLowestRootNode() && node.getChildCount() == 0)
{
pluggableEditorSource.displaySpecialEntry(null, treeDataSource, JXplorer.getProperty("null.entry.editor"));
}
// 4) Make sure the newly added data nodes are visible
expandPath(treeModel.getPathForDN(result.requestDN()));
}
catch (NamingException e)
{
result.setException(e); // register error and trust someone else to handle it...
node.removeAllChildren();
}
}
/**
* Takes a DN and reads and displays the corresponding entry.
* Then reads all unexpanded parent nodes. These calls are done
* via the broker thread.
* TE: only displays the entry if the supplied dn is below the root
* DN (which actually is the baseDN) and if the prefix is the same.
*
* @param dn the end DN to display.
*/
public void readAndExpandDN(DN dn)
{
if (currentDN.size() < rootDN.size())
{ //TE: if the user has selected a node above the prefix (i.e. c AU instead of c AU o DEMOCORP
// in the case of a router being off line) - re select the prefix otherwise a read error may occur.
refresh(rootDN);
setSelectionPath(treeModel.getPathForDN(rootDN));
}
if (dn.size() < rootDN.size() || !dn.getPrefix(rootDN.size()).toString().equalsIgnoreCase(rootDN.toString()))
{
//TE: only display the entry if the dn is below the root DN (baseDN) and if the prefix is the same.
JOptionPane.showMessageDialog(owner, CBIntText.get("The entry {0}\nwill not be displayed because it is either above the baseDN\n{1}\n" +
"that you are connected with or it has a different prefix.", new String[]{dn.toString(), rootDN.toString()}),
CBIntText.get("Display Error"), JOptionPane.ERROR_MESSAGE);
return;
}
log.warning("Opening '" + dn + "' from root DN '" + getRootDN()); //TE: fixes bug 2540 - don't ask me how!
// work down the DN, reading children as required...
for (int level = 1; level <= dn.size(); level++)
{
DN ancestor = (DN) dn.getPrefix(level);
if (ancestor.size() >= rootDN.size())
{
SmartNode node = treeModel.getNodeForDN(ancestor);
/*
* Check if node hasn't been read - if so, read it and all its sibling
* nodes, by 'listing' all the children of its parent.
*/
if (node == null)
{
treeDataSource.getChildren(ancestor.parentDN());
}
/*
* This check shouldn't be called, if the baseDN is skipped.
*/
else if (node.isStructural())
{
treeDataSource.getChildren(ancestor); //TE: for some unknown reason the structural nodes (root dn) need to be read for the correct behavor to occur.
}
/*
* The node hasn't been read yet - read its sibling nodes by 'listing'
* all the children of its parent.
*/
else if (node.isDummy())
{
treeDataSource.getChildren(ancestor.parentDN());
}
/*
* The node already exists in the tree - make sure its visible.
*/
else
{
//was: expandDN(ancestor);
treeDataSource.getChildren(ancestor.parentDN());
}
}
}
treeDataSource.getEntry(dn);
}
/**
* Displays the result of an entry read result, triggered from the data listener.
* This (should) run from the directory connection thread.
*
* @param node the directory read result. If null, indicates a 'no data' display should
* be shown.
*/
public void displayReadNodeResult(DataQuery node)
{
// sanity check
if (treeDataSinks.size() == 0)
{
log.warning("no data sink in display Node");
return;
}
setEntry(null);
try
{
if (node != null)
{
setEntry(node.getEntry());
currentDN = node.requestDN();
}
else
{
currentDN = null;
}
publishData(entry, treeDataSource);
}
catch (NamingException e)
{
CBUtility.error("unexpected naming error trying to \ndisplay: " + node, e);
}
if (node != null)
{
TreePath current = treeModel.getPathForDN(node.requestDN());
if (current == null)
{
log.warning("Unable to find tree path for DN: " + node.requestDN());
return;
}
// 'User' demand seems to oscillate between wanting the next level displayed, and not
// wanting it displayed. Comment out appropriate section below...
// just expand node
if (isExpanded(current.getParentPath()) == false)
expandPath(current.getParentPath());
// expand node and children
// if (isExpanded(current) == false)
// expandPath(current);
if (current.equals(getSelectionPath()) == false)
{
setSelectionPath(current);
}
if (currentDN.size() <= rootDN.size())
//TE: if the user has connected using a baseDN for example, and then moves
//TE: up the tree, change the rootDN to the entry that the user has moved to.
rootDN = currentDN;
}
}
/**
* sets the current entry highlighted by the tree.
*/
public void setEntry(DXEntry newEntry)
{
entry = newEntry;
}
/**
* This publishes entry data to all available data listeners,
* along with a data source.
* note that both entry and treeDataSource can legitimately be null here
*
* @param entry the entry to publish. Null indicates no data
* @param dataSource the datasource to use for further info/operations.
* Null indicates no available data source.
*/
public void publishData(DXEntry entry, DataSource dataSource)
{
for (int i = 0; i < treeDataSinks.size(); i++)
{
((DataSink) treeDataSinks.elementAt(i)).displayEntry(entry, treeDataSource);
}
}
/**
* This is called when a modify request has been completed.
*/
protected void displayModifyResult(DataQuery result)
{
try
{
if (result.getStatus() == true)
{
DXEntry oldEntry = result.oldEntry();
DXEntry newEntry = result.newEntry();
// first, do the 'easy' pure adds and pure deletes.
if (oldEntry == null || (newEntry != null) && (newEntry.isNewEntry())) // add
{
SmartNode node = addNode(newEntry.getDN());
node.add(new SmartNode()); // stick in a dummy node so there's something to expand to...
doObjectClassSpecificHandling(node, newEntry.getAllObjectClasses());
//XXX *** WARNING ***
//
// This code is a little naughty. We reset the status of
// the entry, assuming that no other editor cares about it.
// - this *should* be done by the broker, but for some reason
// isn't...
newEntry.setStatus(DXEntry.NEW_WRITTEN);
publishData(newEntry, treeDataSource);
}
else if (newEntry == null) // delete
{
deleteTreeNode(treeModel.getNodeForDN(oldEntry.getDN()));
}
else if (oldEntry.getDN().equals(newEntry.getDN()) == false) // check for a change of name
{
SmartNode node = treeModel.getNodeForDN(oldEntry.getDN());
/*
* If the old node is not null, then move it to the right place. If it
* *is* null, it should be because it has been directly edited (and hence
* the tree model is already up to date).
*/
if (node != null)
{
moveTreeNode(node, newEntry.getDN());
treeModel.nodeChanged(node);
}
/**
* If the newEntry is empty (i.e. we're just doing a name change)
* use the atts from the old entry...
*/
if (newEntry.size() == 0)
{
newEntry.put(oldEntry.getAll());
}
// re-read node (to get attributes)
// XXX is this always necessary?
treeDataSource.getEntry(newEntry.getDN());
}
else // update editors
{
// re-read node so as to force the browser to correctly display the current state
// (A bit heavy, but solves a bunch of consistancy problems)
treeDataSource.getEntry(newEntry.getDN());
}
// don't need to worry about a change of attributes, since the tree doesn't use them...
}
}
catch (NamingException e)
{
result.setException(e); // XXX set the exception on the result object, let someone else handle it.
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Displays a copy result, triggered from the data listener.
* This (should) run from the directory connection thread.
*
* @param result the directory copy result.
* be shown.
*/
protected void displayCopyResult(DataQuery result)
{
try
{
if (result.getStatus() == true)
{
copyTreeNode(treeModel.getNodeForDN(result.oldDN()), result.requestDN());
}
}
catch (NamingException e)
{
result.setException(e); // XXX set the exception on the result object, let someone else handle it.
}
}
/**
* Displays a search result, triggered from the data listener.
* This (should) run from the directory connection thread.
*
* @param result the directory copy result.
* be shown.
*/
protected void displaySearchResult(DataQuery result)
{
// XXX Currently search results aren't sorted: do want to make them sorted?
// XXX (easy way is to sort result.getEnumeration() as DXNamingEnumeration,
// XXX but this may be expensive...
setNumOfResults(0);
try
{
NamingEnumeration results = result.getEnumeration();
while (results.hasMoreElements())
{
SearchResult sr = (SearchResult) results.nextElement();
//Attribute obClass = sr.getAttributes().get("objectClass");
String search = sr.getName();
if (search == null || search.length() == 0)
{
addNode(new DN(SmartTree.NODATA));
}
else
{
DN searchDN = new DN(search);
addNode(searchDN);
numOfResults++;
}
}
//TE: task 4648...
if (owner instanceof JXplorer)
((JXplorer) owner).setStatus("Number of search results: " + String.valueOf(numOfResults));
expandAll();
}
catch (NamingException e)
{
result.setException(e); // XXX set the exception on the result object, let someone else handle it.
}
}
/**
* @return the numOfResults.
*/
public int getNumOfResults()
{
return numOfResults;
}
/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -