tags:

views:

291

answers:

2

I have a program that shows a tree representation of an XML file. Using a number of sources online I have Copy/Paste within a single instance of the program working. I am using the system Clipboard. What I need though is to be able to copy a node from one instance of the program and paste to a different instance of the same program.

I have tried a number of different options, all resulting in the same behavior. When pasting from within the same application the clipboardContent contains a "transferable" object with the correct data along with an isLocal set to "true". When I perform the copy and then attempt the paste from another instance of the same program running the clipboardContent contains a "flavorsToData" HashMap and "flavors" values, the check for isDataFlavorSupported fails (never hits my custom class that represents the new flavor).

I have tried using different values for the requestor object in the getContents() call. Likewise I have tried a few different ClipboardOwners for the setContent() call. Neither seem to change the behavior in any way.

I am sorely tempted to convert the node that is being copied back into a textual XML format, and then on the paste convert back to the DOM model, but would rather not if possible.

This class is used to define the DataFlavor and transferable object:

import java.awt.datatransfer.*; import org.w3c.dom.Node;

public class NodeCopyPaste implements Transferable {

    static public DataFlavor NodeFlavor;
    private DataFlavor [] supportedFlavors = {NodeFlavor};
    public Node aNode;

    public NodeCopyPaste (Node paraNode) {
        aNode = paraNode;
        try {
            NodeFlavor = new DataFlavor (Class.forName ("org.w3c.dom.Node"), "Node");
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace ();
        }
    }

    public synchronized DataFlavor [] getTransferDataFlavors () {
        return (supportedFlavors);
    }

    public boolean isDataFlavorSupported (DataFlavor nodeFlavor) {
        return (nodeFlavor.equals (NodeFlavor));
    }

    public synchronized Object getTransferData (DataFlavor nFlavor) throws UnsupportedFlavorException {
        if (nFlavor.equals (NodeFlavor))
            return (this);
        else
            throw new UnsupportedFlavorException (nFlavor);
    }

    public void lostOwnership (Clipboard parClipboard, Transferable parTransferable) {
    } 
}

I define a Clipboard object from the main application screen and then tie in copy and paste handlers for the mouse clicks:

During initialization I assign the system clipboard:

    clippy = Toolkit.getDefaultToolkit().getSystemClipboard();

Copy Handler

    Node copyNode = ((CLIInfo) node.getUserObject()).DOMNode.cloneNode(true);
    NodeCopyPaste contents = new NodeCopyPaste(copyNode);
    clippy.setContents (contents, null);

Paste Handler

    Transferable clipboardContent = clippy.getContents (null);
    Node clonedNode = null;
    if ((clipboardContent != null) &&
        (clipboardContent.isDataFlavorSupported (NodeCopyPaste.NodeFlavor))) {
    try {
            NodeCopyPaste tempNCP = (NodeCopyPaste) clipboardContent.getTransferData (NodeCopyPaste.NodeFlavor);
            clonedNode = tempNCP.aNode.cloneNode(true);
        }
    catch (Exception e) {
            e.printStackTrace ();
    }

Thanks!

+1  A: 

To transfer clipboard data between processes you need to use a Serializable class as the representation class for your flavor. org.w3c.dom.Node does not extend Serializable, so your NodeFlavor cannot be copied to another process.

Note also that you are implementing getTransferData() incorrectly - the object returned should be an instance of the representation class.

rwhit
A: 

Speaking of serialization: consider using JAXB for marshalling/unmarshalling XML data (which can be seen as serializing/deserializing).

java.is.for.desktop