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

hansva 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 bf00f703e0 issues #7354, #7343  (#7359)
bf00f703e0 is described below

commit bf00f703e06c1d8cb873500c22902b12b7319e8b
Author: Matt Casters <[email protected]>
AuthorDate: Mon Jun 29 16:05:19 2026 +0200

    issues #7354, #7343  (#7359)
    
    * issue #7354 : fixing the project enforce in home checkbox.
    
    * issue #7343 : improve stream consistency checks
---
 .../org/apache/hop/projects/project/Project.java   |   3 +
 .../apache/hop/projects/project/ProjectTest.java   |  57 ++++
 .../hopgui/file/pipeline/HopGuiPipelineGraph.java  |  41 ++-
 .../delegates/HopGuiPipelineHopDelegate.java       | 290 ++++++++++++++++++++-
 .../ui/hopgui/messages/messages_en_US.properties   |  24 +-
 5 files changed, 406 insertions(+), 9 deletions(-)

diff --git 
a/plugins/misc/projects/src/main/java/org/apache/hop/projects/project/Project.java
 
b/plugins/misc/projects/src/main/java/org/apache/hop/projects/project/Project.java
index 82a7729e54..7c76fa8872 100644
--- 
a/plugins/misc/projects/src/main/java/org/apache/hop/projects/project/Project.java
+++ 
b/plugins/misc/projects/src/main/java/org/apache/hop/projects/project/Project.java
@@ -81,7 +81,10 @@ public class Project extends ConfigFile implements 
IConfigFile {
   private String metadataBaseFolder;
   private String unitTestsBasePath;
   private String dataSetsCsvFolder;
+
+  @JsonInclude(JsonInclude.Include.ALWAYS)
   private boolean enforcingExecutionInHome;
+
   private String parentProjectName;
   @JsonIgnore private MultiMetadataProvider metadataProvider;
   @JsonIgnore private List<Path> pipelinePaths;
diff --git 
a/plugins/misc/projects/src/test/java/org/apache/hop/projects/project/ProjectTest.java
 
b/plugins/misc/projects/src/test/java/org/apache/hop/projects/project/ProjectTest.java
new file mode 100644
index 0000000000..4cb65c6110
--- /dev/null
+++ 
b/plugins/misc/projects/src/test/java/org/apache/hop/projects/project/ProjectTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.projects.project;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.File;
+import java.nio.file.Files;
+import org.junit.jupiter.api.Test;
+
+public class ProjectTest {
+
+  @Test
+  public void testEnforcingExecutionInHomeSerialization() throws Exception {
+    File tempFile = Files.createTempFile("project-config-test", 
".json").toFile();
+    tempFile.deleteOnExit();
+
+    try {
+      Project project = new Project(tempFile.getAbsolutePath());
+      project.setEnforcingExecutionInHome(false);
+      project.saveToFile();
+
+      // Read back
+      Project readProject = new Project(tempFile.getAbsolutePath());
+      readProject.readFromFile();
+
+      assertFalse(readProject.isEnforcingExecutionInHome());
+
+      // Test true
+      project.setEnforcingExecutionInHome(true);
+      project.saveToFile();
+
+      readProject = new Project(tempFile.getAbsolutePath());
+      readProject.readFromFile();
+
+      assertTrue(readProject.isEnforcingExecutionInHome());
+    } finally {
+      tempFile.delete();
+    }
+  }
+}
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
index c20b804a88..42a074d570 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopGuiPipelineGraph.java
@@ -83,6 +83,7 @@ import org.apache.hop.core.plugins.IPlugin;
 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.row.RowBuffer;
 import org.apache.hop.core.svg.SvgFile;
 import org.apache.hop.core.util.ExecutorUtil;
@@ -345,7 +346,7 @@ public class HopGuiPipelineGraph extends HopGuiAbstractGraph
 
   private PipelineHopMeta lastHopSplit;
 
-  private org.apache.hop.core.gui.Rectangle selectionRegion;
+  private Rectangle selectionRegion;
 
   @Getter @Setter private List<ICheckResult> remarks;
 
@@ -954,7 +955,7 @@ public class HopGuiPipelineGraph extends HopGuiAbstractGraph
       //
       canvas.setData("mode", "select");
       if (!control && event.button == 1) {
-        selectionRegion = new org.apache.hop.core.gui.Rectangle(real.x, 
real.y, 0, 0);
+        selectionRegion = new Rectangle(real.x, real.y, 0, 0);
         // Change cursor when selecting a region
         setCursor(getDisplay().getSystemCursor(SWT.CURSOR_CROSS));
       }
@@ -2406,7 +2407,7 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
       toolBarWidgets = new GuiToolbarWidgets();
       toolBarWidgets.registerGuiPluginObject(this);
       toolBarWidgets.createToolbarWidgets(toolBarContainer, 
GUI_PLUGIN_TOOLBAR_PARENT_ID);
-      if 
(org.apache.hop.ui.hopgui.PaletteEngineFilter.shouldShowPipelineComboFilter()) {
+      if (PaletteEngineFilter.shouldShowPipelineComboFilter()) {
         setDesignEngineComboFromConfig();
       } else {
         disposeDesignEngineToolbarItem();
@@ -2613,6 +2614,40 @@ public class HopGuiPipelineGraph extends 
HopGuiAbstractGraph
     HelpUtils.openHelp(getShell(), plugin);
   }
 
+  @GuiContextAction(
+      id = "pipeline-graph-transform-11000-layout-check",
+      parentId = HopGuiPipelineTransformContext.CONTEXT_ID,
+      type = GuiActionType.Info,
+      name = "Layout Check",
+      tooltip = "Check that the row layouts of all previous transforms are 
identical",
+      image = "ui/images/check.svg",
+      category = 
"i18n::HopGuiPipelineGraph.ContextualAction.Category.Routing.Text",
+      categoryOrder = "1")
+  public void layoutCheck(HopGuiPipelineTransformContext context) {
+    pipelineHopDelegate.checkLayoutOfTransformInput(
+        context.getTransformMeta(), context.getPipelineMeta());
+  }
+
+  public boolean isLayoutIdentical(IRowMeta rm1, IRowMeta rm2) {
+    if (rm1 == null || rm2 == null) {
+      return rm1 == rm2;
+    }
+    if (rm1.size() != rm2.size()) {
+      return false;
+    }
+    for (int i = 0; i < rm1.size(); i++) {
+      IValueMeta vm1 = rm1.getValueMeta(i);
+      IValueMeta vm2 = rm2.getValueMeta(i);
+      if (!vm1.getName().equalsIgnoreCase(vm2.getName())) {
+        return false;
+      }
+      if (vm1.getType() != vm2.getType()) {
+        return false;
+      }
+    }
+    return true;
+  }
+
   @GuiContextAction(
       id = "pipeline-graph-transform-10100-transform-detach",
       parentId = HopGuiPipelineTransformContext.CONTEXT_ID,
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineHopDelegate.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineHopDelegate.java
index ee6accf014..1a59bac640 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineHopDelegate.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/delegates/HopGuiPipelineHopDelegate.java
@@ -19,16 +19,25 @@ package org.apache.hop.ui.hopgui.file.pipeline.delegates;
 
 import java.util.ArrayList;
 import java.util.List;
+import org.apache.hop.core.Const;
+import org.apache.hop.core.exception.HopException;
 import org.apache.hop.core.exception.HopRowException;
+import org.apache.hop.core.plugins.IPlugin;
 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.i18n.BaseMessages;
 import org.apache.hop.pipeline.PipelineHopMeta;
 import org.apache.hop.pipeline.PipelineMeta;
 import org.apache.hop.pipeline.transform.IRowDistribution;
+import org.apache.hop.pipeline.transform.ITransformMeta;
 import org.apache.hop.pipeline.transform.RowDistributionPluginType;
 import org.apache.hop.pipeline.transform.TransformErrorMeta;
 import org.apache.hop.pipeline.transform.TransformMeta;
 import org.apache.hop.ui.core.PropsUi;
+import org.apache.hop.ui.core.dialog.EnterTextDialog;
 import org.apache.hop.ui.core.dialog.ErrorDialog;
 import org.apache.hop.ui.core.dialog.MessageBox;
 import org.apache.hop.ui.core.dialog.MessageDialogWithToggle;
@@ -36,6 +45,7 @@ import org.apache.hop.ui.hopgui.HopGui;
 import org.apache.hop.ui.hopgui.file.pipeline.HopGuiPipelineGraph;
 import org.apache.hop.ui.pipeline.dialog.PipelineHopDialog;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Shell;
 
 public class HopGuiPipelineHopDelegate {
 
@@ -128,11 +138,7 @@ public class HopGuiPipelineHopDelegate {
         }
       } catch (HopRowException re) {
         // Show warning about mixing rows with conflicting layouts...
-        new ErrorDialog(
-            hopGui.getActiveShell(),
-            BaseMessages.getString(PKG, 
"PipelineGraph.Dialog.HopCausesRowMixing.Title"),
-            BaseMessages.getString(PKG, 
"PipelineGraph.Dialog.HopCausesRowMixing.Message"),
-            re);
+        checkLayoutOfTransformInput(newHop.getToTransform(), pipelineMeta);
       }
 
       // Verify copy distribution only if the new hop are not for error 
handling
@@ -316,4 +322,278 @@ public class HopGuiPipelineHopDelegate {
     }
     pipelineGraph.updateGui();
   }
+
+  public void checkLayoutOfTransformInput(
+      TransformMeta currentTransformMeta, PipelineMeta pipelineMeta) {
+    Shell shell = hopGui.getShell();
+    IVariables variables = hopGui.getVariables();
+    List<TransformMeta> prevTransforms = 
pipelineMeta.findPreviousTransforms(currentTransformMeta);
+
+    if (prevTransforms.isEmpty()) {
+      MessageBox box = new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
+      box.setText(BaseMessages.getString(PKG, "HopGui.LayoutCheck.Title"));
+      box.setMessage(BaseMessages.getString(PKG, 
"HopGui.LayoutCheck.NoInputs"));
+      box.open();
+      return;
+    } else if (prevTransforms.size() == 1) {
+      MessageBox box = new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
+      box.setText(BaseMessages.getString(PKG, "HopGui.LayoutCheck.Title"));
+      box.setMessage(
+          BaseMessages.getString(
+              PKG, "HopGui.LayoutCheck.OneInput", 
prevTransforms.get(0).getName()));
+      box.open();
+      return;
+    }
+
+    List<IRowMeta> rowMetas = new ArrayList<>();
+    boolean errorOccurred = false;
+    for (TransformMeta prev : prevTransforms) {
+      try {
+        IRowMeta rowMeta = pipelineMeta.getTransformFields(variables, prev);
+        rowMetas.add(rowMeta);
+      } catch (HopException e) {
+        new ErrorDialog(
+            shell,
+            BaseMessages.getString(PKG, "HopGui.LayoutCheck.Error"),
+            BaseMessages.getString(PKG, 
"HopGui.LayoutCheck.ErrorGettingRowLayout", prev.getName()),
+            e);
+        errorOccurred = true;
+        break;
+      }
+    }
+    if (errorOccurred) {
+      return;
+    }
+
+    boolean allIdentical = true;
+    IRowMeta firstMeta = rowMetas.get(0);
+    for (int i = 1; i < rowMetas.size(); i++) {
+      if (!pipelineGraph.isLayoutIdentical(firstMeta, rowMetas.get(i))) {
+        allIdentical = false;
+        break;
+      }
+    }
+
+    if (allIdentical) {
+      MessageBox box = new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
+      box.setText(BaseMessages.getString(PKG, "HopGui.LayoutCheck.Title"));
+      box.setMessage(BaseMessages.getString(PKG, 
"HopGui.LayoutCheck.Identical"));
+      box.open();
+    } else {
+      StringBuilder diffText = new StringBuilder();
+      diffText
+          .append(BaseMessages.getString(PKG, 
"HopGui.LayoutCheck.DifferentInputs"))
+          .append(Const.CR)
+          .append(Const.CR);
+
+      for (int i = 0; i < prevTransforms.size(); i++) {
+        TransformMeta prev = prevTransforms.get(i);
+        IRowMeta rowMeta = rowMetas.get(i);
+        diffText
+            .append(
+                BaseMessages.getString(
+                    PKG, "HopGui.LayoutCheck.InputFromTransform", 
prev.getName()))
+            .append(Const.CR);
+        if (rowMeta == null || rowMeta.isEmpty()) {
+          diffText
+              .append(BaseMessages.getString(PKG, 
"HopGui.LayoutCheck.NoFields"))
+              .append(Const.CR);
+        } else {
+          for (int j = 0; j < rowMeta.size(); j++) {
+            IValueMeta vm = rowMeta.getValueMeta(j);
+            diffText
+                .append(
+                    BaseMessages.getString(
+                        PKG,
+                        "HopGui.LayoutCheck.FieldLine",
+                        String.format("%3d", j + 1),
+                        vm.getName(),
+                        vm.getTypeDesc()))
+                .append(Const.CR);
+          }
+        }
+        diffText.append("\n");
+      }
+
+      diffText
+          .append(BaseMessages.getString(PKG, 
"HopGui.LayoutCheck.DifferencesList"))
+          .append(Const.CR);
+      String firstTransformName = prevTransforms.get(0).getName();
+      for (int i = 1; i < rowMetas.size(); i++) {
+        IRowMeta currentMeta = rowMetas.get(i);
+        String currentTransformName = prevTransforms.get(i).getName();
+
+        if (firstMeta == null || currentMeta == null) {
+          diffText
+              .append(
+                  BaseMessages.getString(
+                      PKG,
+                      "HopGui.LayoutCheck.LayoutIsNull",
+                      firstTransformName,
+                      currentTransformName))
+              .append(Const.CR);
+          continue;
+        }
+
+        if (firstMeta.size() != currentMeta.size()) {
+          diffText
+              .append(
+                  BaseMessages.getString(
+                      PKG,
+                      "HopGui.LayoutCheck.FieldCountMismatch",
+                      firstTransformName,
+                      Integer.toString(firstMeta.size()),
+                      currentTransformName,
+                      Integer.toString(currentMeta.size())))
+              .append(Const.CR);
+        }
+
+        int minSize = Math.min(firstMeta.size(), currentMeta.size());
+        for (int j = 0; j < minSize; j++) {
+          IValueMeta vm1 = firstMeta.getValueMeta(j);
+          IValueMeta vm2 = currentMeta.getValueMeta(j);
+          if (!vm1.getName().equalsIgnoreCase(vm2.getName())) {
+            diffText
+                .append(
+                    BaseMessages.getString(
+                        PKG,
+                        "HopGui.LayoutCheck.NameMismatch",
+                        Integer.toString(j + 1),
+                        firstTransformName,
+                        vm1.getName(),
+                        currentTransformName,
+                        vm2.getName()))
+                .append(Const.CR);
+          } else if (vm1.getType() != vm2.getType()) {
+            diffText
+                .append(
+                    BaseMessages.getString(
+                        PKG,
+                        "HopGui.LayoutCheck.TypeMismatch",
+                        vm1.getName(),
+                        firstTransformName,
+                        vm1.getTypeDesc(),
+                        currentTransformName,
+                        vm2.getTypeDesc()))
+                .append(Const.CR);
+          }
+        }
+
+        if (firstMeta.size() > currentMeta.size()) {
+          for (int j = minSize; j < firstMeta.size(); j++) {
+            diffText
+                .append(
+                    BaseMessages.getString(
+                        PKG,
+                        "HopGui.LayoutCheck.FieldMissing",
+                        firstMeta.getValueMeta(j).getName(),
+                        firstTransformName,
+                        currentTransformName))
+                .append(Const.CR);
+          }
+        } else if (currentMeta.size() > firstMeta.size()) {
+          for (int j = minSize; j < currentMeta.size(); j++) {
+            diffText
+                .append(
+                    BaseMessages.getString(
+                        PKG,
+                        "HopGui.LayoutCheck.FieldMissing",
+                        currentMeta.getValueMeta(j).getName(),
+                        currentTransformName,
+                        firstTransformName))
+                .append(Const.CR);
+          }
+        }
+      }
+
+      EnterTextDialog dialog =
+          new EnterTextDialog(
+              shell,
+              BaseMessages.getString(PKG, 
"HopGui.LayoutCheck.Dialog.MismatchTitle"),
+              BaseMessages.getString(PKG, 
"HopGui.LayoutCheck.Dialog.MismatchMessage"),
+              diffText.toString(),
+              true);
+      dialog.setReadOnly();
+      dialog.open();
+    }
+
+    if ("Dummy".equals(currentTransformMeta.getPluginId())) {
+      MessageBox box = new MessageBox(shell, SWT.ICON_QUESTION | SWT.YES | 
SWT.NO);
+      box.setText(BaseMessages.getString(PKG, 
"HopGui.LayoutCheck.Dialog.ReplaceDummyTitle"));
+      box.setMessage(BaseMessages.getString(PKG, 
"HopGui.LayoutCheck.Dialog.ReplaceDummyMessage"));
+      if (box.open() == SWT.YES) {
+        try {
+          IPlugin plugin =
+              PluginRegistry.getInstance()
+                  .findPluginWithId(TransformPluginType.class, "StreamSchema");
+          if (plugin != null) {
+            ITransformMeta streamSchemaMeta =
+                (ITransformMeta) 
PluginRegistry.getInstance().loadClass(plugin);
+
+            configureSchemaMergeTransform(streamSchemaMeta, prevTransforms);
+            
streamSchemaMeta.searchInfoAndTargetTransforms(pipelineMeta.getTransforms());
+
+            TransformMeta before = (TransformMeta) 
currentTransformMeta.clone();
+
+            currentTransformMeta.setTransform(streamSchemaMeta);
+            currentTransformMeta.setTransformPluginId("StreamSchema");
+            currentTransformMeta.setChanged();
+
+            TransformMeta after = (TransformMeta) currentTransformMeta.clone();
+
+            hopGui.undoDelegate.addUndoChange(
+                pipelineMeta,
+                new TransformMeta[] {before},
+                new TransformMeta[] {after},
+                new int[] 
{pipelineMeta.indexOfTransform(currentTransformMeta)});
+
+            pipelineMeta.setChanged();
+            pipelineGraph.redraw();
+          } else {
+            new ErrorDialog(
+                shell,
+                BaseMessages.getString(PKG, "HopGui.LayoutCheck.Error"),
+                BaseMessages.getString(PKG, 
"HopGui.LayoutCheck.Dialog.StreamSchemaPluginNotFound"),
+                new HopException("Plugin not found"));
+          }
+        } catch (Exception e) {
+          new ErrorDialog(
+              shell,
+              BaseMessages.getString(PKG, "HopGui.LayoutCheck.Error"),
+              BaseMessages.getString(PKG, 
"HopGui.LayoutCheck.Dialog.ReplaceDummyError"),
+              e);
+        }
+      }
+    }
+  }
+
+  private void configureSchemaMergeTransform(
+      ITransformMeta streamSchemaMeta, List<TransformMeta> prevTransforms) {
+    // Configure the Stream Schema Merge transform with the names of the 
previous transforms
+    try {
+      Class<?> metaClass = streamSchemaMeta.getClass();
+      ClassLoader pluginClassLoader = metaClass.getClassLoader();
+      Class<?> transformToMergeClass =
+          Class.forName(
+              
"org.apache.hop.pipeline.transforms.streamschemamerge.StreamSchemaMeta$TransformToMerge",
+              true,
+              pluginClassLoader);
+      java.lang.reflect.Constructor<?> constructor = 
transformToMergeClass.getConstructor();
+      java.lang.reflect.Method setNameMethod =
+          transformToMergeClass.getMethod("setName", String.class);
+
+      List<Object> list = new ArrayList<>();
+      for (TransformMeta prev : prevTransforms) {
+        Object transformToMerge = constructor.newInstance();
+        setNameMethod.invoke(transformToMerge, prev.getName());
+        list.add(transformToMerge);
+      }
+
+      java.lang.reflect.Method setTransformsToMergeMethod =
+          metaClass.getMethod("setTransformsToMerge", List.class);
+      setTransformsToMergeMethod.invoke(streamSchemaMeta, list);
+    } catch (Exception ex) {
+      hopGui.getLog().logError("Error setting transforms to merge via 
reflection", ex);
+    }
+  }
 }
diff --git 
a/ui/src/main/resources/org/apache/hop/ui/hopgui/messages/messages_en_US.properties
 
b/ui/src/main/resources/org/apache/hop/ui/hopgui/messages/messages_en_US.properties
index 8931fa0124..e1a614bfed 100644
--- 
a/ui/src/main/resources/org/apache/hop/ui/hopgui/messages/messages_en_US.properties
+++ 
b/ui/src/main/resources/org/apache/hop/ui/hopgui/messages/messages_en_US.properties
@@ -304,4 +304,26 @@ WorkflowLog.Dialog.SaveJobBeforeRunning.Title=Save workflow
 WorkflowLog.System.ERROR=ERROR
 WorkflowLog.System.EXCEPTION=EXCEPTION
 PipelineLog.Dialog.Pause.Tooltip=Pause the logs
-PipelineLog.Dialog.Resume.Tooltip=Resume the logs
\ No newline at end of file
+PipelineLog.Dialog.Resume.Tooltip=Resume the logs
+HopGui.LayoutCheck.Title=Layout Check
+HopGui.LayoutCheck.NoInputs=This transform has no input transforms. Layouts 
are identical.
+HopGui.LayoutCheck.OneInput=This transform has only one input transform ({0}). 
Layouts are identical.
+HopGui.LayoutCheck.Error=Error
+HopGui.LayoutCheck.ErrorGettingRowLayout=Error getting row layout for 
transform ''{0}''
+HopGui.LayoutCheck.Identical=The row layouts of all previous transforms are 
identical.
+HopGui.LayoutCheck.DifferentInputs=Input row layouts are different!
+HopGui.LayoutCheck.InputFromTransform=Input from transform ''{0}'':
+HopGui.LayoutCheck.NoFields=\  (No fields)
+HopGui.LayoutCheck.FieldLine=\  {0}. {1} ({2})
+HopGui.LayoutCheck.DifferencesList=Differences list:
+HopGui.LayoutCheck.LayoutIsNull=- Layout for ''{0}'' or ''{1}'' is null.
+HopGui.LayoutCheck.FieldCountMismatch=- Field count mismatch: ''{0}'' has {1} 
fields, but ''{2}'' has {3} fields.
+HopGui.LayoutCheck.NameMismatch=- Position {0}: name mismatch (''{1}'' field 
''{2}'' vs ''{3}'' field ''{4}'')
+HopGui.LayoutCheck.TypeMismatch=- Field ''{0}'' type mismatch: ''{1}'' is {2}, 
but ''{3}'' is {4}
+HopGui.LayoutCheck.FieldMissing=- Field ''{0}'' from ''{1}'' is missing in 
''{2}''.
+HopGui.LayoutCheck.Dialog.MismatchTitle=Layout Check - Mismatches
+HopGui.LayoutCheck.Dialog.MismatchMessage=Details of row layout mismatches:
+HopGui.LayoutCheck.Dialog.ReplaceDummyTitle=Replace Transform
+HopGui.LayoutCheck.Dialog.ReplaceDummyMessage=Do you want to replace this 
Dummy transform with a ''Stream Schema Merge'' transform?
+HopGui.LayoutCheck.Dialog.StreamSchemaPluginNotFound=Stream Schema Merge 
plugin not found.
+HopGui.LayoutCheck.Dialog.ReplaceDummyError=Error replacing Dummy transform 
with Stream Schema Merge
\ No newline at end of file

Reply via email to