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 85a7dd2dfd added created and modified hop versions to pipeline and
workflow info. fixes #8039 (#8121)
85a7dd2dfd is described below
commit 85a7dd2dfd300f6f9502e43e0460b726d0ac4ff7
Author: Bart Maertens <[email protected]>
AuthorDate: Thu Aug 27 14:15:19 2026 +0200
added created and modified hop versions to pipeline and workflow info.
fixes #8039 (#8121)
---
core/src/main/java/org/apache/hop/core/Const.java | 27 ++-
.../org/apache/hop/pipeline/AbstractMetaInfo.java | 16 ++
.../java/org/apache/hop/pipeline/PipelineMeta.java | 36 ++++
.../java/org/apache/hop/workflow/WorkflowMeta.java | 36 ++++
.../hop/pipeline/HopVersionSerializationTest.java | 195 +++++++++++++++++++++
.../apache/hop/imports/kettle/KettleImport.java | 20 +++
.../hopgui/file/pipeline/HopGuiPipelineGraph.java | 4 +
.../hopgui/file/pipeline/HopPipelineFileType.java | 5 +
.../hopgui/file/workflow/HopGuiWorkflowGraph.java | 4 +
.../hopgui/file/workflow/HopWorkflowFileType.java | 5 +
.../hop/ui/pipeline/dialog/PipelineDialog.java | 75 ++++++--
.../hop/ui/workflow/dialog/WorkflowDialog.java | 74 ++++++--
.../dialog/messages/messages_en_US.properties | 2 +
.../dialog/messages/messages_en_US.properties | 2 +
14 files changed, 469 insertions(+), 32 deletions(-)
diff --git a/core/src/main/java/org/apache/hop/core/Const.java
b/core/src/main/java/org/apache/hop/core/Const.java
index 882e1b1ea3..497ee0a1bf 100644
--- a/core/src/main/java/org/apache/hop/core/Const.java
+++ b/core/src/main/java/org/apache/hop/core/Const.java
@@ -2165,22 +2165,35 @@ public class Const {
public static String getBaseDocUrl() {
String url = BaseMessages.getString(PKG, "Const.BaseDocUrl");
- // Get the implementation version:
- // Temporary build: 2.4.0-SNAPSHOT (2023-02-13 08.50.52)
- // Release version: 2.4.0
- String version = Const.class.getPackage().getImplementationVersion();
+ String version = getHopVersion();
// Check if implementation version is a SNAPHOT build or if version is not
known.
if (version == null || version.contains("SNAPSHOT")) {
version = "next";
- } else {
- // Only keep until first space to remove the build date
- version = version.split(" ")[0];
}
return url + version + "/";
}
+ /**
+ * Provides the version of Hop this code was built as, without the build
date.
+ *
+ * @return the version, for example "2.20.0" or "2.20.0-SNAPSHOT", or null
when the version can't
+ * be determined. That is the case whenever Hop doesn't run from its
packaged jars, for
+ * example in an IDE or during unit tests.
+ */
+ public static String getHopVersion() {
+ // Get the implementation version:
+ // Temporary build: 2.4.0-SNAPSHOT (2023-02-13 08.50.52)
+ // Release version: 2.4.0
+ String version = Const.class.getPackage().getImplementationVersion();
+ if (version == null) {
+ return null;
+ }
+ // Only keep until first space to remove the build date
+ return version.split(" ")[0];
+ }
+
/**
* Provides the documentation url with the configured base + the given URI.
*
diff --git a/engine/src/main/java/org/apache/hop/pipeline/AbstractMetaInfo.java
b/engine/src/main/java/org/apache/hop/pipeline/AbstractMetaInfo.java
index f51085e697..95c1b8ddaa 100644
--- a/engine/src/main/java/org/apache/hop/pipeline/AbstractMetaInfo.java
+++ b/engine/src/main/java/org/apache/hop/pipeline/AbstractMetaInfo.java
@@ -49,11 +49,27 @@ public abstract class AbstractMetaInfo {
@HopMetadataProperty(key = "modified_date")
protected Date modifiedDate;
+ /**
+ * The version of Hop that created this. Initialized empty rather than to
the running version: the
+ * XML deserializer only assigns a field when its element is present, so a
real version defaulted
+ * here would survive both loading a file written before this element
existed and every undo,
+ * which clears and re-deserializes. That file would then claim to have been
created by whichever
+ * version happened to open it. An empty value makes no such claim and reads
as "unknown".
+ */
+ @HopMetadataProperty(key = "created_hop_version")
+ protected String createdHopVersion;
+
+ /** The version of Hop that last saved this. Initialized empty for the same
reason, see above. */
+ @HopMetadataProperty(key = "modified_hop_version")
+ protected String modifiedHopVersion;
+
protected AbstractMetaInfo() {
this.nameSynchronizedWithFilename = true;
this.createdDate = new Date();
this.modifiedDate = new Date();
this.createdUser = "-";
this.modifiedUser = "-";
+ this.createdHopVersion = "";
+ this.modifiedHopVersion = "";
}
}
diff --git a/engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java
b/engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java
index d50f408754..fbf8da6984 100644
--- a/engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java
+++ b/engine/src/main/java/org/apache/hop/pipeline/PipelineMeta.java
@@ -3574,6 +3574,42 @@ public class PipelineMeta extends AbstractMeta
return info.getModifiedUser();
}
+ /**
+ * Gets the version of Hop that created the pipeline.
+ *
+ * @return the Hop version that created the pipeline, or null when it isn't
known.
+ */
+ public String getCreatedHopVersion() {
+ return info.getCreatedHopVersion();
+ }
+
+ /**
+ * Sets the version of Hop that created the pipeline.
+ *
+ * @param createdHopVersion The Hop version to set.
+ */
+ public void setCreatedHopVersion(String createdHopVersion) {
+ info.setCreatedHopVersion(createdHopVersion);
+ }
+
+ /**
+ * Gets the version of Hop that last saved the pipeline.
+ *
+ * @return the Hop version that last saved the pipeline, or null when it
isn't known.
+ */
+ public String getModifiedHopVersion() {
+ return info.getModifiedHopVersion();
+ }
+
+ /**
+ * Sets the version of Hop that last saved the pipeline.
+ *
+ * @param modifiedHopVersion The Hop version to set.
+ */
+ public void setModifiedHopVersion(String modifiedHopVersion) {
+ info.setModifiedHopVersion(modifiedHopVersion);
+ }
+
@Override
protected INamedParameters getNamedParameters() {
return info.namedParams;
diff --git a/engine/src/main/java/org/apache/hop/workflow/WorkflowMeta.java
b/engine/src/main/java/org/apache/hop/workflow/WorkflowMeta.java
index 854adda4d6..afb4826b24 100644
--- a/engine/src/main/java/org/apache/hop/workflow/WorkflowMeta.java
+++ b/engine/src/main/java/org/apache/hop/workflow/WorkflowMeta.java
@@ -1960,4 +1960,40 @@ public class WorkflowMeta extends AbstractMeta
public void setModifiedUser(String modifiedUser) {
info.setModifiedUser(modifiedUser);
}
+
+ /**
+ * Gets the version of Hop that created the workflow.
+ *
+ * @return the Hop version that created the workflow, or null when it isn't
known.
+ */
+ public String getCreatedHopVersion() {
+ return info.getCreatedHopVersion();
+ }
+
+ /**
+ * Sets the version of Hop that created the workflow.
+ *
+ * @param createdHopVersion The Hop version to set.
+ */
+ public void setCreatedHopVersion(String createdHopVersion) {
+ info.setCreatedHopVersion(createdHopVersion);
+ }
+
+ /**
+ * Gets the version of Hop that last saved the workflow.
+ *
+ * @return the Hop version that last saved the workflow, or null when it
isn't known.
+ */
+ public String getModifiedHopVersion() {
+ return info.getModifiedHopVersion();
+ }
+
+ /**
+ * Sets the version of Hop that last saved the workflow.
+ *
+ * @param modifiedHopVersion The Hop version to set.
+ */
+ public void setModifiedHopVersion(String modifiedHopVersion) {
+ info.setModifiedHopVersion(modifiedHopVersion);
+ }
}
diff --git
a/engine/src/test/java/org/apache/hop/pipeline/HopVersionSerializationTest.java
b/engine/src/test/java/org/apache/hop/pipeline/HopVersionSerializationTest.java
new file mode 100644
index 0000000000..6739830250
--- /dev/null
+++
b/engine/src/test/java/org/apache/hop/pipeline/HopVersionSerializationTest.java
@@ -0,0 +1,195 @@
+/*
+ * 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.pipeline;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.core.variables.Variables;
+import org.apache.hop.junit.rules.RestoreHopEngineEnvironmentExtension;
+import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.metadata.serializer.memory.MemoryMetadataProvider;
+import org.apache.hop.workflow.WorkflowMeta;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+/**
+ * The Hop version that created and last saved a pipeline or workflow is
recorded in the file so a
+ * project can be scanned for files built with an older release.
+ *
+ * <p>Files written before these elements existed must keep them empty rather
than silently claim to
+ * have been created by the running version: the XML deserializer only assigns
a field when its
+ * element is present, so anything defaulted in the constructor would survive
a load and get written
+ * back out on the next save.
+ */
+@ExtendWith(RestoreHopEngineEnvironmentExtension.class)
+class HopVersionSerializationTest {
+
+ private static final String CREATED_VERSION = "2.19.0";
+ private static final String MODIFIED_VERSION = "2.20.0-SNAPSHOT";
+
+ /** A pipeline as written before the created/modified Hop version elements
existed. */
+ private static final String PIPELINE_WITHOUT_VERSIONS =
+ """
+ <pipeline>
+ <info>
+ <name>no-hop-versions</name>
+ <created_user>-</created_user>
+ <created_date>2023/09/16 22:31:19.820</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2023/09/16 22:31:19.820</modified_date>
+ </info>
+ </pipeline>
+ """;
+
+ /** A workflow as written before the created/modified Hop version elements
existed. */
+ private static final String WORKFLOW_WITHOUT_VERSIONS =
+ """
+ <workflow>
+ <name>no-hop-versions</name>
+ <created_user>-</created_user>
+ <created_date>2023/09/16 22:31:19.820</created_date>
+ <modified_user>-</modified_user>
+ <modified_date>2023/09/16 22:31:19.820</modified_date>
+ </workflow>
+ """;
+
+ /** A pipeline where the created version was backfilled by hand, without a
modified version. */
+ private static final String PIPELINE_WITH_BACKFILLED_VERSION =
+ """
+ <pipeline>
+ <info>
+ <name>backfilled</name>
+ <created_hop_version>1.2.0</created_hop_version>
+ </info>
+ </pipeline>
+ """;
+
+ /** A workflow where the created version was backfilled by hand, without a
modified version. */
+ private static final String WORKFLOW_WITH_BACKFILLED_VERSION =
+ """
+ <workflow>
+ <name>backfilled</name>
+ <created_hop_version>1.2.0</created_hop_version>
+ </workflow>
+ """;
+
+ private final IVariables variables = new Variables();
+ private final IHopMetadataProvider metadataProvider = new
MemoryMetadataProvider();
+
+ private PipelineMeta loadPipeline(String xml) throws Exception {
+ return new PipelineMeta(
+ new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)),
+ metadataProvider,
+ variables);
+ }
+
+ private WorkflowMeta loadWorkflow(String xml) throws Exception {
+ return new WorkflowMeta(
+ new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)),
+ metadataProvider,
+ variables);
+ }
+
+ @Test
+ void pipelineKeepsHopVersionsAcrossSaveAndLoad() throws Exception {
+ PipelineMeta pipelineMeta = new PipelineMeta();
+ pipelineMeta.setName("with-hop-versions");
+ pipelineMeta.setCreatedHopVersion(CREATED_VERSION);
+ pipelineMeta.setModifiedHopVersion(MODIFIED_VERSION);
+
+ String xml = pipelineMeta.getXml(variables);
+ assertTrue(xml.contains("<created_hop_version>" + CREATED_VERSION +
"</created_hop_version>"));
+ assertTrue(
+ xml.contains("<modified_hop_version>" + MODIFIED_VERSION +
"</modified_hop_version>"));
+
+ PipelineMeta loaded = loadPipeline(xml);
+ assertEquals(CREATED_VERSION, loaded.getCreatedHopVersion());
+ assertEquals(MODIFIED_VERSION, loaded.getModifiedHopVersion());
+ }
+
+ @Test
+ void workflowKeepsHopVersionsAcrossSaveAndLoad() throws Exception {
+ WorkflowMeta workflowMeta = new WorkflowMeta();
+ workflowMeta.setName("with-hop-versions");
+ workflowMeta.setCreatedHopVersion(CREATED_VERSION);
+ workflowMeta.setModifiedHopVersion(MODIFIED_VERSION);
+
+ String xml = workflowMeta.getXml(variables);
+ assertTrue(xml.contains("<created_hop_version>" + CREATED_VERSION +
"</created_hop_version>"));
+ assertTrue(
+ xml.contains("<modified_hop_version>" + MODIFIED_VERSION +
"</modified_hop_version>"));
+
+ WorkflowMeta loaded = loadWorkflow(xml);
+ assertEquals(CREATED_VERSION, loaded.getCreatedHopVersion());
+ assertEquals(MODIFIED_VERSION, loaded.getModifiedHopVersion());
+ }
+
+ @Test
+ void pipelineWithoutHopVersionsDoesNotClaimTheRunningVersion() throws
Exception {
+ PipelineMeta loaded = loadPipeline(PIPELINE_WITHOUT_VERSIONS);
+
+ assertEquals("", loaded.getCreatedHopVersion());
+ assertEquals("", loaded.getModifiedHopVersion());
+
+ // Both elements are written on every save, empty meaning "we don't know".
+ String xml = loaded.getXml(variables);
+ assertTrue(xml.contains("<created_hop_version/>"));
+ assertTrue(xml.contains("<modified_hop_version/>"));
+ }
+
+ @Test
+ void workflowWithoutHopVersionsDoesNotClaimTheRunningVersion() throws
Exception {
+ WorkflowMeta loaded = loadWorkflow(WORKFLOW_WITHOUT_VERSIONS);
+
+ assertEquals("", loaded.getCreatedHopVersion());
+ assertEquals("", loaded.getModifiedHopVersion());
+
+ String xml = loaded.getXml(variables);
+ assertTrue(xml.contains("<created_hop_version/>"));
+ assertTrue(xml.contains("<modified_hop_version/>"));
+ }
+
+ @Test
+ void pipelineKeepsAManuallyBackfilledCreatedHopVersion() throws Exception {
+ PipelineMeta loaded = loadPipeline(PIPELINE_WITH_BACKFILLED_VERSION);
+
+ // Whatever is in the file is kept verbatim, nothing overwrites or
validates it.
+ assertEquals("1.2.0", loaded.getCreatedHopVersion());
+ assertEquals("", loaded.getModifiedHopVersion());
+
+ String xml = loaded.getXml(variables);
+
assertTrue(xml.contains("<created_hop_version>1.2.0</created_hop_version>"));
+ assertTrue(xml.contains("<modified_hop_version/>"));
+ }
+
+ @Test
+ void workflowKeepsAManuallyBackfilledCreatedHopVersion() throws Exception {
+ WorkflowMeta loaded = loadWorkflow(WORKFLOW_WITH_BACKFILLED_VERSION);
+
+ assertEquals("1.2.0", loaded.getCreatedHopVersion());
+ assertEquals("", loaded.getModifiedHopVersion());
+
+ String xml = loaded.getXml(variables);
+
assertTrue(xml.contains("<created_hop_version>1.2.0</created_hop_version>"));
+ assertTrue(xml.contains("<modified_hop_version/>"));
+ }
+}
diff --git
a/plugins/misc/import/src/main/java/org/apache/hop/imports/kettle/KettleImport.java
b/plugins/misc/import/src/main/java/org/apache/hop/imports/kettle/KettleImport.java
index db0359dfeb..c04b1f72af 100644
---
a/plugins/misc/import/src/main/java/org/apache/hop/imports/kettle/KettleImport.java
+++
b/plugins/misc/import/src/main/java/org/apache/hop/imports/kettle/KettleImport.java
@@ -207,6 +207,7 @@ public class KettleImport extends HopImportBase implements
IHopImport {
Node targetNode = XmlHandler.getSubNode(documentElement, "info");
if (targetNode != null) {
targetNode.insertBefore(nameSync, XmlHandler.getSubNode(targetNode,
"description"));
+ addCreatedHopVersion(doc, targetNode);
}
} else if (extension.equalsIgnoreCase("kjb")) {
kjbCounter++;
@@ -215,6 +216,7 @@ public class KettleImport extends HopImportBase implements
IHopImport {
// Add the name-sync node in /workflow/
//
documentElement.insertBefore(nameSync,
XmlHandler.getSubNode(documentElement, "description"));
+ addCreatedHopVersion(doc, documentElement);
}
processNode(doc, documentElement, EntryType.OTHER, 0);
@@ -693,6 +695,24 @@ public class KettleImport extends HopImportBase implements
IHopImport {
}
}
+ /**
+ * Record the version of Hop that imported this pipeline or workflow. The
Kettle created and
+ * modified date and user elements carry the same names in Hop, so they pass
through the import
+ * untouched and keep their original Kettle values.
+ *
+ * @param doc the document being imported
+ * @param parent the node holding the metadata: /pipeline/info/ for a
pipeline, /workflow/ for a
+ * workflow
+ */
+ private void addCreatedHopVersion(Document doc, Node parent) {
+ // An empty element when the version isn't known, which happens when we're
not running from
+ // the packaged jars. That matches what the serializer writes for an
unknown version.
+ //
+ Element createdHopVersion = doc.createElement("created_hop_version");
+
createdHopVersion.appendChild(doc.createTextNode(Const.NVL(Const.getHopVersion(),
"")));
+ parent.insertBefore(createdHopVersion, XmlHandler.getSubNode(parent,
"description"));
+ }
+
private void setChildElement(Document doc, Node parent, String name, String
value) {
Element child = getChildElement(parent, name);
if (child == null) {
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 1f0e5e5bf2..303bb87d31 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
@@ -5145,6 +5145,10 @@ public class HopGuiPipelineGraph extends
HopGuiAbstractGraph
boolean fileExist = HopVfs.fileExists(pipelineMeta.getFilename());
+ // Record the version of Hop saving this pipeline
+ //
+ pipelineMeta.setModifiedHopVersion(Const.NVL(Const.getHopVersion(), ""));
+
String xml = pipelineMeta.getXml(variables);
OutputStream out = HopVfs.getOutputStream(pipelineMeta.getFilename(),
false);
try {
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopPipelineFileType.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopPipelineFileType.java
index 30acd970c2..301c947c4e 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopPipelineFileType.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/pipeline/HopPipelineFileType.java
@@ -20,6 +20,7 @@ package org.apache.hop.ui.hopgui.file.pipeline;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
+import org.apache.hop.core.Const;
import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.extension.ExtensionPointHandler;
import org.apache.hop.core.extension.HopExtensionPoint;
@@ -168,6 +169,10 @@ public class HopPipelineFileType<T extends PipelineMeta>
extends HopFileTypeBase
PipelineMeta pipelineMeta = new PipelineMeta();
pipelineMeta.setName(BaseMessages.getString(PKG,
"HopPipelineFileType.New.Text"));
+ // Record the version of Hop creating this pipeline
+ //
+ pipelineMeta.setCreatedHopVersion(Const.NVL(Const.getHopVersion(), ""));
+
// Pass the MetadataProvider for reference lookups
//
pipelineMeta.setMetadataProvider(hopGui.getMetadataProvider());
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
index 47441b3e0e..5c3666f22c 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopGuiWorkflowGraph.java
@@ -4677,6 +4677,10 @@ public class HopGuiWorkflowGraph extends
HopGuiAbstractGraph
boolean fileExist = HopVfs.fileExists(workflowMeta.getFilename());
+ // Record the version of Hop saving this workflow
+ //
+ workflowMeta.setModifiedHopVersion(Const.NVL(Const.getHopVersion(), ""));
+
String xml = workflowMeta.getXml(variables);
OutputStream out = HopVfs.getOutputStream(workflowMeta.getFilename(),
false);
try {
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopWorkflowFileType.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopWorkflowFileType.java
index 50b4a6fad8..16e29de2a8 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopWorkflowFileType.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/file/workflow/HopWorkflowFileType.java
@@ -20,6 +20,7 @@ package org.apache.hop.ui.hopgui.file.workflow;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
+import org.apache.hop.core.Const;
import org.apache.hop.core.exception.HopException;
import org.apache.hop.core.extension.ExtensionPointHandler;
import org.apache.hop.core.extension.HopExtensionPoint;
@@ -173,6 +174,10 @@ public class HopWorkflowFileType<T extends WorkflowMeta>
extends HopFileTypeBase
WorkflowMeta workflowMeta = new WorkflowMeta();
workflowMeta.setName(BaseMessages.getString(PKG,
"HopWorkflowFileType.New.Text"));
+ // Record the version of Hop creating this workflow
+ //
+ workflowMeta.setCreatedHopVersion(Const.NVL(Const.getHopVersion(), ""));
+
// Pass the MetaStore for reference lookups
//
workflowMeta.setMetadataProvider(hopGui.getMetadataProvider());
diff --git
a/ui/src/main/java/org/apache/hop/ui/pipeline/dialog/PipelineDialog.java
b/ui/src/main/java/org/apache/hop/ui/pipeline/dialog/PipelineDialog.java
index f8bbae145b..c81001e696 100644
--- a/ui/src/main/java/org/apache/hop/ui/pipeline/dialog/PipelineDialog.java
+++ b/ui/src/main/java/org/apache/hop/ui/pipeline/dialog/PipelineDialog.java
@@ -43,6 +43,7 @@ import
org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
@@ -97,6 +98,10 @@ public class PipelineDialog extends Dialog {
private Text wModUser;
private Text wModDate;
+ private Text wCreatedHopVersion;
+
+ private Text wModifiedHopVersion;
+
private TableView wParamFields;
private final IVariables variables;
@@ -233,7 +238,15 @@ public class PipelineDialog extends Dialog {
wPipelineTab.setFont(GuiResource.getInstance().getFontDefault());
wPipelineTab.setText(BaseMessages.getString(PKG,
"PipelineDialog.PipelineTab.Label"));
- Composite wPipelineComp = new Composite(wTabFolder, SWT.NONE);
+ // The field list is taller than the dialog once it's resized down, so the
tab scrolls
+ // rather than silently cutting off whatever no longer fits.
+ //
+ ScrolledComposite wPipelineSc = new ScrolledComposite(wTabFolder,
SWT.V_SCROLL | SWT.H_SCROLL);
+ PropsUi.setLook(wPipelineSc);
+ wPipelineSc.setExpandHorizontal(true);
+ wPipelineSc.setExpandVertical(true);
+
+ Composite wPipelineComp = new Composite(wPipelineSc, SWT.NONE);
PropsUi.setLook(wPipelineComp);
FormLayout workflowLayout = new FormLayout();
@@ -343,7 +356,7 @@ public class PipelineDialog extends Dialog {
fdExtendedDescription.left = new FormAttachment(middle, 0);
fdExtendedDescription.top = new FormAttachment(wPipelineDescription,
margin);
fdExtendedDescription.right = new FormAttachment(100, 0);
- fdExtendedDescription.bottom = new FormAttachment(50, -margin);
+ fdExtendedDescription.height = (int) (120 * PropsUi.getNativeZoomFactor());
wExtendedDescription.setLayoutData(fdExtendedDescription);
// Pipeline Status
@@ -426,6 +439,25 @@ public class PipelineDialog extends Dialog {
fdCreateDate.right = new FormAttachment(100, 0);
wCreateDate.setLayoutData(fdCreateDate);
+ // Created with Hop version:
+ Label wlCreatedHopVersion = new Label(wPipelineComp, SWT.RIGHT);
+ wlCreatedHopVersion.setText(
+ BaseMessages.getString(PKG, "PipelineDialog.CreatedHopVersion.Label"));
+ PropsUi.setLook(wlCreatedHopVersion);
+ FormData fdlCreatedHopVersion = new FormData();
+ fdlCreatedHopVersion.left = new FormAttachment(0, 0);
+ fdlCreatedHopVersion.right = new FormAttachment(middle, -margin);
+ fdlCreatedHopVersion.top = new FormAttachment(wCreateDate, margin);
+ wlCreatedHopVersion.setLayoutData(fdlCreatedHopVersion);
+ wCreatedHopVersion = new Text(wPipelineComp, SWT.SINGLE | SWT.LEFT |
SWT.BORDER);
+ PropsUi.setLook(wCreatedHopVersion);
+ wCreatedHopVersion.setEditable(false);
+ FormData fdCreatedHopVersion = new FormData();
+ fdCreatedHopVersion.left = new FormAttachment(middle, 0);
+ fdCreatedHopVersion.top = new FormAttachment(wCreateDate, margin);
+ fdCreatedHopVersion.right = new FormAttachment(100, 0);
+ wCreatedHopVersion.setLayoutData(fdCreatedHopVersion);
+
// Modified User:
Label wlModUser = new Label(wPipelineComp, SWT.RIGHT);
wlModUser.setText(BaseMessages.getString(PKG,
"PipelineDialog.LastModifiedUser.Label"));
@@ -433,7 +465,7 @@ public class PipelineDialog extends Dialog {
FormData fdlModUser = new FormData();
fdlModUser.left = new FormAttachment(0, 0);
fdlModUser.right = new FormAttachment(middle, -margin);
- fdlModUser.top = new FormAttachment(wCreateDate, margin);
+ fdlModUser.top = new FormAttachment(wCreatedHopVersion, margin);
wlModUser.setLayoutData(fdlModUser);
wModUser = new Text(wPipelineComp, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
PropsUi.setLook(wModUser);
@@ -441,7 +473,7 @@ public class PipelineDialog extends Dialog {
wModUser.addModifyListener(lsMod);
FormData fdModUser = new FormData();
fdModUser.left = new FormAttachment(middle, 0);
- fdModUser.top = new FormAttachment(wCreateDate, margin);
+ fdModUser.top = new FormAttachment(wCreatedHopVersion, margin);
fdModUser.right = new FormAttachment(100, 0);
wModUser.setLayoutData(fdModUser);
@@ -464,15 +496,29 @@ public class PipelineDialog extends Dialog {
fdModDate.right = new FormAttachment(100, 0);
wModDate.setLayoutData(fdModDate);
- FormData fdPipelineComp = new FormData();
- fdPipelineComp.left = new FormAttachment(0, 0);
- fdPipelineComp.top = new FormAttachment(0, 0);
- fdPipelineComp.right = new FormAttachment(100, 0);
- fdPipelineComp.bottom = new FormAttachment(100, 0);
- wPipelineComp.setLayoutData(fdPipelineComp);
-
- wPipelineComp.layout();
- wPipelineTab.setControl(wPipelineComp);
+ // Last modified with Hop version:
+ Label wlModifiedHopVersion = new Label(wPipelineComp, SWT.RIGHT);
+ wlModifiedHopVersion.setText(
+ BaseMessages.getString(PKG,
"PipelineDialog.ModifiedHopVersion.Label"));
+ PropsUi.setLook(wlModifiedHopVersion);
+ FormData fdlModifiedHopVersion = new FormData();
+ fdlModifiedHopVersion.left = new FormAttachment(0, 0);
+ fdlModifiedHopVersion.right = new FormAttachment(middle, -margin);
+ fdlModifiedHopVersion.top = new FormAttachment(wModDate, margin);
+ wlModifiedHopVersion.setLayoutData(fdlModifiedHopVersion);
+ wModifiedHopVersion = new Text(wPipelineComp, SWT.SINGLE | SWT.LEFT |
SWT.BORDER);
+ PropsUi.setLook(wModifiedHopVersion);
+ wModifiedHopVersion.setEditable(false);
+ FormData fdModifiedHopVersion = new FormData();
+ fdModifiedHopVersion.left = new FormAttachment(middle, 0);
+ fdModifiedHopVersion.top = new FormAttachment(wModDate, margin);
+ fdModifiedHopVersion.right = new FormAttachment(100, 0);
+ wModifiedHopVersion.setLayoutData(fdModifiedHopVersion);
+
+ wPipelineComp.layout(true, true);
+ wPipelineSc.setContent(wPipelineComp);
+ wPipelineSc.setMinSize(wPipelineComp.computeSize(SWT.DEFAULT,
SWT.DEFAULT));
+ wPipelineTab.setControl(wPipelineSc);
// ///////////////////////////////////////////////////////////
// / END OF PIPELINE TAB
@@ -696,6 +742,9 @@ public class PipelineDialog extends Dialog {
wModDate.setText(pipelineMeta.getModifiedDate().toString());
}
+ wCreatedHopVersion.setText(Const.NVL(pipelineMeta.getCreatedHopVersion(),
""));
+
wModifiedHopVersion.setText(Const.NVL(pipelineMeta.getModifiedHopVersion(),
""));
+
// The named parameters
String[] parameters = pipelineMeta.listParameters();
for (int idx = 0; idx < parameters.length; idx++) {
diff --git
a/ui/src/main/java/org/apache/hop/ui/workflow/dialog/WorkflowDialog.java
b/ui/src/main/java/org/apache/hop/ui/workflow/dialog/WorkflowDialog.java
index b187f8c312..d563a5a858 100644
--- a/ui/src/main/java/org/apache/hop/ui/workflow/dialog/WorkflowDialog.java
+++ b/ui/src/main/java/org/apache/hop/ui/workflow/dialog/WorkflowDialog.java
@@ -46,6 +46,7 @@ import org.apache.hop.workflow.action.IAction;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
@@ -112,6 +113,10 @@ public class WorkflowDialog extends Dialog {
private Text wModDate;
+ private Text wCreatedHopVersion;
+
+ private Text wModifiedHopVersion;
+
private ArrayList<IWorkflowDialogPlugin> extraTabs;
public WorkflowDialog(Shell parent, int style, IVariables variables,
WorkflowMeta workflowMeta) {
@@ -201,7 +206,15 @@ public class WorkflowDialog extends Dialog {
wWorkflowTab.setFont(GuiResource.getInstance().getFontDefault());
wWorkflowTab.setText(BaseMessages.getString(PKG,
"WorkflowDialog.WorkflowTab.Label"));
- Composite wWorkflowComp = new Composite(wTabFolder, SWT.NONE);
+ // The field list is taller than the dialog once it's resized down, so the
tab scrolls
+ // rather than silently cutting off whatever no longer fits.
+ //
+ ScrolledComposite wWorkflowSc = new ScrolledComposite(wTabFolder,
SWT.V_SCROLL | SWT.H_SCROLL);
+ PropsUi.setLook(wWorkflowSc);
+ wWorkflowSc.setExpandHorizontal(true);
+ wWorkflowSc.setExpandVertical(true);
+
+ Composite wWorkflowComp = new Composite(wWorkflowSc, SWT.NONE);
PropsUi.setLook(wWorkflowComp);
FormLayout workflowLayout = new FormLayout();
@@ -307,7 +320,7 @@ public class WorkflowDialog extends Dialog {
fdExtendedDescription.left = new FormAttachment(middle, 0);
fdExtendedDescription.top = new FormAttachment(wDescription, margin);
fdExtendedDescription.right = new FormAttachment(100, 0);
- fdExtendedDescription.bottom = new FormAttachment(50, -margin);
+ fdExtendedDescription.height = (int) (120 * PropsUi.getNativeZoomFactor());
wExtendedDescription.setLayoutData(fdExtendedDescription);
// Workflow version:
@@ -366,6 +379,25 @@ public class WorkflowDialog extends Dialog {
fdCreateDate.right = new FormAttachment(100, 0);
wCreateDate.setLayoutData(fdCreateDate);
+ // Created with Hop version:
+ Label wlCreatedHopVersion = new Label(wWorkflowComp, SWT.RIGHT);
+ wlCreatedHopVersion.setText(
+ BaseMessages.getString(PKG, "WorkflowDialog.CreatedHopVersion.Label"));
+ PropsUi.setLook(wlCreatedHopVersion);
+ FormData fdlCreatedHopVersion = new FormData();
+ fdlCreatedHopVersion.left = new FormAttachment(0, 0);
+ fdlCreatedHopVersion.right = new FormAttachment(middle, -margin);
+ fdlCreatedHopVersion.top = new FormAttachment(wCreateDate, margin);
+ wlCreatedHopVersion.setLayoutData(fdlCreatedHopVersion);
+ wCreatedHopVersion = new Text(wWorkflowComp, SWT.SINGLE | SWT.LEFT |
SWT.BORDER);
+ PropsUi.setLook(wCreatedHopVersion);
+ wCreatedHopVersion.setEditable(false);
+ FormData fdCreatedHopVersion = new FormData();
+ fdCreatedHopVersion.left = new FormAttachment(middle, 0);
+ fdCreatedHopVersion.top = new FormAttachment(wCreateDate, margin);
+ fdCreatedHopVersion.right = new FormAttachment(100, 0);
+ wCreatedHopVersion.setLayoutData(fdCreatedHopVersion);
+
// Modified User:
Label wlModUser = new Label(wWorkflowComp, SWT.RIGHT);
wlModUser.setText(BaseMessages.getString(PKG,
"WorkflowDialog.LastModifiedUser.Label"));
@@ -373,7 +405,7 @@ public class WorkflowDialog extends Dialog {
FormData fdlModUser = new FormData();
fdlModUser.left = new FormAttachment(0, 0);
fdlModUser.right = new FormAttachment(middle, -margin);
- fdlModUser.top = new FormAttachment(wCreateDate, margin);
+ fdlModUser.top = new FormAttachment(wCreatedHopVersion, margin);
wlModUser.setLayoutData(fdlModUser);
wModUser = new Text(wWorkflowComp, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
PropsUi.setLook(wModUser);
@@ -381,7 +413,7 @@ public class WorkflowDialog extends Dialog {
wModUser.addModifyListener(lsMod);
FormData fdModUser = new FormData();
fdModUser.left = new FormAttachment(middle, 0);
- fdModUser.top = new FormAttachment(wCreateDate, margin);
+ fdModUser.top = new FormAttachment(wCreatedHopVersion, margin);
fdModUser.right = new FormAttachment(100, 0);
wModUser.setLayoutData(fdModUser);
@@ -404,14 +436,29 @@ public class WorkflowDialog extends Dialog {
fdModDate.right = new FormAttachment(100, 0);
wModDate.setLayoutData(fdModDate);
- FormData fdWorkflowComp = new FormData();
- fdWorkflowComp.left = new FormAttachment(0, 0);
- fdWorkflowComp.top = new FormAttachment(0, 0);
- fdWorkflowComp.right = new FormAttachment(100, 0);
- fdWorkflowComp.bottom = new FormAttachment(100, 0);
-
- wWorkflowComp.setLayoutData(fdWorkflowComp);
- wWorkflowTab.setControl(wWorkflowComp);
+ // Last modified with Hop version:
+ Label wlModifiedHopVersion = new Label(wWorkflowComp, SWT.RIGHT);
+ wlModifiedHopVersion.setText(
+ BaseMessages.getString(PKG,
"WorkflowDialog.ModifiedHopVersion.Label"));
+ PropsUi.setLook(wlModifiedHopVersion);
+ FormData fdlModifiedHopVersion = new FormData();
+ fdlModifiedHopVersion.left = new FormAttachment(0, 0);
+ fdlModifiedHopVersion.right = new FormAttachment(middle, -margin);
+ fdlModifiedHopVersion.top = new FormAttachment(wModDate, margin);
+ wlModifiedHopVersion.setLayoutData(fdlModifiedHopVersion);
+ wModifiedHopVersion = new Text(wWorkflowComp, SWT.SINGLE | SWT.LEFT |
SWT.BORDER);
+ PropsUi.setLook(wModifiedHopVersion);
+ wModifiedHopVersion.setEditable(false);
+ FormData fdModifiedHopVersion = new FormData();
+ fdModifiedHopVersion.left = new FormAttachment(middle, 0);
+ fdModifiedHopVersion.top = new FormAttachment(wModDate, margin);
+ fdModifiedHopVersion.right = new FormAttachment(100, 0);
+ wModifiedHopVersion.setLayoutData(fdModifiedHopVersion);
+
+ wWorkflowComp.layout(true, true);
+ wWorkflowSc.setContent(wWorkflowComp);
+ wWorkflowSc.setMinSize(wWorkflowComp.computeSize(SWT.DEFAULT,
SWT.DEFAULT));
+ wWorkflowTab.setControl(wWorkflowSc);
// ///////////////////////////////////////////////////////////
// / END OF WORKFLOW TAB
@@ -536,6 +583,9 @@ public class WorkflowDialog extends Dialog {
wModDate.setText(workflowMeta.getModifiedDate().toString());
}
+ wCreatedHopVersion.setText(Const.NVL(workflowMeta.getCreatedHopVersion(),
""));
+
wModifiedHopVersion.setText(Const.NVL(workflowMeta.getModifiedHopVersion(),
""));
+
// The named parameters
String[] parameters = workflowMeta.listParameters();
for (int idx = 0; idx < parameters.length; idx++) {
diff --git
a/ui/src/main/resources/org/apache/hop/ui/pipeline/dialog/messages/messages_en_US.properties
b/ui/src/main/resources/org/apache/hop/ui/pipeline/dialog/messages/messages_en_US.properties
index 1e73e8d9ad..e738e4f860 100644
---
a/ui/src/main/resources/org/apache/hop/ui/pipeline/dialog/messages/messages_en_US.properties
+++
b/ui/src/main/resources/org/apache/hop/ui/pipeline/dialog/messages/messages_en_US.properties
@@ -25,6 +25,8 @@ PipelineDialog.Draft_PipelineStatus.Label=Draft
PipelineDialog.Extendeddescription.Label=Extended description
PipelineDialog.InvalidTransformPerfIntervalNumber.DialogMessage=The transform
performance interval must be a valid number. Values less or equal to zero are
not allowed.
PipelineDialog.InvalidTransformPerfIntervalNumber.DialogTitle=Error in
transform performance interval
+PipelineDialog.CreatedHopVersion.Label=Created with Hop version
+PipelineDialog.ModifiedHopVersion.Label=Last modified with Hop version
PipelineDialog.LastModifiedDate.Label=Last modified at
PipelineDialog.LastModifiedUser.Label=Last modified by
PipelineDialog.LoadDialogPlugin.Error.Header=Error
diff --git
a/ui/src/main/resources/org/apache/hop/ui/workflow/dialog/messages/messages_en_US.properties
b/ui/src/main/resources/org/apache/hop/ui/workflow/dialog/messages/messages_en_US.properties
index 6202186071..d8f9faa59b 100644
---
a/ui/src/main/resources/org/apache/hop/ui/workflow/dialog/messages/messages_en_US.properties
+++
b/ui/src/main/resources/org/apache/hop/ui/workflow/dialog/messages/messages_en_US.properties
@@ -27,6 +27,8 @@ WorkflowDialog.Description.Label=Description
WorkflowDialog.Draft_WorkflowStatus.Label=Draft
WorkflowDialog.Extendeddescription.Label=Extended description
WorkflowDialog.Filename.Label=Workflow filename
+WorkflowDialog.CreatedHopVersion.Label=Created with Hop version
+WorkflowDialog.ModifiedHopVersion.Label=Last modified with Hop version
WorkflowDialog.LastModifiedDate.Label=Last modified at
WorkflowDialog.LastModifiedUser.Label=Last modified by
WorkflowDialog.NameFilenameSync.Label=Synchronize name with filename