This is an automated email from the ASF dual-hosted git repository.

mcasters pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new e7cb53117e issue #6954 (TransformErrorMeta) (#6957)
e7cb53117e is described below

commit e7cb53117edaca940470d3c39d70d35c46e249b9
Author: Matt Casters <[email protected]>
AuthorDate: Sun Apr 5 14:42:45 2026 +0200

    issue #6954 (TransformErrorMeta) (#6957)
    
    issue #6955 (HopGuiPipelineClipboardDelegate)
    issue #6950 (DataSet click)
---
 .../hop/pipeline/transform/TransformErrorMeta.java |  53 ++--
 .../apache/hop/pipeline/ModPartitionerTest.java    |  13 +
 .../pipeline/transform/TransformErrorMetaTest.java |  50 ++++
 .../xp/LocationMouseDoubleClickExtensionPoint.java |   7 +-
 .../delegates/HopGuiPipelineClipboardDelegate.java | 299 ++++++++++-----------
 5 files changed, 233 insertions(+), 189 deletions(-)

diff --git 
a/engine/src/main/java/org/apache/hop/pipeline/transform/TransformErrorMeta.java
 
b/engine/src/main/java/org/apache/hop/pipeline/transform/TransformErrorMeta.java
index ca06324bf2..ea0848614f 100644
--- 
a/engine/src/main/java/org/apache/hop/pipeline/transform/TransformErrorMeta.java
+++ 
b/engine/src/main/java/org/apache/hop/pipeline/transform/TransformErrorMeta.java
@@ -21,7 +21,9 @@ import java.util.List;
 import lombok.Getter;
 import lombok.Setter;
 import org.apache.hop.core.changed.ChangedFlag;
+import org.apache.hop.core.exception.HopException;
 import org.apache.hop.core.exception.HopRuntimeException;
+import org.apache.hop.core.exception.HopXmlException;
 import org.apache.hop.core.row.IRowMeta;
 import org.apache.hop.core.row.IValueMeta;
 import org.apache.hop.core.row.RowMeta;
@@ -31,6 +33,8 @@ import org.apache.hop.core.util.Utils;
 import org.apache.hop.core.variables.IVariables;
 import org.apache.hop.core.xml.XmlHandler;
 import org.apache.hop.metadata.api.HopMetadataProperty;
+import org.apache.hop.metadata.serializer.memory.MemoryMetadataProvider;
+import org.apache.hop.metadata.serializer.xml.XmlMetadataUtil;
 import org.w3c.dom.Node;
 
 /** This class contains the metadata to handle proper error handling on a 
transform level. */
@@ -155,40 +159,25 @@ public class TransformErrorMeta extends ChangedFlag 
implements Cloneable {
     }
   }
 
