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 6b22959e91 Add the “Save As” capability to text files #6238 (#6260)
6b22959e91 is described below

commit 6b22959e91d00fb7f10c76dd9ad4d630db075cd2
Author: Nicolas Adment <[email protected]>
AuthorDate: Mon Dec 29 11:48:06 2025 +0100

    Add the “Save As” capability to text files #6238 (#6260)
---
 .../transforms/types/JsonExplorerFileType.java     |  1 +
 .../types/JsonExplorerFileTypeTest.java}           | 42 +++++++++++++---------
 .../transforms/types/CsvExplorerFileType.java      |  5 ++-
 .../transforms/types/MarkDownExplorerFileType.java |  1 +
 .../transforms/types/TextExplorerFileType.java     |  1 +
 .../transforms/types/CsvExplorerFileTypeTest.java  | 20 ++++++++---
 .../types/MarkDownExplorerFileTypeTest.java        | 12 ++++++-
 .../transforms/types/TextExplorerFileTypeTest.java |  5 +++
 .../transforms/xml/types/XmlExplorerFileType.java  |  1 +
 .../types/base/BaseExplorerFileTypeHandler.java    |  7 ++--
 .../file/types/log/LogExplorerFileType.java        |  1 +
 .../text/BaseTextExplorerFileTypeHandler.java      | 39 ++++++++++++++++++--
 12 files changed, 108 insertions(+), 27 deletions(-)

diff --git 
a/plugins/transforms/json/src/main/java/org/apache/hop/pipeline/transforms/types/JsonExplorerFileType.java
 
b/plugins/transforms/json/src/main/java/org/apache/hop/pipeline/transforms/types/JsonExplorerFileType.java
index c7afb68bb7..fc19743704 100644
--- 
a/plugins/transforms/json/src/main/java/org/apache/hop/pipeline/transforms/types/JsonExplorerFileType.java
+++ 
b/plugins/transforms/json/src/main/java/org/apache/hop/pipeline/transforms/types/JsonExplorerFileType.java
@@ -44,6 +44,7 @@ public class JsonExplorerFileType extends 
BaseTextExplorerFileType<JsonExplorerF
         new String[] {"JSON files"},
         FileTypeCapabilities.getCapabilities(
             IHopFileType.CAPABILITY_SAVE,
+            IHopFileType.CAPABILITY_SAVE_AS,
             IHopFileType.CAPABILITY_CLOSE,
             IHopFileType.CAPABILITY_FILE_HISTORY,
             IHopFileType.CAPABILITY_COPY,
diff --git 
a/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/CsvExplorerFileTypeTest.java
 
b/plugins/transforms/json/src/test/java/org/apache/hop/pipeline/transforms/types/JsonExplorerFileTypeTest.java
similarity index 76%
copy from 
plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/CsvExplorerFileTypeTest.java
copy to 
plugins/transforms/json/src/test/java/org/apache/hop/pipeline/transforms/types/JsonExplorerFileTypeTest.java
index bb972423e3..30a08b2fe8 100644
--- 
a/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/CsvExplorerFileTypeTest.java
+++ 
b/plugins/transforms/json/src/test/java/org/apache/hop/pipeline/transforms/types/JsonExplorerFileTypeTest.java
@@ -26,13 +26,13 @@ import org.apache.hop.ui.hopgui.file.IHopFileType;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-class CsvExplorerFileTypeTest {
+class JsonExplorerFileTypeTest {
 
-  private CsvExplorerFileType fileType;
+  private JsonExplorerFileType fileType;
 
   @BeforeEach
   void setUp() {
-    fileType = new CsvExplorerFileType();
+    fileType = new JsonExplorerFileType();
   }
 
   @Test
@@ -42,12 +42,12 @@ class CsvExplorerFileTypeTest {
 
   @Test
   void testGetName() {
-    assertEquals("CSV File", fileType.getName());
+    assertEquals("JSON File", fileType.getName());
   }
 
   @Test
   void testGetDefaultFileExtension() {
-    assertEquals(".csv", fileType.getDefaultFileExtension());
+    assertEquals(".json", fileType.getDefaultFileExtension());
   }
 
   @Test
@@ -55,7 +55,7 @@ class CsvExplorerFileTypeTest {
     String[] extensions = fileType.getFilterExtensions();
     assertNotNull(extensions);
     assertEquals(1, extensions.length);
-    assertEquals("*.csv", extensions[0]);
+    assertEquals("*.json", extensions[0]);
   }
 
   @Test
@@ -63,7 +63,7 @@ class CsvExplorerFileTypeTest {
     String[] names = fileType.getFilterNames();
     assertNotNull(names);
     assertEquals(1, names.length);
-    assertEquals("CSV files", names[0]);
+    assertEquals("JSON files", names[0]);
   }
 
   @Test
@@ -71,6 +71,11 @@ class CsvExplorerFileTypeTest {
     assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SAVE));
   }
 
+  @Test
+  void testHasCapabilitySaveAs() {
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SAVE_AS));
+  }
+
   @Test
   void testHasCapabilityClose() {
     assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_CLOSE));
