package thaw.plugins.index;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Observer;
import java.util.Vector;
import java.util.HashMap;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import thaw.core.Logger;
import thaw.core.Config;
import thaw.fcp.FCPQueueManager;
import thaw.plugins.Hsqldb;
public class IndexFolder implements IndexTreeNode, MutableTreeNode {
public static final int MAX_AUTOSORTING_DEPTH = 6;
private static final long serialVersionUID = 2L;
private Hsqldb db;
private Config config;
private int id;
private TreeNode parentNode = null;
private String name = null;
private Vector children = null;
private boolean loadOnTheFly = true;
private HashMap folders;
public IndexFolder(final Hsqldb db, Config config,
final int id,
boolean loadOnTheFly) {
this.id = id;
this.config = config;
this.db = db;
this.loadOnTheFly = loadOnTheFly;
folders = new HashMap();
}
/**
* @param parentNode only required if in a tree
*/
public IndexFolder(final Hsqldb db, Config config,
final int id, TreeNode parentNode, String name, boolean loadOnTheFly) {
this(db, config, id, loadOnTheFly);
this.parentNode = parentNode;
this.name = name;
folders = new HashMap();
}
protected Hsqldb getDb() {
return db;
}
public boolean isInTree() {
return (parentNode != null);
}
protected void addToVector(Vector v, ResultSet set, boolean folder) throws SQLException {
if (set == null)
return;
while(set.next()) {
IndexTreeNode n;
if (folder) {
n = new IndexFolder(db, config,
set.getInt("id"), this,
set.getString("name"), loadOnTheFly);
if (!loadOnTheFly) /* => load immediatly */
((IndexFolder)n).loadChildren();
folders.put(set.getString("name").toLowerCase(), n);
}
else
n = new Index(db, config,
set.getInt("id"), this, set.getString("publicKey"),
set.getInt("revision"), set.getString("privateKey"),
set.getBoolean("publishPrivateKey"),
set.getString("displayName"), set.getDate("insertionDate"),
set.getBoolean("newRev"), set.getBoolean("newComment"));
int pos = set.getInt("positionInTree");
if (v.size() <= pos) {
v.setSize(pos+1);
}
if (pos >= 0 && v.get(pos) == null)
v.set(pos, n);
else
v.add(n);
}
}
/**
* @param name case insensitive
*/
public IndexFolder getFolder(String name) {
return (IndexFolder)folders.get(name.toLowerCase());
}
/** TREENODE **/
public Enumeration children() {
if (children == null)
loadChildren();
synchronized(children) {
return children.elements();
}
}
public boolean loadChildren() {
Logger.info(this, "Loading child for folder "+Integer.toString(id)+"...");
Vector v = new Vector();
synchronized(db.dbLock) {
try {
/* category first */
PreparedStatement st;
if (id >= 0) {
st = db.getConnection().prepareStatement("SELECT id, name, positionInTree "+
" FROM indexFolders "+
"WHERE parent = ? "+
"ORDER BY positionInTree");
st.setInt(1, id);
} else {
st = db.getConnection().prepareStatement("SELECT id, positionInTree, name "+
"FROM indexFolders "+
"WHERE parent IS NULL "+
"ORDER BY positionInTree");
}
addToVector(v, st.executeQuery(), true);
st.close();
if (id >= 0) {
st = db.getConnection().prepareStatement("SELECT id, positionInTree, "+
" displayName, publicKey, "+
" privateKey, publishPrivateKey, "+
" revision, newRev, newComment, "+
" insertionDate "+
"FROM indexes "+
"WHERE parent = ? "+
"ORDER BY positionInTree");
st.setInt(1, id);
} else {
st = db.getConnection().prepareStatement("SELECT id, positionInTree, "+
" displayName, publicKey, "+
" privateKey, publishPrivateKey, "+
" revision, newRev, newComment, "+
" insertionDate "+
"FROM indexes "+
"WHERE parent IS NULL "+
"ORDER BY positionInTree");
}
addToVector(v, st.executeQuery(), false);
st.close();
} catch (SQLException e) {
Logger.error(this, "Unable to load child list because: "+e.toString());
}
}
while(v.remove(null)) { }
children = v;
return true;
}
protected Vector getChildren() {
return children;
}
public void unloadChildren() {
children = null;
}
public boolean forceReload() {
Logger.info(this, "forceReload()");
return loadChildren();
}
public boolean getAllowsChildren() {
return true;
}
public TreeNode getChildAt(int childIndex) {
if (children == null)
loadChildren();
synchronized(children) {
try {
return (TreeNode)children.get(childIndex);
} catch(ArrayIndexOutOfBoundsException e) {
Logger.error(this, "Huho : ArrayIndexOutOfBoundsException ... :/");
Logger.error(this, e.toString());
return null;
}
}
}
public int getChildCount() {
/* we use systematically this solution because else we can have problems with
* gap / other-not-funny-things-to-manage
*/
if (children == null)
loadChildren();
synchronized(children) {
return children.size();
}
}
/**
* position
*/
public int getIndex(TreeNode node) {
Logger.info(this, "getIndex()");
synchronized(db.dbLock) {
try {
IndexTreeNode n = (IndexTreeNode)node;
PreparedStatement st =
db.getConnection().prepareStatement("SELECT positionInTree FROM "+
((n instanceof Index) ? "indexes" : "indexFolders")
+ " WHERE id = ? LIMIT 1");
st.setInt(1, n.getId());
ResultSet set = st.executeQuery();
if (set.next()) {
int r = set.getInt("positionInTree");
st.close();
return r;
}
st.close();
return -1;
} catch(SQLException e) {
Logger.error(this, "Unable to find position because: "+e.toString());
}
}
return -1;
}
public TreeNode getParent() {
return parentNode;
}
public boolean isLeaf() {
return false;
}
/**
* entry point
* the target child must be in the database
*/
public void insert(MutableTreeNode child, int index) {
Logger.info(this, "Inserting node at "+Integer.toString(index)+" in node "+
Integer.toString(id)+" ("+toString()+")");
if (child instanceof IndexFolder && folders != null) {
folders.put( ((IndexFolder)child).toString().toLowerCase(), child);
}
if (children != null) {
synchronized(children) {
if (index < children.size())
children.add(index, child);
else
children.add(child);
while(children.remove(null)) {};
}
}
child.setParent(this);
synchronized(db.dbLock) {
Logger.info(this, "moving other nodes ...");
try {
PreparedStatement st;
if (id >= 0) {
st = db.getConnection().prepareStatement("UPDATE indexes "+
"SET positionInTree = positionInTree + 1 "+
"WHERE parent = ? AND positionInTree >= ?");
st.setInt(1, id);
st.setInt(2, index);
st.execute();
st.close();
st = db.getConnection().prepareStatement("UPDATE indexFolders "+
"SET positionInTree = positionInTree + 1 "+
"WHERE parent = ? AND positionInTree >= ?");
st.setInt(1, id);
st.setInt(2, index);
st.execute();
st.close();
st = db.getConnection().prepareStatement("UPDATE "+
((child instanceof IndexFolder) ? "indexFolders" : "indexes")+
" SET parent = ?, positionInTree = ?"+
"WHERE id = ?");
st.setInt(1, id);
st.setInt(2, index);
st.setInt(3, ((IndexTreeNode)child).getId());
st.execute();
st.close();
} else {
st = db.getConnection().prepareStatement("UPDATE indexes "+
"SET positionInTree = positionInTree + 1 "+
"WHERE parent IS NULL AND positionInTree >= ?");
st.setInt(1, index);
st.execute();
st.close();
st = db.getConnection().prepareStatement("UPDATE indexFolders "+
"SET positionInTree = positionInTree + 1 "+
"WHERE parent IS NULL AND positionInTree >= ?");
st.setInt(1, index);
st.execute();
st.close();
st = db.getConnection().prepareStatement("UPDATE "+
((child instanceof IndexFolder) ? "indexFolders" : "indexes")+
" SET parent = ?, positionInTree = ?"+
"WHERE id = ?");
st.setNull(1, Types.INTEGER);
st.setInt(2, index);
st.setInt(3, ((IndexTreeNode)child).getId());
st.execute();
st.close();
}
} catch(SQLException e) {
Logger.error(this, "Error while inserting node: "+e.toString());
}
}
}
public void remove(int target_id, int pos, boolean index) {
if (children != null) {
synchronized(children) {
IndexTreeNode node;
if (index)
node = new Index(db, config, target_id);
else {
node = new IndexFolder(db, config,
target_id, false);
folders.remove(((IndexFolder)node).getName());
}
children.remove(node);
}
}
if (pos < 0) {
Logger.error(this, "invalid position in tree ?!!!");
pos = 0;
}
Logger.info(this, "Removing obj pos "+Integer.toString(pos));
synchronized(db.dbLock) {
try {
PreparedStatement st;
if (id >= 0) {
st = db.getConnection().prepareStatement("UPDATE indexes "+
"SET positionInTree = positionInTree - 1 "+
"WHERE parent = ? AND positionInTree > ?");
st.setInt(1, id);
st.setInt(2, pos);
st.execute();
st.close();
st = db.getConnection().prepareStatement("UPDATE indexFolders "+
"SET positionInTree = positionInTree - 1 "+
"WHERE parent = ? AND positionInTree > ?");
st.setInt(1, id);
st.setInt(2, pos);
st.execute();
st.close();
} else {
st = db.getConnection().prepareStatement("UPDATE indexes "+
"SET positionInTree = positionInTree - 1 "+
"WHERE parent IS NULL AND positionInTree > ?");
st.setInt(1, pos);
st.execute();
st.close();
st = db.getConnection().prepareStatement("UPDATE indexFolders "+
"SET positionInTree = positionInTree - 1 "+
"WHERE parent IS NULL AND positionInTree > ?");
st.setInt(1, pos);
st.execute();
st.close();
}
} catch(SQLException e) {
Logger.error(this,
"Error while removing node at the position "+Integer.toString(pos)+
" : "+e.toString());
}
}
}
public void remove(MutableTreeNode n) {
IndexTreeNode node = (IndexTreeNode)n;
int t_id, pos;
boolean index;
synchronized(db.dbLock) {
try {
PreparedStatement st;
st = db.getConnection().prepareStatement("SELECT positionInTree FROM "+
((n instanceof Index) ? "indexes" : "indexFolders")+
" WHERE id = ?");
st.setInt(1, node.getId());
ResultSet set = st.executeQuery();
if (set.next()) {
t_id = node.getId();
pos = set.getInt("positionInTree");
index = n instanceof Index;
} else {
Logger.error(this, "Node not found !");
st.close();
return;
}
st.close();
} catch(SQLException e) {
Logger.error(this, "Unable to remove node "+Integer.toString(node.getId())+" because: "+
e.toString());
return;
}
}
remove(t_id, pos, index);
}
public void remove(int pos) {
remove((MutableTreeNode)getChildAt(pos));
}
/**
* entry point
*/
public void removeFromParent() {
if (id < 0) {
Logger.error(this, "removeFromParent() : We are root ?!");
return;
}
synchronized(db.dbLock) {
try {
PreparedStatement st;
st = db.getConnection().prepareStatement("DELETE FROM indexParents "+
"WHERE (indexParents.indexId IN "+
" (SELECT indexParents.indexId FROM indexParents "+
" WHERE indexParents.folderId = ?)) "+
"AND ((indexParents.folderId IN "+
" (SELECT folderParents.parentId FROM folderParents "+
" WHERE folderParents.folderId = ?)) "+
" OR (indexParents.folderId IS NULL))");
st.setInt(1, id);
st.setInt(2, id);
st.execute();
st.close();
st = db.getConnection().prepareStatement("DELETE FROM folderParents "+
"WHERE ( ((folderId IN "+
" (SELECT folderId FROM folderParents "+
" WHERE parentId = ?)) OR "+
" (folderId = ?)) "+
"AND ((parentId IN "+
" (SELECT parentId FROM folderParents "+
" WHERE folderId = ?)) "+
" OR (parentId IS NULL) ) )");
st.setInt(1, id);
st.setInt(2, id);
st.setInt(3, id);
st.execute();
st.close();
} catch(SQLException e) {
Logger.error(this, "Error while removing from parent: "+e.toString());
}
}
((IndexFolder)parentNode).remove(this);
}
public void setParent(MutableTreeNode newParent) {
this.parentNode = newParent;
setParent(((IndexTreeNode)newParent).getId());
}
public void setUserObject(Object object) {
rename(object.toString());
}
/** /TREENODE **/
public MutableTreeNode getTreeNode() {
return this;
}
public void setParent(int parentId) {
Logger.info(this, "setParent(id)");
if (id < 0) {
Logger.error(this, "setParent(): Hu ? we are root, we can't have a new parent ?!");
return;
}
synchronized(db.dbLock) {
try {
PreparedStatement st;
st = db.getConnection().prepareStatement("UPDATE indexFolders "+
"SET parent = ? "+
"WHERE id = ?");
if (parentId < 0)
st.setNull(1, Types.INTEGER);
else
st.setInt(1, parentId);
st.setInt(2, id);
st.execute();
st.close();
/* put all its child folders into its new parents */
/* all its children:
* SELECT folderId FROM folderParents WHERE parentId = IT
*/
/* all the parent of its parent:
* SELECT parentId FROM folderParents WHERE folderId = <parentId>
*/
/* we put all its children in the parents of the parent folder */
if (parentId >= 0) {
st = db.getConnection().prepareStatement("INSERT INTO folderParents (folderId, parentId) "+
"SELECT a.folderId, b.parentId FROM "+
" folderParents AS a JOIN folderParents AS b ON (a.parentId = ?) WHERE b.folderId = ?");
st.setInt(1, id);
st.setInt(2, parentId);
st.execute();
st.close();
} /* else no parent of the parent */
/* we put all its children in its parent */
st = db.getConnection().prepareStatement("INSERT INTO folderParents (folderId, parentId) "+
" SELECT folderId, ? FROM folderParents "+
" WHERE parentId = ?");
if (parentId >= 0)
st.setInt(1, parentId);
else
st.setNull(1, Types.INTEGER);
st.setInt(2, id);
st.execute();
st.close();
/* we put itself in the parents of its parent */
if (parentId >= 0) {
st = db.getConnection().prepareStatement("INSERT INTO folderParents (folderId, parentId) "+
" SELECT ?, parentId FROM folderParents "+
" WHERE folderId = ?");
st.setInt(1, id);
st.setInt(2, parentId);
st.execute();
st.close();
}
/* and then in its parent */
st = db.getConnection().prepareStatement("INSERT INTO folderParents (folderId, parentId) "+
" VALUES (?, ?)");
st.setInt(1, id);
if (parentId >= 0)
st.setInt(2, parentId);
else
st.setNull(2, Types.INTEGER);
st.execute();
st.close();
st = db.getConnection().prepareStatement("INSERT INTO indexParents (indexId, folderId) "+
"SELECT indexParents.indexId, folderParents.parentId "+
"FROM indexParents JOIN folderParents ON "+
" indexParents.folderId = folderParents.folderId "+
" WHERE folderParents.folderId = ?");
st.setInt(1, id);
st.execute();
st.close();
} catch(SQLException e) {
Logger.error(this, "Unable to change parent because: "+e.toString());
}
}
}
/**
* get Id of this node in the database.
*/
public int getId() {
return id;
}
/**
* Change the name of the node.
*/
public void rename(String name) {
if (id < 0) {
Logger.error(this, "Can't rename the root node !");
return;
}
this.name = name;
synchronized(db.dbLock) {
try {
PreparedStatement st;
st = db.getConnection().prepareStatement("UPDATE indexFolders "+
"SET name = ? "+
"WHERE id = ?");
st.setString(1, name);
st.setInt(2, id);
st.execute();
st.close();
} catch(SQLException e) {
Logger.error(this, "Error while renaming the folder: "+e.toString());
}
}
}
/**
* no choice :/
* else we have troubles with the Foreign keys :/
*/
private void deleteChildFoldersRecursivly(int id) throws SQLException {
Vector children = new Vector();
PreparedStatement st =
db.getConnection().prepareStatement("SELECT indexFolders.id FROM indexFolders where indexfolders.parent = ?");
st.setInt(1, id);
ResultSet set = st.executeQuery();
while(set.next()) {
children.add(new Integer(set.getInt("id")));
}
st.close();
st = db.getConnection().prepareStatement("DELETE from indexfolders where id = ?");
for (Iterator it = children.iterator();
it.hasNext();) {
Integer nextId = (Integer)it.next();
deleteChildFoldersRecursivly(nextId.intValue());
st.setInt(1, nextId.intValue());
st.execute();
}
st.close();
}
/**
* Entry point
* Remove the node from the database.<br/>
* Remark: Parent node must be set !
*/
public void delete() {
if (id < 0) {
Logger.error(this, "Can't remove the root node !");
return;
}
Logger.notice(this, "DELETING FOLDER");
((IndexFolder)parentNode).remove(this);
synchronized(db.dbLock) {
try {
PreparedStatement st;
/* we remove all the comments */
st = db.getConnection().prepareStatement("DELETE FROM indexCommentKeys "+
"WHERE indexCommentKeys.indexId IN "+
" (SELECT indexParents.indexId "+
" FROM indexParents "+
" WHERE indexParents.folderId = ?)");
st.setInt(1, id);
st.execute();
st.close();
st = db.getConnection().prepareStatement("DELETE FROM indexComments "+
"WHERE indexComments.indexId IN "+
" (SELECT indexParents.indexId "+
" FROM indexParents "+
" WHERE indexParents.folderId = ?)");
st.setInt(1, id);
st.execute();
st.close();
st = db.getConnection().prepareStatement("DELETE FROM indexCommentBlackList "+
"WHERE indexCommentBlackList.indexId IN "+
" (SELECT indexParents.indexId "+
" FROM indexParents "+
" WHERE indexParents.folderId = ?)");
st.setInt(1, id);
st.execute();
st.close();
/* we remove all the files */
st = db.getConnection().prepareStatement("DELETE FROM files WHERE files.indexParent IN "+
"(SELECT indexParents.indexId FROM indexParents WHERE indexParents.folderId = ?)");
st.setInt(1, id);
st.execute();
st.close();
/* we remove all the links */
st = db.getConnection().prepareStatement("DELETE FROM links WHERE links.indexParent IN "+
"(SELECT indexParents.indexId FROM indexParents WHERE indexParents.folderId = ?)");
st.setInt(1, id);
st.execute();
st.close();
/* we remove all the indexes */
st = db.getConnection().prepareStatement("DELETE FROM indexes WHERE indexes.id IN "+
"(SELECT indexParents.indexId FROM indexParents WHERE indexParents.folderId = ?)");
st.setInt(1, id);
st.execute();
st.close();
/* we remove all the child folders */
/* we must to it this way, else we have problems with foreign key */
deleteChildFoldersRecursivly(id);
st = db.getConnection().prepareStatement("DELETE FROM indexFolders WHERE indexFolders.id = ?");
st.setInt(1, id);
st.execute();
st.close();
/* we clean the joint tables */
st = db.getConnection().prepareStatement("DELETE FROM indexParents "+
"WHERE indexId IN "+
"(SELECT indexParents.indexId FROM indexParents WHERE indexParents.folderId = ?)");
st.setInt(1, id);
st.execute();
st.close();
st = db.getConnection().prepareStatement("DELETE FROM folderParents "+
"WHERE (folderId IN "+
"(SELECT folderParents.folderId FROM folderParents WHERE folderParents.parentId = ?))");
st.setInt(1, id);
st.execute();
st.close();
st = db.getConnection().prepareStatement("DELETE FROM folderParents "+
"WHERE folderId = ?");
st.setInt(1, id);
st.execute();
st.close();
} catch(SQLException e) {
Logger.error(this, "Error while removing the folder: "+e.toString());
}
}
}
/**
* Update from freenet / Update the freenet version, depending of the index kind (recursive)
*/
public int insertOnFreenet(Observer observer, IndexBrowserPanel indexBrowser, FCPQueueManager queueManager) {
int i = 0;
synchronized(db.dbLock) {
try {
PreparedStatement st;
if (id >= 0) {
st = db.getConnection().prepareStatement("SELECT indexId from indexParents WHERE folderId = ?");
st.setInt(1, id);
} else {
st = db.getConnection().prepareStatement("SELECT indexId from indexParents WHERE folderId IS NULL");
}
ResultSet set = st.executeQuery();
while(set.next()) {
(new Index(db, config,
set.getInt("indexId"))).insertOnFreenet(observer, indexBrowser, queueManager);
i++;
}
st.close();
} catch(SQLException e) {
Logger.error(this, "Unable to start insertions because: "+e.toString());
}
}
return i;
}
/**
* Update from freenet using the given revision
*/
public int downloadFromFreenet(Observer observer, IndexTree indexTree, FCPQueueManager queueManager) {
return downloadFromFreenet(observer, indexTree, queueManager, -1);
}
public int downloadFromFreenet(Observer observer, IndexTree indexTree, FCPQueueManager queueManager, int rev) {
int i = 0;
synchronized(db.dbLock) {
try {
PreparedStatement st;
if (id >= 0) {
st = db.getConnection().prepareStatement("SELECT indexParents.indexId "+
"FROM indexParents WHERE folderId = ?");
st.setInt(1, id);
} else {
st = db.getConnection().prepareStatement("SELECT id FROM indexes");
}
ResultSet set = st.executeQuery();
while(set.next()) {
int indexId;
if (id >= 0)
indexId = set.getInt("indexId");
else
indexId = set.getInt("id");
/* TODO : give publickey too immediatly */
if (rev < 0)
(new Index(db, config, indexId)).downloadFromFreenet(observer, indexTree, queueManager);
else
(new Index(db, config, indexId)).downloadFromFreenet(observer, indexTree, queueManager, rev);
i++;
}
st.close();
} catch(SQLException e) {
Logger.error(this, "Unable to start insertions because: "+e.toString());
}
}
return i;
}
/**
* Get key(s)
*/
public String getPublicKey() {
String keys = "";
Logger.info(this, "getPublicKey()");
synchronized(db.dbLock) {
try {
PreparedStatement st;
if (id >= 0) {
st = db.getConnection().prepareStatement("SELECT indexes.publicKey FROM indexes "+
"WHERE indexes.id = "+
"(SELECT indexParents.id FROM indexParents "+
" WHERE indexParents.folderId = ?)");
st.setInt(1, id);
} else {
st = db.getConnection().prepareStatement("SELECT indexes.publicKey FROM indexes "+
"WHERE indexes.id = "+
"(SELECT indexParents.id FROM indexParents "+
" WHERE indexParents.folderId IS NULL)");
}
ResultSet set = st.executeQuery();
while(set.next()) {
keys += set.getString("publicKey") + "\n";
}
st.close();
} catch(SQLException e) {
Logger.error(this, "Unable to get public keys because: "+e.toString());
}
}
return keys;
}
public String getPrivateKey() {
String keys = "";
Logger.info(this, "getPrivateKey()");
synchronized(db.dbLock) {
try {
PreparedStatement st;
if (id >= 0) {
st = db.getConnection().prepareStatement("SELECT indexes.privateKey FROM indexes "+
"WHERE indexes.id = "+
"(SELECT indexParents.id FROM indexParents "+
" WHERE indexParents.folderId = ?)");
st.setInt(1, id);
} else {
st = db.getConnection().prepareStatement("SELECT indexes.privateKey FROM indexes "+
"WHERE indexes.id = "+
"(SELECT indexParents.id FROM indexParents "+
" WHERE indexParents.folderId IS NULL)");
}
ResultSet set = st.executeQuery();
while(set.next()) {
keys += set.getString("privateKey") + "\n";
}
st.close();
} catch(SQLException e) {
Logger.error(this, "Unable to get private keys because: "+e.toString());
}
}
if ("".equals(keys))
return null;
return keys;
}
public void reorder() {
int position;
synchronized(db.dbLock) {
try {
PreparedStatement selectSt;
PreparedStatement updateSt;
position = 0;
/* We first sort the index folders */
if (id >= 0) {
selectSt =
db.getConnection().prepareStatement("SELECT id FROM indexFolders WHERE parent = ? ORDER BY LOWER(name)");
} else {
selectSt =
db.getConnection().prepareStatement("SELECT id FROM indexFolders WHERE parent IS NULL ORDER BY LOWER(name)");
}
updateSt =
db.getConnection().prepareStatement("UPDATE indexFolders SET positionInTree = ? WHERE id = ?");
if (id >= 0)
selectSt.setInt(1, id);
ResultSet set = selectSt.executeQuery();
while(set.next()) {
updateSt.setInt(1, position);
updateSt.setInt(2, set.getInt("id"));
updateSt.execute();
position++;
}
selectSt.close();
updateSt.close();
/* next we sort the indexes */
if (id >= 0) {
selectSt =
db.getConnection().prepareStatement("SELECT id FROM indexes WHERE parent = ? ORDER BY LOWER(displayName)");
} else {
selectSt =
db.getConnection().prepareStatement("SELECT id FROM indexes WHERE parent IS NULL ORDER BY LOWER(displayName)");
}
updateSt =
db.getConnection().prepareStatement("UPDATE indexes SET positionInTree = ? WHERE id = ?");
if (id >= 0)
selectSt.setInt(1, id);
set = selectSt.executeQuery();
while(set.next()) {
updateSt.setInt(1, position);
updateSt.setInt(2, set.getInt("id"));
updateSt.execute();
position++;
}
selectSt.close();
updateSt.close();
} catch(SQLException e) {
Logger.error(this, "Error while reordering: "+e.toString());
}
}
}
public String getName() {
return toString();
}
private final static String yourIndexesStr = thaw.core.I18n.getMessage("thaw.plugin.index.yourIndexes");
public String toString() {
if (id < 0)
return yourIndexesStr;
if (name != null)
return name;
Logger.info(this, "toString()");
synchronized(db.dbLock) {
try {
PreparedStatement st;
st = db.getConnection().prepareStatement("SELECT name from indexfolders WHERE id = ? LIMIT 1");
st.setInt(1, id);
ResultSet set = st.executeQuery();
if (set.next()) {
st.close();
name = set.getString("name");
return name;
}
st.close();
Logger.error(this, "toString(): not found in the db ?!");
return null;
} catch(SQLException e) {
Logger.error(this, "Unable to get name because: "+e.toString());
}
}
return null;
}
public boolean equals(Object o) {
if (o == null || !(o instanceof IndexFolder))
return false;
if (((IndexTreeNode)o).getId() == getId())
return true;
return false;
}
public boolean isModifiable() {
/* disable for performance reasons */
return false;
}
public boolean realIsModifiable() {
if (children != null) {
synchronized(children) {
for (Iterator it = children.iterator();
it.hasNext();) {
IndexTreeNode child = (IndexTreeNode)it.next();
if (!child.isModifiable()) {
return false;
}
}
}
return true;
}
synchronized(db.dbLock) {
try {
PreparedStatement st;
if (id >= 0) {
st = db.getConnection().prepareStatement("SELECT count(indexes.id) FROM "+
"indexes JOIN indexParents ON indexes.id = indexParents.indexId "+
"WHERE indexParents.folderId = ?");
st.setInt(1, id);
} else {
st = db.getConnection().prepareStatement("SELECT count(indexes.id) FROM "+
"indexes JOIN indexParents ON indexes.id = indexParents.indexId "+
"WHERE indexParents.folderId IS NULL");
}
ResultSet set = st.executeQuery();
if(set.next()) {
int res;
res = set.getInt(1);
st.close();
if (res > 0)
return false;
else
return true;
}
st.close();
} catch(SQLException e) {
Logger.error(this, "unable to know if the folder contains only modifiable indexes because: "+e.toString());
}
}
return false;
}
public boolean setHasChangedFlag(boolean flag) {
setHasChangedFlagInMem(flag);
synchronized(db.dbLock) {
try {
PreparedStatement st;
if (id > 0) {
st = db.getConnection().prepareStatement("UPDATE indexes "+
"SET newRev = ? "+
"WHERE id IN "+
"(SELECT indexParents.indexId FROM indexParents WHERE indexParents.folderId = ?)");
st.setInt(2, id);
} else {
st = db.getConnection().prepareStatement("UPDATE indexes "+
"SET newRev = ?");
}
st.setBoolean(1, flag);
st.execute();
st.close();
} catch(SQLException e) {
Logger.error(this, "Error while changing 'hasChanged' flag: "+e.toString());
return false;
}
}
return true;
}
public boolean setNewCommentFlag(boolean flag) {
setNewCommentFlagInMem(flag);
synchronized(db.dbLock) {
try {
PreparedStatement st;
if (id > 0) {
st = db.getConnection().prepareStatement("UPDATE indexes "+
"SET newComment = ? "+
"WHERE id IN "+
"(SELECT indexParents.indexId FROM indexParents WHERE indexParents.folderId = ?)");
st.setInt(2, id);
} else {
st = db.getConnection().prepareStatement("UPDATE indexes "+
"SET newComment = ?");
}
st.setBoolean(1, flag);
st.execute();
st.close();
} catch(SQLException e) {
Logger.error(this, "Error while changing 'newComment' flag: "+e.toString());
return false;
}
}
return true;
}
public boolean setHasChangedFlagInMem(boolean flag) {
if (children != null) {
synchronized(children) {
for (Iterator it = children.iterator();
it.hasNext();) {
IndexTreeNode child = (IndexTreeNode)it.next();
child.setHasChangedFlagInMem(flag);
}
}
}
return true;
}
public boolean setNewCommentFlagInMem(boolean flag) {
if (children != null) {
synchronized(children) {
for (Iterator it = children.iterator();
it.hasNext();) {
IndexTreeNode child = (IndexTreeNode)it.next();
child.setNewCommentFlagInMem(flag);
}
}
}
return true;
}
private boolean lastHasChangedValue = false;
private boolean lastNewCommentValue = false;
private boolean hasLastHasChangedValueBeenSet = false;
public void forceFlagsReload() {
if (children != null) {
//synchronized(children) {
for (Iterator it = children.iterator();
it.hasNext();) {
IndexTreeNode child = (IndexTreeNode)it.next();
child.forceFlagsReload();
}
//}
}
hasLastHasChangedValueBeenSet = false;
hasChanged();
}
public boolean hasChanged() {
if (children != null) {
synchronized(children) {
for (Iterator it = children.iterator();
it.hasNext();) {
IndexTreeNode child = (IndexTreeNode)it.next();
if (child.hasChanged())
return true;
}
return false;
}
}
/* It's dirty and will probably cause graphical bug :/ */
if (hasLastHasChangedValueBeenSet)
return lastHasChangedValue;
synchronized(db.dbLock) {
try {
PreparedStatement st;
st = db.getConnection().prepareStatement("SELECT indexes.id "+
"FROM indexes JOIN indexParents ON indexes.id = indexParents.indexId "+
"WHERE indexParents.folderId = ? AND indexes.newRev = TRUE LIMIT 1");
st.setInt(1, id);
ResultSet set = st.executeQuery();
boolean ret;
ret = set.next();
st.close();
lastHasChangedValue = ret;
hasLastHasChangedValueBeenSet = true;
return ret;
} catch(SQLException e) {
Logger.error(this, "Error while trying to see if there is any change: "+e.toString());
}
}
return false;
}
public boolean hasNewComment() {
if (children != null) {
synchronized(children) {
for (Iterator it = children.iterator();
it.hasNext();) {
IndexTreeNode child = (IndexTreeNode)it.next();
if (child.hasNewComment())
return true;
}
return false;
}
}
/* It's dirty and will probably cause graphical bug :/ */
if (hasLastHasChangedValueBeenSet)
return lastNewCommentValue;
synchronized(db.dbLock) {
try {
PreparedStatement st;
st = db.getConnection().prepareStatement("SELECT indexes.id "+
"FROM indexes JOIN indexParents ON indexes.id = indexParents.indexId "+
"WHERE indexParents.folderId = ? AND indexes.newComment = TRUE LIMIT 1");
st.setInt(1, id);
ResultSet set = st.executeQuery();
boolean ret;
ret = set.next();
st.close();
lastNewCommentValue = ret;
hasLastHasChangedValueBeenSet = true;
return ret;
} catch(SQLException e) {
Logger.error(this, "Error while trying to see if there is any new comment: "+e.toString());
}
}
return false;
}
/**
* Will export private keys too !<br/>
* TODO: Improve perfs
*/
public Element do_export(Document xmlDoc, boolean withContent) {
Element e = xmlDoc.createElement("indexCategory");
if (id != -1)
e.setAttribute("name", name);
if(children == null)
loadChildren();
for(final Iterator it = children.iterator();
it.hasNext();) {
final IndexTreeNode node = (IndexTreeNode)(it.next());
e.appendChild(node.do_export(xmlDoc, withContent));
}
unloadChildren();
return e;
}
public IndexFolder getChildFolder(int id) {
return getChildFolder(id, true);
}
public IndexFolder getChildFolder(int id, boolean loadChildren) {
if (id < 0) {
Logger.notice(this, "getChildFolder() : Asked me to have the root ?!");
return null;
}
if (children == null && loadChildren)
loadChildren();
if (children == null)
return null;
for (Iterator it = children.iterator() ;
it.hasNext(); ) {
Object child = it.next();
if (child instanceof IndexFolder) {
if (((IndexFolder)child).getId() == id) {
return ((IndexFolder)child);
}
}
}
return null;
}
public Index getChildIndex(int id) {
return getChildIndex(id, true);
}
public Index getChildIndex(int id, boolean loadChildren) {
if (id < 0) {
Logger.error(this, "getChildIndex() : Invalid parameter !");
return null;
}
if (children == null && loadChildren)
loadChildren();
if (children == null)
return null;
for (Iterator it = children.iterator() ;
it.hasNext(); ) {
Object child = it.next();
if (child instanceof Index) {
if (((Index)child).getId() == id) {
return ((Index)child);
}
}
}
return null;
}
public boolean publishPrivateKey() {
return false;
}
}