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 f5421f7fa2 save pipeline to update name attribute when renaming, fixes
#4998 (#6428)
f5421f7fa2 is described below
commit f5421f7fa2a9ffbc6b75959d8640d5e8003075f8
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Tue Jan 20 13:05:21 2026 +0100
save pipeline to update name attribute when renaming, fixes #4998 (#6428)
---
.../perspective/explorer/ExplorerPerspective.java | 113 +++++++++++++++++----
1 file changed, 96 insertions(+), 17 deletions(-)
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
index f29f7f33e8..8cc69f3571 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/explorer/ExplorerPerspective.java
@@ -18,6 +18,8 @@
package org.apache.hop.ui.hopgui.perspective.explorer;
import java.io.File;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -54,7 +56,10 @@ import org.apache.hop.core.svg.SvgCacheEntry;
import org.apache.hop.core.svg.SvgFile;
import org.apache.hop.core.svg.SvgImage;
import org.apache.hop.core.util.Utils;
+import org.apache.hop.core.variables.IVariables;
+import org.apache.hop.core.variables.Variables;
import org.apache.hop.core.vfs.HopVfs;
+import org.apache.hop.core.xml.XmlHandler;
import org.apache.hop.i18n.BaseMessages;
import org.apache.hop.pipeline.PipelineMeta;
import org.apache.hop.pipeline.engine.IPipelineEngine;
@@ -192,7 +197,7 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
@Getter private GuiMenuWidgets menuWidgets;
private final List<TabItemHandler> items;
private boolean showingHiddenFiles;
- private Composite treeComposite;
+
private boolean fileExplorerPanelVisible = true;
@Getter private String rootFolder;
@Getter private String rootName;
@@ -397,6 +402,7 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
}
protected void createTree(Composite parent) {
+ Composite treeComposite;
// Create composite
//
treeComposite = new Composite(parent, SWT.NONE);
@@ -900,8 +906,7 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
}
}
- private void renameFile(FileObject sourceFile, FileObject targetFile)
- throws FileSystemException, HopFileException {
+ private void renameFile(FileObject sourceFile, FileObject targetFile) throws
FileSystemException {
if (sourceFile.isFolder()) {
// List all impacted files
@@ -921,6 +926,7 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
changeFilename(handler.getTypeHandler(), path.toString());
updateTabItem(handler.getTypeHandler());
+ saveFileIfNameSynchronized(handler.getTypeHandler());
}
}
} else {
@@ -932,6 +938,10 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
if (handler != null) {
changeFilename(handler.getTypeHandler(),
HopVfs.getFilename(targetFile));
updateTabItem(handler.getTypeHandler());
+ saveFileIfNameSynchronized(handler.getTypeHandler());
+ } else {
+ // File is not open, but we still need to update the name attribute if
name sync is enabled
+ updateClosedFileIfNameSynchronized(targetFile);
}
}
@@ -986,6 +996,79 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
hopGui.fileRefreshDelegate.register(newFilename, fileTypeHandler);
}
+ /**
+ * Save the file if it's a pipeline or workflow with name synchronization
enabled. This ensures
+ * that when a file is renamed, the name attribute in the XML is updated to
match the new
+ * filename.
+ *
+ * @param fileTypeHandler to specify which filetype
+ */
+ private void saveFileIfNameSynchronized(IHopFileTypeHandler fileTypeHandler)
{
+ try {
+ Object subject = fileTypeHandler.getSubject();
+ if (subject instanceof PipelineMeta pipelineMeta
+ && pipelineMeta.isNameSynchronizedWithFilename()) {
+ fileTypeHandler.save();
+ } else if (subject instanceof WorkflowMeta workflowMeta
+ && workflowMeta.isNameSynchronizedWithFilename()) {
+ fileTypeHandler.save();
+ }
+
+ } catch (Exception e) {
+ hopGui.getLog().logError("Error saving file after rename", e);
+ }
+ }
+
+ /**
+ * Update a closed file's name attribute if it has name synchronization
enabled. This is called
+ * when renaming a file that is not currently open in any tab.
+ */
+ private void updateClosedFileIfNameSynchronized(FileObject targetFile) {
+ try {
+ String filename = HopVfs.getFilename(targetFile);
+ String extension = filename.substring(filename.lastIndexOf('.'));
+
+ // Check if it's a pipeline or workflow file
+ if (".hpl".equalsIgnoreCase(extension)) {
+ // Load pipeline
+ IVariables variables = Variables.getADefaultVariableSpace();
+ PipelineMeta pipelineMeta =
+ new PipelineMeta(filename, hopGui.getMetadataProvider(),
variables);
+ if (pipelineMeta.isNameSynchronizedWithFilename()) {
+ // Save to update the name attribute
+ String xml = pipelineMeta.getXml(variables);
+ OutputStream out = HopVfs.getOutputStream(filename, false);
+ try {
+
out.write(XmlHandler.getXmlHeader(Const.XML_ENCODING).getBytes(StandardCharsets.UTF_8));
+ out.write(xml.getBytes(StandardCharsets.UTF_8));
+ } finally {
+ out.flush();
+ out.close();
+ }
+ }
+ } else if (".hwf".equalsIgnoreCase(extension)) {
+ // Load workflow
+ IVariables variables = Variables.getADefaultVariableSpace();
+ WorkflowMeta workflowMeta =
+ new WorkflowMeta(variables, filename,
hopGui.getMetadataProvider());
+ if (workflowMeta.isNameSynchronizedWithFilename()) {
+ // Save to update the name attribute
+ String xml = workflowMeta.getXml(variables);
+ OutputStream out = HopVfs.getOutputStream(filename, false);
+ try {
+
out.write(XmlHandler.getXmlHeader(Const.XML_ENCODING).getBytes(StandardCharsets.UTF_8));
+ out.write(xml.getBytes(StandardCharsets.UTF_8));
+ } finally {
+ out.flush();
+ out.close();
+ }
+ }
+ }
+ } catch (Exception e) {
+ hopGui.getLog().logError("Error updating closed file after rename", e);
+ }
+ }
+
protected void createTabFolder(Composite parent) {
tabFolder = new CTabFolder(parent, SWT.MULTI | SWT.BORDER);
tabFolder.addListener(SWT.Selection, e -> updateGui());
@@ -1682,7 +1765,7 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
rootItem.setText(Const.NVL(rootName, ""));
IHopFileType fileType = getFileType(rootFolder);
setItemImage(rootItem, fileType);
- callPaintListeners(tree, rootItem, rootFolder, rootName, fileType);
+ callPaintListeners(tree, rootItem, rootFolder, rootName);
setTreeItemData(rootItem, rootFolder, rootName, fileType, 0, true, true);
// Paint the top level folder only
@@ -1818,7 +1901,7 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
TreeItem childItem = new TreeItem(item, SWT.NONE);
childItem.setText(childName);
setItemImage(childItem, fileType);
- callPaintListeners(tree, childItem, childPath, childName, fileType);
+ callPaintListeners(tree, childItem, childPath, childName);
setTreeItemData(childItem, childPath, childName, fileType, depth,
folder, true);
// Recursively add children
@@ -1874,8 +1957,7 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
}
}
- private void callPaintListeners(
- Tree tree, TreeItem treeItem, String path, String name, IHopFileType
fileType) {
+ private void callPaintListeners(Tree tree, TreeItem treeItem, String path,
String name) {
for (IExplorerFilePaintListener filePaintListener : filePaintListeners) {
filePaintListener.filePainted(tree, treeItem, path, name);
}
@@ -2051,11 +2133,9 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
// If the filename is a URL and the name is the full URL or very long,
extract a better title
if (filename != null
&& (filename.toLowerCase().startsWith("http://")
- || filename.toLowerCase().startsWith("https://"))) {
- // If name is the URL or longer than 30 chars, extract a better title
- if (name == null || name.equals(filename) || name.length() > 30) {
- return extractTitleFromUrl(filename);
- }
+ || filename.toLowerCase().startsWith("https://"))
+ && (name == null || name.equals(filename) || name.length() > 30)) {
+ return extractTitleFromUrl(filename);
}
return name;
@@ -2104,8 +2184,8 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
String[] words = title.split("\\s+");
StringBuilder result = new StringBuilder();
for (String word : words) {
- if (word.length() > 0) {
- if (result.length() > 0) {
+ if (!word.isEmpty()) {
+ if (!result.isEmpty()) {
result.append(" ");
}
result.append(word.substring(0, 1).toUpperCase());
@@ -2176,8 +2256,7 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
for (IExplorerRefreshListener listener : refreshListeners) {
listener.beforeRefresh();
}
- callPaintListeners(
- tree, item, filename, fileTypeHandler.getName(),
fileTypeHandler.getFileType());
+ callPaintListeners(tree, item, filename, fileTypeHandler.getName());
}
}
}
@@ -2339,7 +2418,7 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable {
if (fileExplorerPanelVisible) {
// Show the file explorer panel - restore normal layout
sash.setMaximizedControl(null);
- sash.setWeights(new int[] {20, 80});
+ sash.setWeights(20, 80);
} else {
// Hide the file explorer panel - maximize the tab folder
sash.setMaximizedControl(tabFolder);