Sunday Oct 05, 2008

Serializing Marilyn Monroe

I made a lot of progress with node serialization. Now, when I start up my application, I see ALL of the following selected:

The above are selected, without me doing anything at start up, because those were the ones I had selected at the time the application shut down. Hence, I serialized ALL the selected nodes. Before, I only managed to work with a single selection, instead of the multiple selection you see above, because I hadn't figured out how to iterate over my handles correctly and add them to the array of nodes that is selected at start up. The important changes over the previous blog entry is in bold below, within the context of everything else that is relevant here:

@Override
public Object writeReplace() {

    Handle[] selectedHandles = NodeOp.toHandles(em.getSelectedNodes());
    return new ResolvableHelper(selectedHandles);
    
}

public final static class ResolvableHelper implements Serializable {

    private static final long serialVersionUID = 1L;
    public Handle[] selectedHandles;

    private ResolvableHelper(Handle[] selectedHandles) {
        this.selectedHandles = selectedHandles;
    }

    public Object readResolve() {
        
        try {
            
            DemoTopComponent result = DemoTopComponent.getDefault();

            String path;
            int noOfHandles = selectedHandles.length;

            Node rootNode = result.getExplorerManager().getRootContext();
            Node foundNode = null;
            Node[] allFoundNodes = new Node[noOfHandles];

            //We build up an array of found nodes:  
            for (int i = 0; i < noOfHandles; i++) {
                Handle handle = selectedHandles[i];
                path = handle.getNode().getDisplayName();
                foundNode = NodeOp.findPath(rootNode, new String[]{path});
                if (foundNode != null) {
                    allFoundNodes[i] = foundNode;
                }
            }

            //Then we select the array, which means each node is selected:
            if (allFoundNodes != null) {
                try {
                    result.getExplorerManager().setSelectedNodes(allFoundNodes);
                } catch (PropertyVetoException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }

            return result;

        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }

        return null;

    }
    
}

However, in real life your children would probably have children too. (And your children's children would have children, ad nauseum.) How to serialize the entire hierarchy of selections from parent to child to grandchild and so on? Below you see my Marilyn Monroe window (search this blog for all the code, which is definitely somewhere), but this time the nodes that are selected below are selected at start up, i.e., automatically, because I serialized them at the time the application shut down:

Below is all the relevant code. Instead of serializing the entire set of selected nodes, we only serialize the first one. The cool thing is that when you serialize a node, you store the COMPLETE node, which means that all the information on the node is available to you, such as who its parent is! So, when the application restarts, we get the parent of the serialized node and, based on whether the parent is named 'Root' (which is the name of the hidden root node of the explorer view), we either select only the node or also the parent node:

@Override
public Object writeReplace() {
    Handle childHandle = NodeOp.toHandles(em.getSelectedNodes())[0];
    return new ResolvableHelper(childHandle);
}

public final static class ResolvableHelper implements Serializable {

    private static final long serialVersionUID = 1L;
    public Handle parentHandle;
    public Handle childHandle;

    private ResolvableHelper(Handle childHandle) {
        try {
            this.childHandle = childHandle;
            this.parentHandle = childHandle.getNode().getParentNode().getHandle();
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
    }

    public Object readResolve() {

        try {

            MarilynTopComponent result = MarilynTopComponent.getDefault();

            String parentName = parentHandle.getNode().getDisplayName();
            String childName = childHandle.getNode().getDisplayName();

            Node root = result.getExplorerManager().getRootContext();

            Node parentNode = null;
            Node childNode = null;

            //We know a movie has been selected if the parent is not named 'Root',
            //which is the name of the hidden root node of the explorer view,
            //so we find two nodes and select both:
            if (!parentName.equals("Root")) {
                parentNode = NodeOp.findPath(root, new String[]{parentName, childName});
                childNode = NodeOp.findPath(root, new String[]{parentName});
                result.getExplorerManager().setSelectedNodes(new Node[]{childNode, parentNode});
            } 
            //If the parent is 'Root', then we're dealing with a category,
            //so we only need to find one node, the child of the 'Root', which we then select:
            else {
                childNode = NodeOp.findPath(root, new String[]{childName});
                result.getExplorerManager().setSelectedNodes(new Node[]{childNode});
            }

            return result;

        } catch (PropertyVetoException ex) {
            Exceptions.printStackTrace(ex);
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }

        return null;

    }

}

This principle could be extended for a larger hierarchy of nodes and, if you don't only serialize a single node, your user could potentially see many hierarchies of selected nodes at the time that the application restarts.

About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« October 2008 »
SunMonTueWedThuFriSat
   
2
7
8
11
12
20
24
25
27
31
 
       
Today