@@ -82,13 +87,18 @@ class CsvExplorerFileTypeTest {
   }
 
   @Test
-  void testDoesNotHaveCapabilityCopy() {
-    assertFalse(fileType.hasCapability(IHopFileType.CAPABILITY_COPY));
+  void testHasCapabilityCopy() {
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_COPY));
+  }
+
+  @Test
+  void testHasCapabilitySelect() {
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SELECT));
   }
 
   @Test
-  void testDoesNotHaveCapabilitySelect() {
-    assertFalse(fileType.hasCapability(IHopFileType.CAPABILITY_SELECT));
+  void testDoesNotHaveCapabilityStart() {
+    assertFalse(fileType.hasCapability(IHopFileType.CAPABILITY_START));
   }
 
   @Test
@@ -117,13 +127,13 @@ class CsvExplorerFileTypeTest {
   @Test
   void testGetCapabilities() {
     assertNotNull(fileType.getCapabilities());
-    assertTrue(fileType.getCapabilities().size() > 0);
+    assertFalse(fileType.getCapabilities().isEmpty());
   }
 
   @Test
-  void testFileTypeIsForCsvFiles() {
-    assertTrue(fileType.getDefaultFileExtension().endsWith(".csv"));
-    assertTrue(fileType.getFilterExtensions()[0].contains("csv"));
-    assertTrue(fileType.getFilterNames()[0].toLowerCase().contains("csv"));
+  void testFileTypeIsForJsonFiles() {
+    assertTrue(fileType.getDefaultFileExtension().endsWith(".json"));
+    assertTrue(fileType.getFilterExtensions()[0].contains("json"));
+    assertTrue(fileType.getFilterNames()[0].toLowerCase().contains("json"));
   }
 }
diff --git 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/CsvExplorerFileType.java
 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/CsvExplorerFileType.java
index 844c207dfa..0e6170ca53 100644
--- 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/CsvExplorerFileType.java
+++ 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/CsvExplorerFileType.java
@@ -44,8 +44,11 @@ public class CsvExplorerFileType extends 
BaseTextExplorerFileType<TextExplorerFi
         new String[] {"CSV files"},
         FileTypeCapabilities.getCapabilities(
             IHopFileType.CAPABILITY_SAVE,
+            IHopFileType.CAPABILITY_SAVE_AS,
             IHopFileType.CAPABILITY_CLOSE,
-            IHopFileType.CAPABILITY_FILE_HISTORY));
+            IHopFileType.CAPABILITY_FILE_HISTORY,
+            IHopFileType.CAPABILITY_COPY,
+            IHopFileType.CAPABILITY_SELECT));
   }
 
   @Override
diff --git 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/MarkDownExplorerFileType.java
 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/MarkDownExplorerFileType.java
index 4166c3c4b4..4f26c0bd75 100644
--- 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/MarkDownExplorerFileType.java
+++ 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/MarkDownExplorerFileType.java
@@ -45,6 +45,7 @@ public class MarkDownExplorerFileType
         new String[] {"MarkDown files"},
         FileTypeCapabilities.getCapabilities(
             IHopFileType.CAPABILITY_SAVE,
+            IHopFileType.CAPABILITY_SAVE_AS,
             IHopFileType.CAPABILITY_CLOSE,
             IHopFileType.CAPABILITY_FILE_HISTORY,
             IHopFileType.CAPABILITY_COPY,
diff --git 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/TextExplorerFileType.java
 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/TextExplorerFileType.java
index 568e70ab6a..094a47ebc2 100644
--- 
a/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/TextExplorerFileType.java
+++ 
b/plugins/transforms/textfile/src/main/java/org/apache/hop/pipeline/transforms/types/TextExplorerFileType.java
@@ -44,6 +44,7 @@ public class TextExplorerFileType extends 
BaseTextExplorerFileType<TextExplorerF
         new String[] {"TXT files"},
         FileTypeCapabilities.getCapabilities(
             IHopFileType.CAPABILITY_SAVE,
+            IHopFileType.CAPABILITY_SAVE_AS,
             IHopFileType.CAPABILITY_CLOSE,
             IHopFileType.CAPABILITY_FILE_HISTORY,
             IHopFileType.CAPABILITY_COPY,
diff --git 
a/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/CsvExplorerFileTypeTest.java
 
b/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/CsvExplorerFileTypeTest.java
index bb972423e3..1e0d648b5a 100644
--- 
a/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/CsvExplorerFileTypeTest.java
+++ 
b/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/CsvExplorerFileTypeTest.java
@@ -71,6 +71,11 @@ class CsvExplorerFileTypeTest {
     assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SAVE));
   }
 
