title: JTree Lazy Load Expand
body: <p>Hope you are doing fine. </p>
  
  <p>I have a JTree which I load lazily using database query (each node). I have a button on the screen and when user clicks the button I perform some <code>insert/update/delete</code> in database and then add the model back in <code>Jtree</code> with only root and its immediate children using an SQL (this collapses the tree and selection and all expanded nodes collapse which is expected since it is a lazily loaded tree)</p>
  
  <p>What I want to accomplish is before user clicks button to <code>insert/update/delete</code>, I read all the expanded state and save it in  memory then when I re-initialize the <code>JTree</code> I loop through those expanded children and call <code>jtree.expandPath</code> but it does not expand the nodes :(. </p>
  
  <p>I even added a <code>TreeWillExpandListener</code> and in <code>treeWillExpand</code> event I added code to get the children of the node from database and I see that query does get executed to get the childreen but <code>JTree</code> still shows up as collapsed.</p>
  
  <p>I really need your help. Please advise. Here is the code snippet.</p>
  
  <pre><code>package marketdatagui;
  
  import javax.swing.JFrame;
  import javax.swing.JScrollPane;
  import javax.swing.JTree;
  import javax.swing.tree.DefaultTreeModel;
  import javax.swing.tree.TreeModel;
  import javax.swing.tree.TreePath;
  import javax.swing.event.TreeModelListener;
  import javax.swing.event.TreeModelEvent;
  import javax.swing.event.EventListenerList;
  import java.awt.event.WindowAdapter;
  import java.awt.event.WindowEvent;
  import java.util.List;
  import java.util.ArrayList;
  import java.util.Map;
  import java.util.HashMap;
  import java.io.File;
  import java.io.Serializable;
  import java.io.ObjectOutputStream;
  import java.io.ObjectInputStream;
  
  
  public class StressGroupModel
      implements TreeModel,Serializable, Cloneable
  {
      protected EventListenerList listeners;
  
      private static final Object LEAF = new Serializable() { };
  
      private Map map;
  
      private NodeData root;
  
      private class NodeData{
          String id;
          String name;
  
          public String toString(){
              return name;
          }
      }
  
      public StressGroupModel()
      {
          this.root = new NodeData();
          root.id = "Root";
          root.name = "Root";
  
          this.listeners = new EventListenerList();
  
          this.map = new HashMap();
  
          List rootChildren = new ArrayList();
  
          NodeData d1 = new NodeData();
          d1.id = "5000007";
          d1.name = "Name5000007";
  
          rootChildren.add(d1);
  
          NodeData d2 = new NodeData();
          d2.id = "10000054";
          d2.name = "Name10000054";
  
          rootChildren.add(d2);
          map.put(root.id, rootChildren);
      }
  
  
      public Object getRoot()
      {
          return root;
      }
  
      public boolean isLeaf(Object node)
      {
          return map.get(node) == LEAF;
      }
  
      public int getChildCount(Object node)
      {
          List children = children(node);
  
          if (children == null)
              return 0;
  
          return children.size();
      }
  
      public Object getChild(Object parent, int index)
      {
          return children(parent).get(index);
      }
  
      public int getIndexOfChild(Object parent, Object child)
      {
          return children(parent).indexOf(child);
      }
  
      protected List children(Object node)
      {
          NodeData s = (NodeData)node;
  
          Object value = map.get(s.id);
  
          if (value == LEAF)
              return null;
  
          List children = (List)value;
  
          if (!"Root".equals(s.id))
          {
              String[][] dbData = getChildren(s.id);
  
              if (dbData != null)
              {
                  children = new ArrayList(dbData.length);
                  for (int i = 0; i &lt; dbData.length; i++)
                  {
                      NodeData d = new NodeData();
                      d.id = dbData[i][1];
                      d.name = dbData[i][1] + "Name";
                      children.add(d);
                      if ("R".equals(dbData[i][2]))
                          map.put(d, LEAF);
                  }
              }
              else
                  children = new ArrayList(0);
  
              map.put(s.id, children);       
          }
  
          return children;
      }
  
      private String[][] getChildren(String parent_uid){
          String sql = "select parent_uid,child_uid,child_type from stress_groups_mapping "
                + " where parent_uid="+ parent_uid
                +" order by parent_uid, child_uid";
  
          return Util.getTableData(sql);
      }
  
      public void valueForPathChanged(TreePath path, Object value)
      {
      }
  
      public void addTreeModelListener(TreeModelListener l)
      {
          listeners.add(TreeModelListener.class, l);
      }
  
      public void removeTreeModelListener(TreeModelListener l)
      {
          listeners.remove(TreeModelListener.class, l);
      }
  
      public Object clone()
      {
          try
          {
              StressGroupModel clone = (StressGroupModel)super.clone();
  
              clone.listeners = new EventListenerList();
  
              clone.map = new HashMap(map);
  
              return clone;
          }
          catch (CloneNotSupportedException e)
          {
              throw new InternalError();
          }
      }
  
  }
  </code></pre>
  
  <ul>
  <li>Here is how I create the tree</li>
  </ul>
  
  <blockquote>
    <p>public createTree{</p>
  
  <pre><code>JFrame f = new JFrame("Tree Dragging Tester");
            DefaultMutableTreeNode root = new DefaultMutableTreeNode(new Object());
            jtree = new JTree(new StressGroupModel());
            TreeWillExpandListener treeWillExpandListener = new TreeWillExpandListener() {
                  public void treeWillCollapse(TreeExpansionEvent treeExpansionEvent)
                      throws ExpandVetoException {
  
  
                  }
  
                  public void treeWillExpand(TreeExpansionEvent treeExpansionEvent) throws ExpandVetoException {
                      TreePath path = treeExpansionEvent.getPath();
                      Object node =  path.getLastPathComponent();
                      ((StressGroupModel)jtree.getModel()).getChildCount(node);
                    }
  
  
            };
  
            jtree.addTreeWillExpandListener(treeWillExpandListener);
  
            f.getContentPane().add(jtree, BorderLayout.CENTER);
            f.setSize(300, 200);
            f.setVisible(true);
  }
  </code></pre>
  </blockquote>
  
  <ul>
  <li>Here is how I save the expanded state</li>
  </ul>
  
  <blockquote>
    <p>Enumeration paths = jtree.getExpandedDescendants(new
    TreePath(jtree.getModel().getRoot()));</p>
  </blockquote>
  
  <ul>
  <li>Do insert/update/delete DB stuffs</li>
  <li>Now re-initialize the model and add back to JTree (so it picks latest
  values from DB)</li>
  <li>Now I loop and call expand to expand the nodes that user expanded
  before he clicked the button but alas it stays collapsed :(</li>
  </ul>
  
  <blockquote>
    <p>jtree.setModel(new StressGroupModel());
              while (paths.hasMoreElements()) {</p>
  
  <pre><code>            TreePath treePath = (TreePath) paths.nextElement();
  
              try {
  
              jtree.expandPath(treePath);
              jtree.setSelectionPath(treePath);
  
              }
              catch(Exception ex){
  
              }
  
          }
  </code></pre>
  </blockquote>