package org.basex.gui.layout;
import static org.basex.util.Token.*;
import java.util.Arrays;
import java.util.Comparator;
import javax.swing.tree.DefaultTreeModel;
import org.basex.core.Prop;
import org.basex.data.Data;
import org.basex.index.Resources;
import org.basex.util.hash.TokenBoolMap;
import org.basex.util.list.TokenList;
/**
* JTree node which represents a folder.
*
* @author BaseX Team 2005-12, BSD License
* @author Lukas Kircher
*/
public class TreeFolder extends TreeNode {
/** Children of node have been loaded. */
private boolean loaded;
/**
* Constructor.
* @param nm displayed node name
* @param pth folder path
* @param bxt tree reference
* @param d data reference
*/
public TreeFolder(final byte[] nm, final byte[] pth, final BaseXTree bxt,
final Data d) {
super(nm, pth, bxt, d);
}
@Override
void load() {
if(loaded) return;
// append new child nodes, folders first ...
for(final byte[] b : folders(this)) {
add(new TreeFolder(b, subfolder(), tree, data));
}
// ... then leaves.
for(final TreeLeaf l : leaves(this)) add(l);
loaded = true;
((DefaultTreeModel) tree.getModel()).nodeStructureChanged(this);
}
/**
* Finds all raw and document folders on the child axis of the given node.
* @param node node for which to find child folders for
* @return folders
*/
private static byte[][] folders(final TreeFolder node) {
final Resources res = node.data.resources;
final TokenBoolMap ts = res.children(node.subfolder(), true);
return new TokenList(ts.keys()).sort(!Prop.WIN).toArray();
}
/**
* Finds all leaf child nodes for the given node.
* @param node node for which to find leaves for
* @return raw file / document leaves
*/
public static TreeLeaf[] leaves(final TreeFolder node) {
// get child resources
final Resources res = node.data.resources;
final TokenBoolMap tbm = res.children(node.subfolder(), false);
// create leaf nodes
final int ts = tbm.size();
final TreeLeaf[] leaves = new TreeLeaf[ts];
for(int t = 0; t < ts; t++) {
leaves[t] = new TreeLeaf(tbm.key(t + 1), node.subfolder(),
tbm.value(t + 1), node.tree, node.data);
}
// sort and return leaves
Arrays.sort(leaves, new Comparator<TreeLeaf>() {
@Override
public int compare(final TreeLeaf l1, final TreeLeaf l2) {
final byte[] n1 = l1.name;
final byte[] n2 = l2.name;
return Prop.WIN ? diff(lc(n1), lc(n2)) : diff(n1, n2);
}
});
return leaves;
}
/**
* Returns the path for a child node of this folder.
* @return sub folder path
*/
byte[] subfolder() {
return path.length > 1 ? concat(concat(path, SLASH), name) :
concat(path, name);
}
/**
* Extracts the file/document/folder name from the given path.
* @param path path
* @return name
*/
public static byte[] name(final byte[] path) {
final byte[][] s = split(path, '/');
if(s.length == 0) return EMPTY;
return s[s.length - 1];
}
/**
* Returns the path without folder/file name for the given path.
* @param path path
* @return path without file/folder name
*/
public static byte[] path(final byte[] path) {
if(path.length == 0) return path;
final byte[] r = substring(path, 0, lastIndexOf(path, '/'));
return r.length == 0 ? SLASH : r;
}
/**
* Removes all children from this node.
*/
public void removeChildren() {
removeAllChildren();
loaded = false;
}
/**
* Reloads this node without repainting the tree.
*/
public void reload() {
removeChildren();
load();
}
@Override
public boolean isLeaf() {
return false;
}
}