+  @Test
+  void testHasCapabilitySaveAs() {
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SAVE_AS));
+  }
+
   @Test
   void testHasCapabilityClose() {
     assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_CLOSE));
@@ -82,13 +87,18 @@ class CsvExplorerFileTypeTest {
   }
 
   @Test
-  void testDoesNotHaveCapabilityCopy() {
-    assertFalse(fileType.hasCapability(IHopFileType.CAPABILITY_COPY));
+  void testHasCapabilityCopy() {
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_COPY));
+  }
+
+  @Test
+  void testHasCapabilitySelect() {
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SELECT));
   }
 
   @Test
-  void testDoesNotHaveCapabilitySelect() {
-    assertFalse(fileType.hasCapability(IHopFileType.CAPABILITY_SELECT));
+  void testDoesNotHaveCapabilityStart() {
+    assertFalse(fileType.hasCapability(IHopFileType.CAPABILITY_START));
   }
 
   @Test
@@ -117,7 +127,7 @@ class CsvExplorerFileTypeTest {
   @Test
   void testGetCapabilities() {
     assertNotNull(fileType.getCapabilities());
-    assertTrue(fileType.getCapabilities().size() > 0);
+    assertFalse(fileType.getCapabilities().isEmpty());
   }
 
   @Test
diff --git 
a/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/MarkDownExplorerFileTypeTest.java
 
b/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/MarkDownExplorerFileTypeTest.java
index 67c2ebb09f..a7777899b2 100644
--- 
a/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/MarkDownExplorerFileTypeTest.java
+++ 
b/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/MarkDownExplorerFileTypeTest.java
@@ -71,6 +71,11 @@ class MarkDownExplorerFileTypeTest {
     assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SAVE));
   }
 
+  @Test
+  void testHasCapabilitySaveAs() {
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SAVE_AS));
+  }
+
   @Test
   void testHasCapabilityClose() {
     assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_CLOSE));
@@ -91,6 +96,11 @@ class MarkDownExplorerFileTypeTest {
     assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SELECT));
   }
 
+  @Test
+  void testDoesNotHaveCapabilityStart() {
+    assertFalse(fileType.hasCapability(IHopFileType.CAPABILITY_START));
+  }
+
   @Test
   void testMultipleFilterExtensions() {
     String[] extensions = fileType.getFilterExtensions();
@@ -117,7 +127,7 @@ class MarkDownExplorerFileTypeTest {
   @Test
   void testGetCapabilities() {
     assertNotNull(fileType.getCapabilities());
-    assertTrue(fileType.getCapabilities().size() > 0);
+    assertFalse(fileType.getCapabilities().isEmpty());
   }
 
   @Test
diff --git 
a/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/TextExplorerFileTypeTest.java
 
b/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/TextExplorerFileTypeTest.java
index dac01b6eda..68defea278 100644
--- 
a/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/TextExplorerFileTypeTest.java
+++ 
b/plugins/transforms/textfile/src/test/java/org/apache/hop/pipeline/transforms/types/TextExplorerFileTypeTest.java
@@ -71,6 +71,11 @@ class TextExplorerFileTypeTest {
     assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SAVE));
   }
 
