// We create a dummy process which we put into the clipboard.
// In order to force all object references to be absolute, we choose the System model
// as parent model of the dummy process (this is also fine for objects which belong
// to the System model itself since these object will always be referenced using their
// local name)
ProcessItem process = new ProcessItemImpl();
process.setName("ProcessDummy");
process.setModel(ModelConnector.getInstance().getModelByQualifier(CoreConstants.SYSTEM_MODEL_QUALIFIER));
// When copying a node, we perform the following steps:
// 1. Encode the geometry
// 2. Clone the object
// 3. Add the cloned object to the dummy process
// 4. Generate reference names from the actual object references (e. g. for actions, sub processes, data types etc.)
// Node that contains the selected sockets
ActivityNodeImpl socketHolder = null;
// List of source nodes that have been copied
ArrayList copiedSourceNodes = new ArrayList();
// Socket that contains the selected parameters
NodeSocket paramHolder = null;
for (FigureEnumeration fe = workspaceView.selectionElements(); fe.hasMoreElements();)
{
Figure next = fe.nextFigure();
if (next instanceof NodeFigure)
{
NodeFigure nodeFigure = (NodeFigure) next;
nodeFigure.encodeGeometry();
Node node = nodeFigure.getNode();
// Remember that we have copied this one
copiedSourceNodes.add(node);
// Clone the node and add it to the process
node = (Node) node.clone();
process.addNode(node);
copyFlavor = ClientFlavors.PROCESS_ITEM;
}
else if (next instanceof TextElementFigure)
{
TextElementFigure textElementFigure = (TextElementFigure) next;
textElementFigure.encodeGeometry();
TextElement textElement = textElementFigure.getTextElement();
// Clone the element and add it to the process
textElement = (TextElement) textElement.clone();
process.addTextElement(textElement);
copyFlavor = ClientFlavors.PROCESS_ITEM;
}
else if (next instanceof SocketFigure)
{
SocketFigure socketFigure = (SocketFigure) next;
socketFigure.encodeGeometry();
NodeSocket socket = socketFigure.getNodeSocket();
if (socketHolder == null)
{
socketHolder = new ActivityNodeImpl();
socketHolder.setName("NodeDummy");
process.addNode(socketHolder);
}
// Clone the socketand add it to the dummy node
socket = (NodeSocket) socket.clone();
socketHolder.addSocket(socket);
copyFlavor = ClientFlavors.NODE_SOCKETS;
}
else if (next instanceof ParamFigure)
{
ParamFigure paramFigure = (ParamFigure) next;
NodeParam param = paramFigure.getNodeParam();
if (paramHolder == null)
{
if (socketHolder == null)
{
socketHolder = new ActivityNodeImpl();
socketHolder.setName("NodeDummy");
process.addNode(socketHolder);
}
paramHolder = new NodeSocketImpl();
paramHolder.setName("SocketDummy");
socketHolder.addSocket(paramHolder);
}
// Clone the socket and add it to the dummy node
param = (NodeParam) param.clone();
paramHolder.addParam(param, - 1);
copyFlavor = ClientFlavors.NODE_PARAMS;
}
}
// When copying a link, we perform the following steps:
// 1. Encode the geometry
// 2. Generate reference names from the actual object references
// (e. g. node names for control links, parameter names for data links etc.)
// 3. Clone the object
// 4. Add the cloned object to the dummy process
// 5. Re-establish the object references (now based on the elements of the dummy process)
// If this fails, the object will be removed from the dummy process again.
StandardMsgContainer msgContainer = ModelConnector.getInstance().getMsgContainer();
msgContainer.clearMsgs();
for (FigureEnumeration fe = workspaceView.selectionElements(); fe.hasMoreElements();)
{
Figure next = fe.nextFigure();
if (next instanceof FlowConnection)
{
FlowConnection flowConnection = (FlowConnection) next;
ControlLink link = flowConnection.getControlLink();
if (! copiedSourceNodes.contains(link.getSourceSocket().getNode())
|| ! copiedSourceNodes.contains(link.getTargetSocket().getNode()))
{
// Link source or target has not been copied
continue;
}
flowConnection.encodeGeometry();
link = (ControlLink) link.clone();
process.addControlLink(link);
if (! msgContainer.isEmpty())
{
// One of the end points of the link is not present in the copied set,
// so remove the link from the dummy process again.
process.removeControlLink(link);
msgContainer.clearMsgs();
}
}
else if (next instanceof ParamConnection)
{
ParamConnection paramConnection = (ParamConnection) next;
DataLink link = paramConnection.getDataLink();
Param sourceParam = link.getSourceParam();
Param targetParam = link.getTargetParam();
if (sourceParam instanceof NodeParam)
{
if (! copiedSourceNodes.contains(((NodeParam) sourceParam).getSocket().getNode()))
{
// Link source or target has not been copied
continue;
}
}
else
{
// Don't copy process variable links
continue;
}
if (targetParam instanceof NodeParam)
{
if (! copiedSourceNodes.contains(((NodeParam) targetParam).getSocket().getNode()))
{
// Link source or target has not been copied
continue;
}
}
else
{
// Don't copy process variable links
continue;
}
paramConnection.encodeGeometry();
link = (DataLink) link.clone();
process.addDataLink(link);
if (! msgContainer.isEmpty())
{
// One of the end points of the link is not present in the copied set,
// so remove the link from the dummy process again.
process.removeDataLink(link);
msgContainer.clearMsgs();
}
}
}
// Re-establish inter-object links and links to other items
// and remove links to figures to make the gc work
// TODO Fix 4 This seems to produce some maintainReferences error: "Cannot resolve ... in Model /System"
process.maintainReferences(ModelObject.RESOLVE_GLOBAL_REFS | ModelObject.RESOLVE_LOCAL_REFS | ModelObject.UNLINK_FROM_REPRESENTATION);
if (copyFlavor != null && (process.getNodes().hasNext() || process.getTextElements().hasNext()))
{
Transferable ret = new SimpleTransferable(process, copyFlavor);
if (copiedSourceNodes.size() == 1)
{