-  public String getXml() {
-    return XmlHandler.openTag(TransformErrorMeta.XML_ERROR_TAG)
-        + XmlHandler.addTagValue(
-            TransformErrorMeta.XML_SOURCE_TRANSFORM_TAG,
-            sourceTransform != null ? sourceTransform.getName() : "")
-        + XmlHandler.addTagValue(
-            TransformErrorMeta.XML_TARGET_TRANSFORM_TAG,
-            targetTransform != null ? targetTransform.getName() : "")
-        + XmlHandler.addTagValue("is_enabled", enabled)
-        + XmlHandler.addTagValue("nr_valuename", nrErrorsValueName)
-        + XmlHandler.addTagValue("descriptions_valuename", 
errorDescriptionsValueName)
-        + XmlHandler.addTagValue("fields_valuename", errorFieldsValueName)
-        + XmlHandler.addTagValue("codes_valuename", errorCodesValueName)
-        + XmlHandler.addTagValue("max_errors", maxErrors)
-        + XmlHandler.addTagValue("max_pct_errors", maxPercentErrors)
-        + XmlHandler.addTagValue("min_pct_rows", minPercentRows)
-        + XmlHandler.closeTag(TransformErrorMeta.XML_ERROR_TAG);
+  public String getXml() throws HopException {
+    return XmlHandler.aroundTag(XML_ERROR_TAG, 
XmlMetadataUtil.serializeObjectToXml(this));
   }
 
-  public TransformErrorMeta(Node node, List<TransformMeta> transforms) {
-    sourceTransform =
-        TransformMeta.findTransform(
-            transforms, XmlHandler.getTagValue(node, 
TransformErrorMeta.XML_SOURCE_TRANSFORM_TAG));
-    targetTransform =
-        TransformMeta.findTransform(
-            transforms, XmlHandler.getTagValue(node, 
TransformErrorMeta.XML_TARGET_TRANSFORM_TAG));
-    enabled = "Y".equals(XmlHandler.getTagValue(node, "is_enabled"));
-    nrErrorsValueName = XmlHandler.getTagValue(node, "nr_valuename");
-    errorDescriptionsValueName = XmlHandler.getTagValue(node, 
"descriptions_valuename");
-    errorFieldsValueName = XmlHandler.getTagValue(node, "fields_valuename");
-    errorCodesValueName = XmlHandler.getTagValue(node, "codes_valuename");
-    maxErrors = XmlHandler.getTagValue(node, "max_errors");
-    maxPercentErrors = XmlHandler.getTagValue(node, "max_pct_errors");
-    minPercentRows = XmlHandler.getTagValue(node, "min_pct_rows");
+  @Getter
+  public static class Transforms {
+    private List<TransformMeta> transforms;
+  }
+
+  public TransformErrorMeta(Node node, List<TransformMeta> transforms) throws 
HopXmlException {
+    // The deSerializeFromXml call searches for a List field called 
'transforms' in the provided
+    // Object.
+    // Normally this is the transform metadata but here we wrap it a tiny 
class.
+    //
+    Transforms parentObject = new Transforms();
+    parentObject.transforms = transforms;
+
+    XmlMetadataUtil.deSerializeFromXml(
+        parentObject, null, node, TransformErrorMeta.class, this, new 
MemoryMetadataProvider());
   }
 
   public IRowMeta getErrorRowMeta(IVariables variables) {
diff --git 
a/engine/src/test/java/org/apache/hop/pipeline/ModPartitionerTest.java 
b/engine/src/test/java/org/apache/hop/pipeline/ModPartitionerTest.java
index 0232daf382..5562f78fa9 100644
--- a/engine/src/test/java/org/apache/hop/pipeline/ModPartitionerTest.java
+++ b/engine/src/test/java/org/apache/hop/pipeline/ModPartitionerTest.java
@@ -21,9 +21,12 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 import java.util.List;
 import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.xml.XmlHandler;
 import org.apache.hop.junit.rules.RestoreHopEngineEnvironmentExtension;
+import org.apache.hop.metadata.serializer.xml.XmlMetadataUtil;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.w3c.dom.Node;
 
 @ExtendWith(RestoreHopEngineEnvironmentExtension.class)
 class ModPartitionerTest {
@@ -37,4 +40,14 @@ class ModPartitionerTest {
     assertNotNull(tester);
     tester.testSerialization();
   }
+
+  @Test
+  void testSerializationRoundTrip() throws HopException {
+    ModPartitioner test = new ModPartitioner();
+    test.setFieldName("field1");
+
+    String xml = XmlHandler.aroundTag("p", 
XmlMetadataUtil.serializeObjectToXml(test));
+
+    Node node = XmlHandler.loadXmlString(xml, "p");
+  }
 }
diff --git 
a/engine/src/test/java/org/apache/hop/pipeline/transform/TransformErrorMetaTest.java
 
b/engine/src/test/java/org/apache/hop/pipeline/transform/TransformErrorMetaTest.java
index 66d3bec890..6e2848f3cd 100644
--- 
a/engine/src/test/java/org/apache/hop/pipeline/transform/TransformErrorMetaTest.java
+++ 
b/engine/src/test/java/org/apache/hop/pipeline/transform/TransformErrorMetaTest.java
@@ -19,14 +19,30 @@ package org.apache.hop.pipeline.transform;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.hop.core.annotations.Transform;
+import org.apache.hop.core.plugins.PluginRegistry;
+import org.apache.hop.core.plugins.TransformPluginType;
 import org.apache.hop.core.row.IRowMeta;
 import org.apache.hop.core.row.IValueMeta;
 import org.apache.hop.core.variables.IVariables;
 import org.apache.hop.core.variables.Variables;
+import org.apache.hop.core.xml.XmlHandler;
+import org.apache.hop.pipeline.transform.transforms.FakeMeta;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.w3c.dom.Node;
 
 class TransformErrorMetaTest {
+  @BeforeEach
+  void setUp() throws Exception {
+    PluginRegistry registry = PluginRegistry.getInstance();
+    registry.registerPluginClass(
+        FakeMeta.class.getName(), TransformPluginType.class, Transform.class);
+  }
 
   @Test
   void testGetErrorRowMeta() {
@@ -57,4 +73,38 @@ class TransformErrorMetaTest {
     assertEquals(IValueMeta.TYPE_STRING, result.getValueMeta(3).getType());
     assertEquals("errorCodes", result.getValueMeta(3).getName());
   }
+
+  @Test
+  void testSerialization() throws Exception {
+    List<TransformMeta> transforms = new ArrayList<>();
+    TransformMeta t1 = new TransformMeta("t1", new FakeMeta());
+    transforms.add(t1);
+    TransformMeta t2 = new TransformMeta("t1", new FakeMeta());
+    transforms.add(t2);
+
+    TransformErrorMeta meta = new TransformErrorMeta();
+    meta.setSourceTransform(t1);
+    meta.setTargetTransform(t2);
+    meta.setEnabled(true);
+    meta.setMaxErrors("400");
+    meta.setMinPercentRows("100");
+    meta.setMaxPercentErrors("25");
+    meta.setErrorFieldsValueName("errorFields");
+    meta.setErrorCodesValueName("errorCodes");
+    meta.setErrorDescriptionsValueName("errorDescriptions");
+
+    String xml = meta.getXml();
+    Node node = XmlHandler.loadXmlString(xml, 
TransformErrorMeta.XML_ERROR_TAG);
+    TransformErrorMeta copy = new TransformErrorMeta(node, transforms);
+
+    assertEquals(meta.getSourceTransform(), copy.getSourceTransform());
+    assertEquals(meta.getTargetTransform(), copy.getTargetTransform());
+    assertTrue(copy.isEnabled());
+    assertEquals("400", copy.getMaxErrors());
+    assertEquals("100", copy.getMinPercentRows());
+    assertEquals("25", copy.getMaxPercentErrors());
+    assertEquals("errorFields", copy.getErrorFieldsValueName());
+    assertEquals("errorCodes", copy.getErrorCodesValueName());
+    assertEquals("errorDescriptions", copy.getErrorDescriptionsValueName());
+  }
 }
diff --git 
a/plugins/misc/testing/src/main/java/org/apache/hop/testing/xp/LocationMouseDoubleClickExtensionPoint.java
 
b/plugins/misc/testing/src/main/java/org/apache/hop/testing/xp/LocationMouseDoubleClickExtensionPoint.java
index d202f3b466..b83a657208 100644
--- 
a/plugins/misc/testing/src/main/java/org/apache/hop/testing/xp/LocationMouseDoubleClickExtensionPoint.java
+++ 
b/plugins/misc/testing/src/main/java/org/apache/hop/testing/xp/LocationMouseDoubleClickExtensionPoint.java
@@ -91,6 +91,7 @@ public class LocationMouseDoubleClickExtensionPoint
           // Check if this is the flask...
           //
           if 
(DataSetConst.AREA_DRAWN_INPUT_DATA_SET.equals(areaOwner.getParent())) {
+            pipelineGraphExtension.setPreventingDefault(true);
 
             // Open the dataset double-clicked on...
             //
@@ -113,8 +114,9 @@ public class LocationMouseDoubleClickExtensionPoint
               }
             }
           } else if 
(DataSetConst.AREA_DRAWN_GOLDEN_DATA_SET.equals(areaOwner.getParent())) {
+            pipelineGraphExtension.setPreventingDefault(true);
 
-            // Open the dataset double clicked on...
+            // Open the dataset double-clicked on...
             //
             String transformName = (String) areaOwner.getOwner();
 
@@ -136,8 +138,9 @@ public class LocationMouseDoubleClickExtensionPoint
               }
             }
           } else if 