+  @Test
+  void testHasCapabilitySaveAs() {
+    assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_SAVE_AS));
+  }
+
   @Test
   void testHasCapabilityClose() {
     assertTrue(fileType.hasCapability(IHopFileType.CAPABILITY_CLOSE));
diff --git 
a/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/types/XmlExplorerFileType.java
 
b/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/types/XmlExplorerFileType.java
index d8cdc0e24f..95a47259e2 100644
--- 
a/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/types/XmlExplorerFileType.java
+++ 
b/plugins/transforms/xml/src/main/java/org/apache/hop/pipeline/transforms/xml/types/XmlExplorerFileType.java
@@ -44,6 +44,7 @@ public class XmlExplorerFileType extends 
BaseTextExplorerFileType<XmlExplorerFil
         new String[] {"XML files"},
         FileTypeCapabilities.getCapabilities(
             IHopFileType.CAPABILITY_SAVE,
+            IHopFileType.CAPABILITY_SAVE_AS,
             IHopFileType.CAPABILITY_CLOSE,
             IHopFileType.CAPABILITY_FILE_HISTORY,
             IHopFileType.CAPABILITY_COPY,
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/file/types/base/BaseExplorerFileTypeHandler.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/file/types/base/BaseExplorerFileTypeHandler.java
index 35a7d7c82a..db49b6665e 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/file/types/base/BaseExplorerFileTypeHandler.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/file/types/base/BaseExplorerFileTypeHandler.java
@@ -168,8 +168,11 @@ public abstract class BaseExplorerFileTypeHandler 
implements IExplorerFileTypeHa
     hopGui
         .getDisplay()
         .asyncExec(
-            () ->
-                hopGui.handleFileCapabilities(this.getFileType(), 
this.hasChanged(), false, false));
+            () -> {
+              hopGui.handleFileCapabilities(this.getFileType(), 
this.hasChanged(), false, false);
+              perspective.updateTabItem(this);
+              perspective.updateTreeItem(this);
+            });
   }
 
   @Override
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/file/types/log/LogExplorerFileType.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/file/types/log/LogExplorerFileType.java
index 340f46b716..4a9e8d19d3 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/file/types/log/LogExplorerFileType.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/file/types/log/LogExplorerFileType.java
@@ -44,6 +44,7 @@ public class LogExplorerFileType extends 
BaseTextExplorerFileType<LogExplorerFil
         new String[] {"Log files"},
         FileTypeCapabilities.getCapabilities(
             IHopFileType.CAPABILITY_SAVE,
+            IHopFileType.CAPABILITY_SAVE_AS,
             IHopFileType.CAPABILITY_CLOSE,
             IHopFileType.CAPABILITY_FILE_HISTORY,
             IHopFileType.CAPABILITY_COPY,
diff --git 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/file/types/text/BaseTextExplorerFileTypeHandler.java
 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/file/types/text/BaseTextExplorerFileTypeHandler.java
index f9811cc930..b3497659b0 100644
--- 
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/file/types/text/BaseTextExplorerFileTypeHandler.java
+++ 
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/file/types/text/BaseTextExplorerFileTypeHandler.java
@@ -19,12 +19,14 @@ package 
org.apache.hop.ui.hopgui.perspective.explorer.file.types.text;
 
 import java.io.OutputStream;
 import java.nio.charset.StandardCharsets;
+import org.apache.commons.vfs2.FileObject;
 import org.apache.hop.core.Const;
 import org.apache.hop.core.Props;
 import org.apache.hop.core.exception.HopException;
 import org.apache.hop.core.logging.LogChannel;
 import org.apache.hop.core.vfs.HopVfs;
 import org.apache.hop.ui.core.PropsUi;
+import org.apache.hop.ui.core.dialog.MessageBox;
 import org.apache.hop.ui.hopgui.HopGui;
 import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerFile;
 import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerPerspective;
@@ -97,8 +99,8 @@ public class BaseTextExplorerFileTypeHandler extends 
BaseExplorerFileTypeHandler
 
       this.clearChanged();
 
-      // Update menu options
-      perspective.updateGui();
+      // Update menu options, tab and tree item
+      updateGui();
 
       // If we create a new file, refresh the explorer perspective tree
       if (!fileExist) {
@@ -109,6 +111,39 @@ public class BaseTextExplorerFileTypeHandler extends 
BaseExplorerFileTypeHandler
     }
   }
 
+  @Override
+  public void saveAs(String filename) throws HopException {
+    try {
+
+      // Enforce file extension
+      if 
(!filename.toLowerCase().endsWith(this.getFileType().getDefaultFileExtension()))
 {
+        filename = filename + this.getFileType().getDefaultFileExtension();
+      }
+
+      // Normalize file name
+      filename = HopVfs.normalize(filename);
+
+      FileObject fileObject = HopVfs.getFileObject(filename);
+      if (fileObject.exists()) {
+        MessageBox box =
+            new MessageBox(hopGui.getActiveShell(), SWT.YES | SWT.NO | 
SWT.ICON_QUESTION);
+        box.setText("Overwrite?");
+        box.setMessage("Are you sure you want to overwrite file '" + filename 
+ "'?");
+        int answer = box.open();
+        if ((answer & SWT.YES) == 0) {
+          return;
+        }
+      }
+
+      setFilename(filename);
+
+      save();
+      hopGui.fileRefreshDelegate.register(filename, this);
+    } catch (Exception e) {
+      throw new HopException("Error validating file existence for '" + 
filename + "'", e);
+    }
+  }
+
   @Override
   public void reload() {
     try {

Reply via email to