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 12a26db20f Button to view object references, fixes #7101 (#7471)
12a26db20f is described below
commit 12a26db20fb0b0d6bded9f83c841a93b20c1074a
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Thu Jul 9 15:46:05 2026 +0200
Button to view object references, fixes #7101 (#7471)
---
.../perspective/explorer/ExplorerPerspective.java | 93 +++++++++++
.../perspective/metadata/MetadataPerspective.java | 68 ++++++++
.../ui/hopgui/search/HopGuiSearchResultsPanel.java | 43 +++++-
.../ui/hopgui/search/ReferenceSearchResults.java | 172 +++++++++++++++++++++
.../explorer/messages/messages_en_US.properties | 6 +
.../metadata/messages/messages_en_US.properties | 6 +
6 files changed, 384 insertions(+), 4 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 de696b85da..00f8071d14 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
@@ -53,6 +53,7 @@ import
org.apache.hop.core.gui.plugin.toolbar.GuiToolbarElement;
import org.apache.hop.core.listeners.IContentChangedListener;
import org.apache.hop.core.plugins.IPlugin;
import org.apache.hop.core.plugins.PluginRegistry;
+import org.apache.hop.core.search.ISearchResult;
import org.apache.hop.core.search.ISearchable;
import org.apache.hop.core.search.SearchMatcher;
import org.apache.hop.core.svg.SvgCache;
@@ -118,6 +119,7 @@ import
org.apache.hop.ui.hopgui.perspective.explorer.file.types.GenericFileType;
import org.apache.hop.ui.hopgui.perspective.metadata.MetadataPerspective;
import org.apache.hop.ui.hopgui.search.HopGuiPipelineSearchable;
import org.apache.hop.ui.hopgui.search.HopGuiWorkflowSearchable;
+import org.apache.hop.ui.hopgui.search.ReferenceSearchResults;
import org.apache.hop.ui.hopgui.shared.CanvasZoomHelper;
import org.apache.hop.ui.hopgui.shared.SashFormMemory;
import org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
@@ -213,6 +215,8 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable, IFileD
"ExplorerPerspective-ContextMenu-10400-CopyName";
public static final String CONTEXT_MENU_COPY_PATH =
"ExplorerPerspective-ContextMenu-10401-CopyPath";
+ public static final String CONTEXT_MENU_FIND_REFERENCES =
+ "ExplorerPerspective-ContextMenu-10402-FindReferences";
public static final String CONTEXT_MENU_DELETE =
"ExplorerPerspective-ContextMenu-90000-Delete";
private static final String FILE_EXPLORER_TREE = "File explorer tree";
private static final String TREE_WIDTH_AUDIT_TYPE =
"explorer-perspective-tree-width";
@@ -633,6 +637,17 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable, IFileD
menuWidgets.findMenuItem(CONTEXT_MENU_RENAME).setEnabled(selection.length == 1);
+ // Finding references is only meaningful for a single pipeline or
workflow file.
+ //
+ MenuItem findReferencesItem =
menuWidgets.findMenuItem(CONTEXT_MENU_FIND_REFERENCES);
+ if (findReferencesItem != null) {
+ findReferencesItem.setEnabled(
+ selection.length == 1
+ && tif != null
+ && !tif.folder
+ && isPipelineOrWorkflowFile(tif.path));
+ }
+
// Show the menu
//
menu.setVisible(true);
@@ -2817,6 +2832,84 @@ public class ExplorerPerspective implements
IHopPerspective, TabClosable, IFileD
GuiResource.getInstance().toClipboard(folder.path);
}
+ @GuiMenuElement(
+ root = GUI_PLUGIN_CONTEXT_MENU_PARENT_ID,
+ parentId = GUI_PLUGIN_CONTEXT_MENU_PARENT_ID,
+ id = CONTEXT_MENU_FIND_REFERENCES,
+ label = "i18n::ExplorerPerspective.Menu.FindReferences",
+ image = "ui/images/search.svg",
+ separator = true)
+ public void findReferences() {
+ TreeItem[] selection = tree.getSelection();
+ if (selection == null || selection.length != 1) {
+ return;
+ }
+ TreeItemFolder tif = (TreeItemFolder) selection[0].getData();
+ if (tif == null || tif.folder || !isPipelineOrWorkflowFile(tif.path)) {
+ return;
+ }
+ findReferences(tif.path, tif.name);
+ }
+
+ /**
+ * Best-effort static scan (same engine as rename) for pipelines/workflows
and metadata objects
+ * that reference the given file. Results are shown in the shared
search-results UI, in a
+ * bottom-dock tab, so each one can be opened by double-clicking it.
+ */
+ private void findReferences(String path, String name) {
+ String projectHome = hopGui.getVariables().resolve(Const.VAR_PROJECT_HOME);
+ if (Utils.isEmpty(projectHome) ||
Const.VAR_PROJECT_HOME.equals(projectHome)) {
+ // Without an active project there is nothing to scan.
+ showNoReferencesFound(name);
+ return;
+ }
+ List<String> searchRoots =
java.util.Collections.singletonList(projectHome);
+ try {
+ MetadataReferenceFinder finder = new
MetadataReferenceFinder(hopGui.getMetadataProvider());
+ List<MetadataReferenceResult> fileReferences =
+ finder.findFileReferences(searchRoots, path, hopGui.getVariables());
+ List<MetadataObjectReference> metadataReferences =
+ finder.findFilePathReferencesInMetadata(path, hopGui.getVariables());
+
+ List<ISearchResult> results =
+ ReferenceSearchResults.build(hopGui, fileReferences,
metadataReferences);
+ if (results.isEmpty()) {
+ showNoReferencesFound(name);
+ return;
+ }
+ ReferenceSearchResults.showInBottomDock(
+ hopGui,
+ BaseMessages.getString(PKG,
"ExplorerPerspective.FindReferences.Tab.Title", name),
+ name,
+ results);
+ } catch (HopException e) {
+ new ErrorDialog(
+ hopGui.getShell(),
+ BaseMessages.getString(PKG,
"ExplorerPerspective.FindReferences.Error.Title"),
+ BaseMessages.getString(PKG,
"ExplorerPerspective.FindReferences.Error.Message", name),
+ e);
+ }
+ }
+
+ private void showNoReferencesFound(String name) {
+ MessageBox box = new MessageBox(hopGui.getShell(), SWT.ICON_INFORMATION |
SWT.OK);
+ box.setText(
+ BaseMessages.getString(PKG,
"ExplorerPerspective.FindReferences.NoReferences.Title"));
+ box.setMessage(
+ BaseMessages.getString(
+ PKG, "ExplorerPerspective.FindReferences.NoReferences.Message",
name));
+ box.open();
+ }
+
+ /** True when the path is a pipeline (.hpl) or workflow (.hwf) file. */
+ private static boolean isPipelineOrWorkflowFile(String path) {
+ if (path == null) {
+ return false;
+ }
+ String lower = path.toLowerCase(java.util.Locale.ROOT);
+ return lower.endsWith(".hpl") || lower.endsWith(".hwf");
+ }
+
@GuiToolbarElement(
root = GUI_PLUGIN_TOOLBAR_PARENT_ID,
id = TOOLBAR_ITEM_REFRESH,
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/metadata/MetadataPerspective.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/metadata/MetadataPerspective.java
index f482d7396a..f9e2fc874d 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/metadata/MetadataPerspective.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/metadata/MetadataPerspective.java
@@ -39,6 +39,7 @@ import
org.apache.hop.core.gui.plugin.toolbar.GuiToolbarElement;
import org.apache.hop.core.logging.LogChannel;
import org.apache.hop.core.plugins.IPlugin;
import org.apache.hop.core.plugins.PluginRegistry;
+import org.apache.hop.core.search.ISearchResult;
import org.apache.hop.core.search.ISearchable;
import org.apache.hop.core.util.TranslateUtil;
import org.apache.hop.core.util.Utils;
@@ -92,6 +93,7 @@ import org.apache.hop.ui.hopgui.perspective.TabCloseHandler;
import org.apache.hop.ui.hopgui.perspective.TabItemHandler;
import org.apache.hop.ui.hopgui.perspective.TabItemReorder;
import org.apache.hop.ui.hopgui.perspective.explorer.ExplorerPerspective;
+import org.apache.hop.ui.hopgui.search.ReferenceSearchResults;
import org.apache.hop.ui.hopgui.shared.SashFormMemory;
import org.apache.hop.ui.pipeline.transform.BaseTransformDialog;
import org.apache.hop.ui.util.HelpUtils;
@@ -448,6 +450,13 @@ public class MetadataPerspective implements
IHopPerspective, TabClosable, IMetad
menuItem.setImage(GuiResource.getInstance().getImageDuplicate());
menuItem.addListener(SWT.Selection, e -> duplicateMetadata());
+ menuItem = new MenuItem(menu, SWT.POP_UP);
+ menuItem.setText(
+ BaseMessages.getString(PKG,
"MetadataPerspective.Menu.FindReferences"));
+ menuItem.setImage(
+ GuiResource.getInstance().getImage("ui/images/search.svg",
16, 16));
+ menuItem.addListener(SWT.Selection, e -> onFindReferences());
+
new MenuItem(menu, SWT.SEPARATOR);
menuItem = new MenuItem(menu, SWT.POP_UP);
@@ -926,6 +935,65 @@ public class MetadataPerspective implements
IHopPerspective, TabClosable, IMetad
return new String[] {key.toString(), name};
}
+ /** Context-menu handler: find where the selected metadata item is
referenced. */
+ private void onFindReferences() {
+ String[] keyAndName = getSelectedMetadataKeyAndName();
+ if (keyAndName == null) {
+ return;
+ }
+ findReferences(keyAndName[0], keyAndName[1]);
+ }
+
+ /**
+ * Best-effort static scan (same engine as rename) for pipelines/workflows
and metadata objects
+ * that reference the given metadata element by name. Results are shown in
the shared
+ * search-results UI, in a bottom-dock tab, so each one can be opened by
double-clicking it.
+ */
+ private void findReferences(String metadataKey, String name) {
+ String projectHome = hopGui.getVariables().resolve(Const.VAR_PROJECT_HOME);
+ if (Utils.isEmpty(projectHome) ||
Const.VAR_PROJECT_HOME.equals(projectHome)) {
+ // Without an active project there is nothing to scan.
+ showNoReferencesFound(name);
+ return;
+ }
+ List<String> searchRoots =
java.util.Collections.singletonList(projectHome);
+ try {
+ MetadataReferenceFinder finder = new
MetadataReferenceFinder(hopGui.getMetadataProvider());
+ List<MetadataReferenceResult> fileReferences =
+ finder.findReferences(metadataKey, name, searchRoots);
+ List<MetadataObjectReference> metadataReferences =
+ finder.findReferencesInMetadata(metadataKey, name);
+
+ List<ISearchResult> results =
+ ReferenceSearchResults.build(hopGui, fileReferences,
metadataReferences);
+ if (results.isEmpty()) {
+ showNoReferencesFound(name);
+ return;
+ }
+ ReferenceSearchResults.showInBottomDock(
+ hopGui,
+ BaseMessages.getString(PKG,
"MetadataPerspective.FindReferences.Tab.Title", name),
+ name,
+ results);
+ } catch (HopException e) {
+ new ErrorDialog(
+ getShell(),
+ BaseMessages.getString(PKG,
"MetadataPerspective.FindReferences.Error.Title"),
+ BaseMessages.getString(PKG,
"MetadataPerspective.FindReferences.Error.Message", name),
+ e);
+ }
+ }
+
+ private void showNoReferencesFound(String name) {
+ MessageBox box = new MessageBox(getShell(), SWT.ICON_INFORMATION | SWT.OK);
+ box.setText(
+ BaseMessages.getString(PKG,
"MetadataPerspective.FindReferences.NoReferences.Title"));
+ box.setMessage(
+ BaseMessages.getString(
+ PKG, "MetadataPerspective.FindReferences.NoReferences.Message",
name));
+ box.open();
+ }
+
/**
* Append context-menu items contributed by plugins (annotated with {@link
* org.apache.hop.core.gui.plugin.menu.GuiMenuElement} under {@link
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/search/HopGuiSearchResultsPanel.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/search/HopGuiSearchResultsPanel.java
index f97d8552e8..eb2bf4ddb4 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/search/HopGuiSearchResultsPanel.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/search/HopGuiSearchResultsPanel.java
@@ -18,6 +18,7 @@
package org.apache.hop.ui.hopgui.search;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.hop.core.Const;
@@ -107,6 +108,12 @@ public class HopGuiSearchResultsPanel extends Composite {
private final Runnable searchRunnable = () -> search(new Event());
+ /**
+ * When true, programmatic changes to the search field (e.g. showing a
reference label) must not
+ * trigger the debounced text search that would otherwise clobber injected
results.
+ */
+ private boolean suppressAutoSearch;
+
public HopGuiSearchResultsPanel(Composite parent, HopGui hopGui) {
super(parent, SWT.NONE);
this.hopGui = hopGui;
@@ -310,7 +317,7 @@ public class HopGuiSearchResultsPanel extends Composite {
}
private void scheduleSearch() {
- if (isDisposed()) {
+ if (isDisposed() || suppressAutoSearch) {
return;
}
getDisplay().timerExec(-1, searchRunnable);
@@ -451,18 +458,46 @@ public class HopGuiSearchResultsPanel extends Composite {
hopGui.getLog().logError("Error while searching", e);
results = new ArrayList<>();
}
- populateTree(results);
+ populateTree(results, cachedEnumeration.getSourceByKey());
+ }
+
+ /**
+ * Show a pre-computed set of results (e.g. "find references") without
running a text search. The
+ * search field is set to {@code targetLabel} for context only; typing a new
query afterwards
+ * turns this back into a normal search tab.
+ *
+ * @param targetLabel a label describing what the results relate to (shown
in the search field)
+ * @param results the results to display; all are grouped under the Project
section
+ */
+ public void showReferenceResults(String targetLabel, List<ISearchResult>
results) {
+ if (wTree == null || wTree.isDisposed()) {
+ return;
+ }
+ suppressAutoSearch = true;
+ try {
+ if (wSearchString != null && !wSearchString.isDisposed()) {
+ wSearchString.setText(Const.NVL(targetLabel, ""));
+ }
+ } finally {
+ suppressAutoSearch = false;
+ }
+ wTree.removeAll();
+ clearDetails();
+ wbOpen.setEnabled(false);
+ // Reference results have no enumeration behind them: an empty source map
puts them all under
+ // the Project section.
+ populateTree(results, Collections.emptyMap());
}
/**
* Render the two-tier tree: section (Open/Project) -> type -> object -> the
matches inside it.
*/
- private void populateTree(List<ISearchResult> results) {
+ private void populateTree(List<ISearchResult> results, Map<String, Integer>
sourceByKey) {
String searchTerm = wRegEx.getSelection() ? null : wSearchString.getText();
TreeItem firstLeaf = null;
for (HopGuiSearchHelper.SearchSection section :
- HopGuiSearchHelper.groupResults(results,
cachedEnumeration.getSourceByKey())) {
+ HopGuiSearchHelper.groupResults(results, sourceByKey)) {
TreeItem sectionItem = new TreeItem(wTree, SWT.NONE);
sectionItem.setText(
0, sectionLabel(section.getKey()) + " (" + section.getObjectCount()
+ ")");
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/search/ReferenceSearchResults.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/search/ReferenceSearchResults.java
new file mode 100644
index 0000000000..ad422b22d0
--- /dev/null
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/search/ReferenceSearchResults.java
@@ -0,0 +1,172 @@
+/*
+ * 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.ui.hopgui.search;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import org.apache.hop.core.search.ISearchResult;
+import org.apache.hop.core.search.ISearchable;
+import org.apache.hop.core.search.SearchResult;
+import org.apache.hop.metadata.api.IHopMetadata;
+import org.apache.hop.metadata.api.IHopMetadataProvider;
+import org.apache.hop.metadata.api.IHopMetadataSerializer;
+import org.apache.hop.metadata.refactor.MetadataObjectReference;
+import org.apache.hop.metadata.refactor.MetadataReferenceResult;
+import org.apache.hop.pipeline.PipelineMeta;
+import org.apache.hop.ui.core.gui.GuiResource;
+import org.apache.hop.ui.hopgui.HopGui;
+import org.apache.hop.ui.hopgui.terminal.HopGuiBottomDock;
+import org.apache.hop.workflow.WorkflowMeta;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Turns the output of {@link
org.apache.hop.metadata.refactor.MetadataReferenceFinder} into {@link
+ * ISearchResult}s that the shared search-results UI ({@link
HopGuiSearchResultsPanel}) can render
+ * and open. Each referencing pipeline/workflow file or metadata object is
wrapped in the existing
+ * searchable for that object type, so double-clicking a result opens it with
no new open logic.
+ */
+public final class ReferenceSearchResults {
+
+ private static final String EXT_HPL = ".hpl";
+ private static final String EXT_HWF = ".hwf";
+ private static final String LOCATION_PIPELINE = "Project pipeline file";
+ private static final String LOCATION_WORKFLOW = "Project workflow file";
+
+ private ReferenceSearchResults() {}
+
+ /**
+ * Builds openable search results for the given references. Objects that
fail to load (corrupt,
+ * missing plugin, ...) are skipped so the feature stays best-effort.
+ *
+ * @param hopGui the active HopGui (for metadata provider, variables and
logging)
+ * @param fileReferences referencing pipeline/workflow files (from {@code
findFileReferences})
+ * @param metadataReferences referencing metadata objects (from {@code
+ * findFilePathReferencesInMetadata})
+ * @return the search results, in file-first then metadata order
+ */
+ public static List<ISearchResult> build(
+ HopGui hopGui,
+ List<MetadataReferenceResult> fileReferences,
+ List<MetadataObjectReference> metadataReferences) {
+ List<ISearchResult> results = new ArrayList<>();
+ if (fileReferences != null) {
+ for (MetadataReferenceResult fileReference : fileReferences) {
+ ISearchable<?> searchable = toFileSearchable(hopGui,
fileReference.getFilePath());
+ if (searchable != null) {
+ results.add(asObjectResult(searchable));
+ }
+ }
+ }
+ if (metadataReferences != null) {
+ for (MetadataObjectReference reference : metadataReferences) {
+ ISearchable<?> searchable = toMetadataSearchable(hopGui, reference);
+ if (searchable != null) {
+ results.add(asObjectResult(searchable));
+ }
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Opens the given reference results in a bottom-dock tab hosting the shared
search-results panel,
+ * so each result can be opened by double-clicking it. Does nothing when the
dock is unavailable.
+ *
+ * @param hopGui the active HopGui
+ * @param tabTitle the dock tab title
+ * @param label a short label describing what the results relate to (shown
in the search field)
+ * @param results the (non-empty) results to display
+ */
+ public static void showInBottomDock(
+ HopGui hopGui, String tabTitle, String label, List<ISearchResult>
results) {
+ HopGuiBottomDock dock = hopGui.getTerminalPanel();
+ if (dock == null || dock.isDisposed()) {
+ return;
+ }
+ Control content =
+ dock.openToolTab(
+ tabTitle,
+ GuiResource.getInstance().getImage("ui/images/search.svg", 16, 16),
+ true,
+ container -> new HopGuiSearchResultsPanel(container, hopGui));
+ if (content instanceof HopGuiSearchResultsPanel panel) {
+ panel.showReferenceResults(label, results);
+ }
+ }
+
+ /**
+ * A result whose matching string equals the object's name, so the shared
results tree renders it
+ * as a plain object node (no inner field/transform match rows) and no
component is selected on
+ * open.
+ */
+ private static ISearchResult asObjectResult(ISearchable<?> searchable) {
+ return new SearchResult(searchable, searchable.getName(), null, null,
null);
+ }
+
+ private static ISearchable<?> toFileSearchable(HopGui hopGui, String path) {
+ if (path == null) {
+ return null;
+ }
+ String lower = path.toLowerCase(Locale.ROOT);
+ try {
+ if (lower.endsWith(EXT_HPL)) {
+ PipelineMeta pipelineMeta =
+ new PipelineMeta(path, hopGui.getMetadataProvider(),
hopGui.getVariables());
+ return new HopGuiPipelineSearchable(LOCATION_PIPELINE, pipelineMeta);
+ } else if (lower.endsWith(EXT_HWF)) {
+ WorkflowMeta workflowMeta =
+ new WorkflowMeta(hopGui.getVariables(), path,
hopGui.getMetadataProvider());
+ return new HopGuiWorkflowSearchable(LOCATION_WORKFLOW, workflowMeta);
+ }
+ } catch (Exception e) {
+ hopGui.getLog().logBasic("Find references: could not load " + path + ":
" + e.getMessage());
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static ISearchable<?> toMetadataSearchable(
+ HopGui hopGui, MetadataObjectReference reference) {
+ try {
+ IHopMetadataProvider provider = hopGui.getMetadataProvider();
+ Class<? extends IHopMetadata> containerClass =
+ provider.getMetadataClassForKey(reference.getContainerMetadataKey());
+ if (containerClass == null) {
+ return null;
+ }
+ IHopMetadataSerializer<IHopMetadata> serializer =
+ (IHopMetadataSerializer<IHopMetadata>)
provider.getSerializer(containerClass);
+ IHopMetadata object =
serializer.load(reference.getContainerObjectName());
+ if (object == null) {
+ return null;
+ }
+ return new HopGuiMetadataSearchable(
+ provider, serializer, object, (Class<IHopMetadata>) containerClass);
+ } catch (Exception e) {
+ hopGui
+ .getLog()
+ .logBasic(
+ "Find references: could not load metadata object "
+ + reference.getContainerObjectName()
+ + ": "
+ + e.getMessage());
+ return null;
+ }
+ }
+}
diff --git
a/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/explorer/messages/messages_en_US.properties
b/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/explorer/messages/messages_en_US.properties
index a449d125ad..8290f42516 100644
---
a/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/explorer/messages/messages_en_US.properties
+++
b/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/explorer/messages/messages_en_US.properties
@@ -41,6 +41,7 @@ ExplorerPerspective.Menu.CopyName=Copy name
ExplorerPerspective.Menu.CopyPath=Copy path
ExplorerPerspective.Menu.CreateFolder=Create folder
ExplorerPerspective.Menu.Delete=Delete
+ExplorerPerspective.Menu.FindReferences=Find references
ExplorerPerspective.Menu.Open=Open
ExplorerPerspective.Menu.OpenInExplorer=Open in explorer
ExplorerPerspective.Menu.Rename=Rename
@@ -65,6 +66,11 @@ ExplorerPerspective.UpdateFileReferences.Message=Found {0}
reference(s) in {1} p
ExplorerPerspective.UpdateFileReferences.MessageWithMetadata=Found {0}
reference(s) in {1} pipeline/workflow file(s) and {2} metadata object(s).
Update references to the new path(s)?
ExplorerPerspective.UpdateFileReferences.ExperimentalFeatureNote=Note:
Reference detection and replacement is an experimental feature. Not all
transforms and actions may be updated automatically.
ExplorerPerspective.UpdateFileReferences.Button.Details=Details
+ExplorerPerspective.FindReferences.Tab.Title=References: {0}
+ExplorerPerspective.FindReferences.NoReferences.Title=Find references
+ExplorerPerspective.FindReferences.NoReferences.Message=No references to
''{0}'' were found in this project.
+ExplorerPerspective.FindReferences.Error.Title=Error finding references
+ExplorerPerspective.FindReferences.Error.Message=There was an error while
searching for references to ''{0}''.
ExplorerPerspective.UpdateFileReferences.Details.Title=Details
ExplorerPerspective.UpdateFileReferences.Details.Message=Files and metadata
objects that will be modified:
ExplorerPerspective.UpdateFileReferences.Details.MetadataEntry=Metadata ({0}):
{1}
diff --git
a/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/metadata/messages/messages_en_US.properties
b/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/metadata/messages/messages_en_US.properties
index 41f7829dd9..7c30a6ff17 100644
---
a/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/metadata/messages/messages_en_US.properties
+++
b/ui/src/main/resources/org/apache/hop/ui/hopgui/perspective/metadata/messages/messages_en_US.properties
@@ -31,6 +31,7 @@ MetadataPerspective.GuiPlugin.Description=This perspective
allows you to see and
MetadataPerspective.Menu.Delete=Delete\tDelete
MetadataPerspective.Menu.Duplicate=Duplicate
MetadataPerspective.Menu.Edit=Edit\tF3
+MetadataPerspective.Menu.FindReferences=Find references
MetadataPerspective.Menu.Help=Help\tF1
MetadataPerspective.Menu.New=New
MetadataPerspective.Menu.NewFolder=New Folder
@@ -47,6 +48,11 @@ MetadataPerspective.ToolbarElement.New.Tooltip=Create a new
metadata element
MetadataPerspective.ToolbarElement.Refresh.Tooltip=Refresh
MetadataPerspective.ToolbarElement.Rename.Tooltip=Rename
MetadataPerspective.Search.Placeholder=Search metadata...
+MetadataPerspective.FindReferences.Tab.Title=References: {0}
+MetadataPerspective.FindReferences.NoReferences.Title=Find references
+MetadataPerspective.FindReferences.NoReferences.Message=No references to
''{0}'' were found in this project.
+MetadataPerspective.FindReferences.Error.Title=Error finding references
+MetadataPerspective.FindReferences.Error.Message=There was an error while
searching for references to ''{0}''.
MetadataPerspective.RenameMetadata.UpdateReferences.Title=Rename metadata
MetadataPerspective.RenameMetadata.UpdateReferences.Message=Found {0}
reference(s) in {1} file(s). Update references to the new name?
MetadataPerspective.RenameMetadata.UpdateReferences.MessageWithMetadata=Found
{0} reference(s) in {1} pipeline/workflow file(s) and {2} metadata object(s).
Update references to the new name?