(DataSetConst.AREA_DRAWN_GOLDEN_DATA_RESULT.equals(areaOwner.getParent())) {
+            pipelineGraphExtension.setPreventingDefault(true);
 
-            // Open the dataset double clicked on...
+            // Open the dataset double-clicked on...
             //
             String transformName = (String) areaOwner.getOwner();
 
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineClipboardDelegate.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineClipboardDelegate.java
index 4aa20a69ec..062c8f5c8f 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineClipboardDelegate.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineClipboardDelegate.java
@@ -18,12 +18,15 @@
 package org.apache.hop.ui.hopgui.file.pipeline.delegates;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
 import org.apache.hop.base.BaseHopMeta;
 import org.apache.hop.core.Const;
 import org.apache.hop.core.NotePadMeta;
 import org.apache.hop.core.exception.HopException;
+import org.apache.hop.core.exception.HopPluginLoaderException;
+import org.apache.hop.core.exception.HopXmlException;
 import org.apache.hop.core.gui.Point;
 import org.apache.hop.core.logging.ILogChannel;
 import org.apache.hop.core.xml.XmlHandler;
@@ -40,9 +43,12 @@ import org.apache.hop.ui.core.gui.GuiResource;
 import org.apache.hop.ui.hopgui.HopGui;
 import org.apache.hop.ui.hopgui.file.pipeline.HopGuiPipelineGraph;
 import org.apache.hop.workflow.WorkflowMeta;
+import org.jspecify.annotations.NonNull;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 
+@Getter
+@Setter
 public class HopGuiPipelineClipboardDelegate {
   private static final Class<?> PKG = HopGui.class;
 
@@ -51,18 +57,17 @@ public class HopGuiPipelineClipboardDelegate {
 
   private HopGui hopGui;
   private HopGuiPipelineGraph pipelineGraph;
-  private ILogChannel log;
 
   public HopGuiPipelineClipboardDelegate(HopGui hopGui, HopGuiPipelineGraph 
pipelineGraph) {
     this.hopGui = hopGui;
     this.pipelineGraph = pipelineGraph;
-    this.log = hopGui.getLog();
+    ILogChannel log = hopGui.getLog();
   }
 
   public void toClipboard(String clipText) {
     try {
       GuiResource.getInstance().toClipboard(clipText);
-    } catch (Throwable e) {
+    } catch (Exception e) {
       new ErrorDialog(
           hopGui.getActiveShell(),
           BaseMessages.getString(PKG, 
"HopGui.Dialog.ExceptionCopyToClipboard.Title"),
@@ -74,7 +79,7 @@ public class HopGuiPipelineClipboardDelegate {
   public String fromClipboard() {
     try {
       return GuiResource.getInstance().fromClipboard();
-    } catch (Throwable e) {
+    } catch (Exception e) {
       new ErrorDialog(
           hopGui.getActiveShell(),
           BaseMessages.getString(PKG, 
"HopGui.Dialog.ExceptionPasteFromClipboard.Title"),
@@ -85,96 +90,45 @@ public class HopGuiPipelineClipboardDelegate {
   }
 
   public void pasteXml(PipelineMeta pipelineMeta, String clipboardContent, 
Point location) {
-
     try {
       Document doc = XmlHandler.loadXmlString(clipboardContent);
       Node pipelineNode = XmlHandler.getSubNode(doc, 
XML_TAG_PIPELINE_TRANSFORMS);
-      // De-select all, re-select pasted transforms...
+      // Unselect all, reselect pasted transforms...
       pipelineMeta.unselectAll();
 
       Node transformsNode = XmlHandler.getSubNode(pipelineNode, 
XML_TAG_TRANSFORMS);
-      int nr = XmlHandler.countNodes(transformsNode, TransformMeta.XML_TAG);
-      if (log.isDebug()) {
-        // "I found "+nr+" transforms to paste on location: "
-        log.logDebug(BaseMessages.getString(PKG, "HopGui.Log.FoundTransforms", 
"" + nr) + location);
-      }
-      TransformMeta[] transforms = new TransformMeta[nr];
-      ArrayList<String> transformOldNames = new ArrayList<>(nr);
+      List<Node> transformNodes = XmlHandler.getNodes(transformsNode, 
TransformMeta.XML_TAG);
+      ArrayList<String> transformOldNames = new ArrayList<>();
 
       Point min = new Point(99999999, 99999999);
 
-      // Load the transforms...
-      for (int i = 0; i < nr; i++) {
-        Node transformNode = XmlHandler.getSubNodeByNr(transformsNode, 
TransformMeta.XML_TAG, i);
-        transforms[i] = new TransformMeta(transformNode, 
hopGui.getMetadataProvider());
-
-        if (location != null) {
-          Point p = transforms[i].getLocation();
-
-          if (min.x > p.x) {
-            min.x = p.x;
-          }
-          if (min.y > p.y) {
-            min.y = p.y;
-          }
-        }
-      }
-
-      // Load the notes...
-      Node notesNode = XmlHandler.getSubNode(pipelineNode, 
WorkflowMeta.XML_TAG_NOTEPADS);
-      nr = XmlHandler.countNodes(notesNode, NotePadMeta.XML_TAG);
-      if (log.isDebug()) {
-        log.logDebug(BaseMessages.getString(PKG, "HopGui.Log.FoundNotepads", 
"" + nr));
-      }
-      NotePadMeta[] notes = new NotePadMeta[nr];
-      for (int i = 0; i < nr; i++) {
-        Node noteNode = XmlHandler.getSubNodeByNr(notesNode, 
NotePadMeta.XML_TAG, i);
-        notes[i] = new NotePadMeta(noteNode);
-
-        if (location != null) {
-          Point p = notes[i].getLocation();
-
-          if (min.x > p.x) {
-            min.x = p.x;
-          }
-          if (min.y > p.y) {
-            min.y = p.y;
-          }
-        }
-      }
-
-      // Load the hops...
-      Node hopsNode = XmlHandler.getSubNode(pipelineNode, 
PipelineMeta.XML_TAG_ORDER);
-      nr = XmlHandler.countNodes(hopsNode, BaseHopMeta.XML_HOP_TAG);
-      if (log.isDebug()) {
-        // "I found "+nr+" hops to paste."
-        log.logDebug(BaseMessages.getString(PKG, "HopGui.Log.FoundHops", "" + 
nr));
-      }
-      PipelineHopMeta[] hops = new PipelineHopMeta[nr];
-
-      for (int i = 0; i < nr; i++) {
-        Node hopNode = XmlHandler.getSubNodeByNr(hopsNode, 
BaseHopMeta.XML_HOP_TAG, i);
-        hops[i] = new PipelineHopMeta(hopNode, Arrays.asList(transforms));
-      }
+      List<TransformMeta> transforms = deSerializeTransforms(location, 
transformNodes, min);
+      List<NotePadMeta> notes = deSerializeNotes(location, pipelineNode, min);
+      List<PipelineHopMeta> hops = deSerializePipelineHops(pipelineNode, 
transforms);
 
       // This is the offset:
-      Point offset = new Point(location.x - min.x, location.y - min.y);
+      Point offset;
+      if (location != null) {
+        offset = new Point(location.x - min.x, location.y - min.y);
+      } else {
+        offset = new Point(-min.x, -min.y);
+      }
 
       // Undo/redo object positions...
-      int[] position = new int[transforms.length];
+      int[] position = new int[transforms.size()];
 
-      for (int i = 0; i < transforms.length; i++) {
-        Point p = transforms[i].getLocation();
-        String name = transforms[i].getName();
+      for (int i = 0; i < transforms.size(); i++) {
+        Point p = transforms.get(i).getLocation();
+        String name = transforms.get(i).getName();
 
-        PropsUi.setLocation(transforms[i], p.x + offset.x, p.y + offset.y);
+        PropsUi.setLocation(transforms.get(i), p.x + offset.x, p.y + offset.y);
 
         // Check the name, find alternative...
         transformOldNames.add(name);
-        transforms[i].setName(pipelineMeta.getAlternativeTransformName(name));
-        pipelineMeta.addTransform(transforms[i]);
-        position[i] = pipelineMeta.indexOfTransform(transforms[i]);
-        transforms[i].setSelected(true);
+        
transforms.get(i).setName(pipelineMeta.getAlternativeTransformName(name));
+        pipelineMeta.addTransform(transforms.get(i));
+        position[i] = pipelineMeta.indexOfTransform(transforms.get(i));
+        transforms.get(i).setSelected(true);
       }
 
       // Add the hops too...
@@ -216,35 +170,35 @@ public class HopGuiPipelineClipboardDelegate {
               
transformOldNames.indexOf(transformErrorMeta.getTargetTransform().getName());
         }
         TransformMeta sourceTransform =
-            pipelineMeta.findTransform(transforms[srcTransformPos].getName());
+            
pipelineMeta.findTransform(transforms.get(srcTransformPos).getName());
         if (sourceTransform != null) {
           sourceTransform.setTransformErrorMeta(transformErrorMeta);
         }
-        sourceTransform.setTransformErrorMeta(null);
         if (tgtTransformPos >= 0) {
-          sourceTransform.setTransformErrorMeta(transformErrorMeta);
           TransformMeta targetTransform =
-              
pipelineMeta.findTransform(transforms[tgtTransformPos].getName());
+              
pipelineMeta.findTransform(transforms.get(tgtTransformPos).getName());
           transformErrorMeta.setSourceTransform(sourceTransform);
           transformErrorMeta.setTargetTransform(targetTransform);
         }
       }
 
       // Save undo information too...
-      hopGui.undoDelegate.addUndoNew(pipelineMeta, transforms, position, 
false);
+      hopGui.undoDelegate.addUndoNew(
+          pipelineMeta, transforms.toArray(new TransformMeta[0]), position, 
false);
 
-      int[] hopPos = new int[hops.length];
-      for (int i = 0; i < hops.length; i++) {
-        hopPos[i] = pipelineMeta.indexOfPipelineHop(hops[i]);
+      int[] hopPos = new int[hops.size()];
+      for (int i = 0; i < hops.size(); i++) {
+        hopPos[i] = pipelineMeta.indexOfPipelineHop(hops.get(i));
       }
-      hopGui.undoDelegate.addUndoNew(pipelineMeta, hops, hopPos, true);
+      hopGui.undoDelegate.addUndoNew(
+          pipelineMeta, hops.toArray(new PipelineHopMeta[0]), hopPos, true);
 
-      int[] notePos = new int[notes.length];
-      for (int i = 0; i < notes.length; i++) {
-        notePos[i] = pipelineMeta.indexOfNote(notes[i]);
+      int[] notePos = new int[notes.size()];
+      for (int i = 0; i < notes.size(); i++) {
+        notePos[i] = pipelineMeta.indexOfNote(notes.get(i));
       }
-      hopGui.undoDelegate.addUndoNew(pipelineMeta, notes, notePos, true);
-
+      hopGui.undoDelegate.addUndoNew(
+          pipelineMeta, notes.toArray(new NotePadMeta[0]), notePos, true);
     } catch (HopException e) {
       // See if this was different (non-XML) content
       //
@@ -253,6 +207,61 @@ public class HopGuiPipelineClipboardDelegate {
     pipelineGraph.redraw();
   }
 
+  private static @NonNull List<PipelineHopMeta> deSerializePipelineHops(
+      Node pipelineNode, List<TransformMeta> transforms) throws 
HopXmlException {
+    Node hopsNode = XmlHandler.getSubNode(pipelineNode, 
PipelineMeta.XML_TAG_ORDER);
+    List<Node> hopNodes = XmlHandler.getNodes(hopsNode, 
BaseHopMeta.XML_HOP_TAG);
+    List<PipelineHopMeta> hops = new ArrayList<>();
+
+    for (Node hopNode : hopNodes) {
+      hops.add(new PipelineHopMeta(hopNode, transforms));
+    }
+    return hops;
+  }
+
+  private static @NonNull List<NotePadMeta> deSerializeNotes(
+      Point location, Node pipelineNode, Point min) throws HopXmlException {
+    Node notesNode = XmlHandler.getSubNode(pipelineNode, 
WorkflowMeta.XML_TAG_NOTEPADS);
+    List<Node> noteNodes = XmlHandler.getNodes(notesNode, NotePadMeta.XML_TAG);
+
+    List<NotePadMeta> notes = new ArrayList<>();
+    for (Node noteNode : noteNodes) {
+      NotePadMeta note = new NotePadMeta(noteNode);
+      notes.add(note);
+      if (location != null) {
+        Point p = note.getLocation();
+        if (min.x > p.x) {
+          min.x = p.x;
+        }
+        if (min.y > p.y) {
+          min.y = p.y;
+        }
+      }
+    }
+    return notes;
+  }
+
+  private List<TransformMeta> deSerializeTransforms(
+      Point location, List<Node> transformNodes, Point min)
+      throws HopXmlException, HopPluginLoaderException {
+    List<TransformMeta> transforms = new ArrayList<>();
+    for (Node transformNode : transformNodes) {
+      TransformMeta transform = new TransformMeta(transformNode, 
hopGui.getMetadataProvider());
+      transforms.add(transform);
+
+      if (location != null) {
+        Point p = transform.getLocation();
+        if (min.x > p.x) {
+          min.x = p.x;
+        }
+        if (min.y > p.y) {
+          min.y = p.y;
+        }
+      }
+    }
+    return transforms;
+  }
+
   private void pasteNoXmlContent(
       PipelineMeta pipelineMeta, String clipboardContent, Point location) {
     try {
@@ -298,46 +307,10 @@ public class HopGuiPipelineClipboardDelegate {
     StringBuilder xml = new 
StringBuilder(5000).append(XmlHandler.getXmlHeader());
     try {
       
xml.append(XmlHandler.openTag(XML_TAG_PIPELINE_TRANSFORMS)).append(Const.CR);
-
-      xml.append(XmlHandler.openTag(XML_TAG_TRANSFORMS)).append(Const.CR);
-      for (TransformMeta transform : transforms) {
-        xml.append(transform.getXml());
-      }
-      xml.append(XmlHandler.closeTag(XML_TAG_TRANSFORMS)).append(Const.CR);
-
-      // Also check for the hops in between the selected transforms...
-      
xml.append(XmlHandler.openTag(PipelineMeta.XML_TAG_ORDER)).append(Const.CR);
-      for (TransformMeta transform1 : transforms) {
-        for (TransformMeta transform2 : transforms) {
-          if (transform1 != transform2) {
-            PipelineHopMeta hop = pipelineMeta.findPipelineHop(transform1, 
transform2, true);
-            if (hop != null) {
-              // Ok, we found one...
-              xml.append(hop.getXml()).append(Const.CR);
-            }
-          }
-        }
-      }
-      
xml.append(XmlHandler.closeTag(PipelineMeta.XML_TAG_ORDER)).append(Const.CR);
-
-      
xml.append(XmlHandler.openTag(PipelineMeta.XML_TAG_NOTEPADS)).append(Const.CR);
-      if (notes != null) {
-        for (NotePadMeta note : notes) {
-          xml.append(note.getXml());
-        }
-      }
-      
xml.append(XmlHandler.closeTag(PipelineMeta.XML_TAG_NOTEPADS)).append(Const.CR);
-
-      
xml.append(XmlHandler.openTag(PipelineMeta.XML_TAG_TRANSFORM_ERROR_HANDLING))
-          .append(Const.CR);
-      for (TransformMeta transform : transforms) {
-        if (transform.getTransformErrorMeta() != null) {
-          
xml.append(transform.getTransformErrorMeta().getXml()).append(Const.CR);
-        }
-      }
-      
xml.append(XmlHandler.closeTag(PipelineMeta.XML_TAG_TRANSFORM_ERROR_HANDLING))
-          .append(Const.CR);
-
+      serializeTransformsToXml(transforms, xml);
+      serializePipelineHopsToXml(pipelineMeta, transforms, xml);
+      serializeNotesToXml(notes, xml);
+      serializeTransformErrorHandlingToXml(transforms, xml);
       
xml.append(XmlHandler.closeTag(XML_TAG_PIPELINE_TRANSFORMS)).append(Const.CR);
 
       toClipboard(xml.toString());
@@ -346,35 +319,51 @@ public class HopGuiPipelineClipboardDelegate {
     }
   }
 
-  /**
-   * Gets hopGui
-   *
-   * @return value of hopGui
-   */
-  public HopGui getHopGui() {
-    return hopGui;
+  private static void serializeTransformErrorHandlingToXml(
+      List<TransformMeta> transforms, StringBuilder xml) throws HopException {
+    
xml.append(XmlHandler.openTag(PipelineMeta.XML_TAG_TRANSFORM_ERROR_HANDLING)).append(Const.CR);
+    for (TransformMeta transform : transforms) {
+      if (transform.getTransformErrorMeta() != null) {
+        
xml.append(transform.getTransformErrorMeta().getXml()).append(Const.CR);
+      }
+    }
+    
xml.append(XmlHandler.closeTag(PipelineMeta.XML_TAG_TRANSFORM_ERROR_HANDLING)).append(Const.CR);
   }
 
-  /**
-   * @param hopGui The hopGui to set
-   */
-  public void setHopGui(HopGui hopGui) {
-    this.hopGui = hopGui;
+  private static void serializeNotesToXml(List<NotePadMeta> notes, 
StringBuilder xml) {
+    
xml.append(XmlHandler.openTag(PipelineMeta.XML_TAG_NOTEPADS)).append(Const.CR);
+    if (notes != null) {
+      for (NotePadMeta note : notes) {
+        xml.append(note.getXml());
+      }
+    }
+    
xml.append(XmlHandler.closeTag(PipelineMeta.XML_TAG_NOTEPADS)).append(Const.CR);
   }
 
-  /**
-   * Gets pipelineGraph
-   *
-   * @return value of pipelineGraph
-   */
-  public HopGuiPipelineGraph getPipelineGraph() {
-    return pipelineGraph;
+  private static void serializePipelineHopsToXml(
+      PipelineMeta pipelineMeta, List<TransformMeta> transforms, StringBuilder 
xml)
+      throws HopException {
+    
xml.append(XmlHandler.openTag(PipelineMeta.XML_TAG_ORDER)).append(Const.CR);
+    for (TransformMeta transform1 : transforms) {
+      for (TransformMeta transform2 : transforms) {
+        if (transform1 != transform2) {
+          PipelineHopMeta hop = pipelineMeta.findPipelineHop(transform1, 
transform2, true);
+          if (hop != null) {
+            // Ok, we found one...
+            xml.append(hop.getXml()).append(Const.CR);
+          }
+        }
+      }
+    }
+    
xml.append(XmlHandler.closeTag(PipelineMeta.XML_TAG_ORDER)).append(Const.CR);
   }
 
-  /**
-   * @param pipelineGraph The pipelineGraph to set
-   */
-  public void setPipelineGraph(HopGuiPipelineGraph pipelineGraph) {
-    this.pipelineGraph = pipelineGraph;
+  private static void serializeTransformsToXml(List<TransformMeta> transforms, 
StringBuilder xml)
+      throws HopException {
+    xml.append(XmlHandler.openTag(XML_TAG_TRANSFORMS)).append(Const.CR);
+    for (TransformMeta transform : transforms) {
+      xml.append(transform.getXml());
+    }
+    xml.append(XmlHandler.closeTag(XML_TAG_TRANSFORMS)).append(Const.CR);
   }
 }

Reply via email to