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 41a36eb3c1 Fix Check for Delete and Copy/Move result filenames (#8939)
41a36eb3c1 is described below
commit 41a36eb3c1e4aca3c1119a9d5fc0fdc6a3764788
Author: Lance <[email protected]>
AuthorDate: Thu Oct 15 23:03:37 2026 +0800
Fix Check for Delete and Copy/Move result filenames (#8939)
Signed-off-by: leehaut <[email protected]>
---
.../ActionCopyMoveResultFilenames.java | 28 +++++----
.../ActionCopyMoveResultFilenamesTest.java | 69 ++++++++++++++++++++++
.../ActionDeleteResultFilenames.java | 20 ++-----
.../ActionDeleteResultFilenamesTest.java | 15 +++++
4 files changed, 104 insertions(+), 28 deletions(-)
diff --git
a/plugins/actions/copymoveresultfilenames/src/main/java/org/apache/hop/workflow/actions/copymoveresultfilenames/ActionCopyMoveResultFilenames.java
b/plugins/actions/copymoveresultfilenames/src/main/java/org/apache/hop/workflow/actions/copymoveresultfilenames/ActionCopyMoveResultFilenames.java
index 0200572e8e..ed698fbd92 100644
---
a/plugins/actions/copymoveresultfilenames/src/main/java/org/apache/hop/workflow/actions/copymoveresultfilenames/ActionCopyMoveResultFilenames.java
+++
b/plugins/actions/copymoveresultfilenames/src/main/java/org/apache/hop/workflow/actions/copymoveresultfilenames/ActionCopyMoveResultFilenames.java
@@ -43,16 +43,17 @@ import org.apache.hop.metadata.api.IHopMetadataProvider;
import org.apache.hop.workflow.WorkflowMeta;
import org.apache.hop.workflow.action.ActionBase;
import org.apache.hop.workflow.action.IAction;
-import org.apache.hop.workflow.action.validator.AbstractFileValidator;
import org.apache.hop.workflow.action.validator.ActionValidatorUtils;
import org.apache.hop.workflow.action.validator.AndValidator;
-import org.apache.hop.workflow.action.validator.ValidatorContext;
import org.apache.hop.workflow.engine.IWorkflowEngine;
/**
- * This defines a 'copymoveresultfilenames' action. Its main use would be to
copy or move files in
- * the result filenames to a destination folder. that can be used to control
the flow in ETL cycles.
+ * This defines a 'copy move result filenames' action. Its main use would be
to copy or move files
+ * in the result filenames to a destination folder. that can be used to
control the flow in ETL
+ * cycles.
*/
+@Getter
+@Setter
@Action(
id = "COPY_MOVE_RESULT_FILENAMES",
name = "i18n::ActionCopyMoveResultFilenames.Name",
@@ -61,8 +62,6 @@ import org.apache.hop.workflow.engine.IWorkflowEngine;
categoryDescription =
"i18n:org.apache.hop.workflow:ActionCategory.Category.FileManagement",
keywords = "i18n::ActionCopyMoveResultFilenames.keyword",
documentationUrl = "/workflow/actions/processresultfilenames.html")
-@Getter
-@Setter
public class ActionCopyMoveResultFilenames extends ActionBase implements
Cloneable, IAction {
private static final Class<?> PKG = ActionCopyMoveResultFilenames.class;
public static final String SUCCESS_IF_AT_LEAST_X_FILES =
"success_when_at_least";
@@ -488,12 +487,15 @@ public class ActionCopyMoveResultFilenames extends
ActionBase implements Cloneab
WorkflowMeta workflowMeta,
IVariables variables,
IHopMetadataProvider metadataProvider) {
- ValidatorContext ctx = new ValidatorContext();
- AbstractFileValidator.putVariableSpace(ctx, getVariables());
- AndValidator.putValidators(
- ctx,
- ActionValidatorUtils.notNullValidator(),
- ActionValidatorUtils.fileDoesNotExistValidator());
- ActionValidatorUtils.andValidator().validate(this, "filename", remarks,
ctx);
+ // Delete only drops names from the result. Copy and move need a
destination folder.
+ if (getAction() == ActionType.DELETE) {
+ return;
+ }
+ ActionValidatorUtils.andValidator()
+ .validate(
+ this,
+ "destinationFolder",
+ remarks,
+
AndValidator.putValidators(ActionValidatorUtils.notBlankValidator()));
}
}
diff --git
a/plugins/actions/copymoveresultfilenames/src/test/java/org/apache/hop/workflow/actions/copymoveresultfilenames/ActionCopyMoveResultFilenamesTest.java
b/plugins/actions/copymoveresultfilenames/src/test/java/org/apache/hop/workflow/actions/copymoveresultfilenames/ActionCopyMoveResultFilenamesTest.java
index c023653d8b..6d5b1f3ac6 100644
---
a/plugins/actions/copymoveresultfilenames/src/test/java/org/apache/hop/workflow/actions/copymoveresultfilenames/ActionCopyMoveResultFilenamesTest.java
+++
b/plugins/actions/copymoveresultfilenames/src/test/java/org/apache/hop/workflow/actions/copymoveresultfilenames/ActionCopyMoveResultFilenamesTest.java
@@ -19,12 +19,18 @@
package org.apache.hop.workflow.actions.copymoveresultfilenames;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.hop.core.ICheckResult;
import org.apache.hop.workflow.action.ActionSerializationTestUtil;
import org.junit.jupiter.api.Test;
+/** Unit test for {@link ActionCopyMoveResultFilenames} */
class ActionCopyMoveResultFilenamesTest {
+
@Test
void testSerializationRoundTrip() throws Exception {
ActionCopyMoveResultFilenames action =
@@ -49,4 +55,67 @@ class ActionCopyMoveResultFilenamesTest {
assertTrue(action.isRemovedSourceFilename());
assertTrue(action.isAddDestinationFilename());
}
+
+ @Test
+ void checkRequiresDestinationFolderWhenCopying() {
+ ActionCopyMoveResultFilenames action = new ActionCopyMoveResultFilenames();
+ action.setAction(ActionCopyMoveResultFilenames.ActionType.COPY);
+
+ List<String> errors = errors(check(action));
+
+ assertEquals(1, errors.size());
+ assertTrue(errors.getFirst().contains("destinationFolder cannot be null or
blank"));
+ assertFalse(errors.getFirst().contains("filename"));
+ }
+
+ @Test
+ void checkRequiresDestinationFolderWhenMoving() {
+ ActionCopyMoveResultFilenames action = new ActionCopyMoveResultFilenames();
+ action.setAction(ActionCopyMoveResultFilenames.ActionType.MOVE);
+
+ List<String> errors = errors(check(action));
+
+ assertEquals(1, errors.size());
+ assertTrue(errors.getFirst().contains("destinationFolder cannot be null or
blank"));
+ }
+
+ @Test
+ void checkAcceptsADestinationFolder() {
+ ActionCopyMoveResultFilenames action = new ActionCopyMoveResultFilenames();
+ action.setAction(ActionCopyMoveResultFilenames.ActionType.COPY);
+ action.setDestinationFolder("/tmp/hop-result");
+
+ List<ICheckResult> remarks = check(action);
+
+ assertTrue(errors(remarks).isEmpty());
+ assertTrue(
+ remarks.stream().anyMatch(remark ->
remark.getText().contains("destinationFolder is OK")));
+ assertTrue(remarks.stream().noneMatch(remark ->
remark.getText().contains("filename")));
+ }
+
+ @Test
+ void checkSkipsDestinationFolderWhenDeleting() {
+ ActionCopyMoveResultFilenames action = new ActionCopyMoveResultFilenames();
+ action.setAction(ActionCopyMoveResultFilenames.ActionType.DELETE);
+
+ List<ICheckResult> remarks = check(action);
+
+ assertTrue(remarks.isEmpty());
+ }
+
+ private static List<ICheckResult> check(ActionCopyMoveResultFilenames
action) {
+ List<ICheckResult> remarks = new ArrayList<>();
+ action.check(remarks, null, action, null);
+ return remarks;
+ }
+
+ private static List<String> errors(List<ICheckResult> remarks) {
+ List<String> errors = new ArrayList<>();
+ for (ICheckResult remark : remarks) {
+ if (remark.getType() == ICheckResult.TYPE_RESULT_ERROR) {
+ errors.add(remark.getText());
+ }
+ }
+ return errors;
+ }
}
diff --git
a/plugins/actions/deleteresultfilenames/src/main/java/org/apache/hop/workflow/actions/deleteresultfilenames/ActionDeleteResultFilenames.java
b/plugins/actions/deleteresultfilenames/src/main/java/org/apache/hop/workflow/actions/deleteresultfilenames/ActionDeleteResultFilenames.java
index c9a470880a..23c15187ae 100644
---
a/plugins/actions/deleteresultfilenames/src/main/java/org/apache/hop/workflow/actions/deleteresultfilenames/ActionDeleteResultFilenames.java
+++
b/plugins/actions/deleteresultfilenames/src/main/java/org/apache/hop/workflow/actions/deleteresultfilenames/ActionDeleteResultFilenames.java
@@ -36,15 +36,13 @@ import org.apache.hop.metadata.api.IHopMetadataProvider;
import org.apache.hop.workflow.WorkflowMeta;
import org.apache.hop.workflow.action.ActionBase;
import org.apache.hop.workflow.action.IAction;
-import org.apache.hop.workflow.action.validator.AbstractFileValidator;
-import org.apache.hop.workflow.action.validator.ActionValidatorUtils;
-import org.apache.hop.workflow.action.validator.AndValidator;
-import org.apache.hop.workflow.action.validator.ValidatorContext;
/**
- * This defines a 'deleteresultfilenames' action. Its main use would be to
create empty folder that
- * can be used to control the flow in ETL cycles.
+ * This defines a 'delete result filenames' action. Its main use would be to
create empty folder
+ * that can be used to control the flow in ETL cycles.
*/
+@Getter
+@Setter
@Action(
id = "DELETE_RESULT_FILENAMES",
name = "i18n::ActionDeleteResultFilenames.Name",
@@ -53,8 +51,6 @@ import
org.apache.hop.workflow.action.validator.ValidatorContext;
categoryDescription =
"i18n:org.apache.hop.workflow:ActionCategory.Category.FileManagement",
keywords = "i18n::ActionDeleteResultFilenames.keyword",
documentationUrl = "/workflow/actions/deleteresultfilenames.html")
-@Getter
-@Setter
public class ActionDeleteResultFilenames extends ActionBase implements
Cloneable, IAction {
private static final Class<?> PKG = ActionDeleteResultFilenames.class;
@@ -156,12 +152,6 @@ public class ActionDeleteResultFilenames extends
ActionBase implements Cloneable
WorkflowMeta workflowMeta,
IVariables variables,
IHopMetadataProvider metadataProvider) {
- ValidatorContext ctx = new ValidatorContext();
- AbstractFileValidator.putVariableSpace(ctx, getVariables());
- AndValidator.putValidators(
- ctx,
- ActionValidatorUtils.notNullValidator(),
- ActionValidatorUtils.fileDoesNotExistValidator());
- ActionValidatorUtils.andValidator().validate(this, "filename", remarks,
ctx);
+ // Names come from the previous result. This action has no path of its own
to validate.
}
}
diff --git
a/plugins/actions/deleteresultfilenames/src/test/java/org/apache/hop/workflow/actions/deleteresultfilenames/ActionDeleteResultFilenamesTest.java
b/plugins/actions/deleteresultfilenames/src/test/java/org/apache/hop/workflow/actions/deleteresultfilenames/ActionDeleteResultFilenamesTest.java
index 5b1d8ef816..7876b91d5f 100644
---
a/plugins/actions/deleteresultfilenames/src/test/java/org/apache/hop/workflow/actions/deleteresultfilenames/ActionDeleteResultFilenamesTest.java
+++
b/plugins/actions/deleteresultfilenames/src/test/java/org/apache/hop/workflow/actions/deleteresultfilenames/ActionDeleteResultFilenamesTest.java
@@ -20,10 +20,15 @@ package
org.apache.hop.workflow.actions.deleteresultfilenames;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.hop.core.ICheckResult;
import org.apache.hop.workflow.action.ActionSerializationTestUtil;
import org.junit.jupiter.api.Test;
+/** Unit test for {@link ActionDeleteResultFilenames} */
class ActionDeleteResultFilenamesTest {
+
@Test
void testSerializationRoundTrip() throws Exception {
ActionDeleteResultFilenames action =
@@ -34,4 +39,14 @@ class ActionDeleteResultFilenamesTest {
assertEquals("wildcard", action.getWildcard());
assertEquals("exclude", action.getWildcardExclude());
}
+
+ @Test
+ void checkDoesNotReportAMissingFilename() {
+ ActionDeleteResultFilenames action = new ActionDeleteResultFilenames();
+ List<ICheckResult> remarks = new ArrayList<>();
+
+ action.check(remarks, null, action, null);
+
+ assertTrue(remarks.isEmpty());
+ }
}