diff --git a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ReplaceTextWithMapping.java b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ReplaceTextWithMapping.java index 85dba965e281..9552fefd278c 100644 --- a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ReplaceTextWithMapping.java +++ b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ReplaceTextWithMapping.java @@ -23,10 +23,12 @@ import org.apache.nifi.annotation.behavior.SupportsBatching; import org.apache.nifi.annotation.documentation.CapabilityDescription; import org.apache.nifi.annotation.documentation.Tags; +import org.apache.nifi.annotation.lifecycle.OnScheduled; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.components.ValidationContext; import org.apache.nifi.components.ValidationResult; import org.apache.nifi.components.resource.ResourceCardinality; +import org.apache.nifi.components.resource.ResourceReference; import org.apache.nifi.components.resource.ResourceType; import org.apache.nifi.expression.AttributeValueDecorator; import org.apache.nifi.expression.ExpressionLanguageScope; @@ -45,7 +47,6 @@ import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -68,8 +69,9 @@ @SupportsBatching @InputRequirement(Requirement.INPUT_REQUIRED) @Tags({"Text", "Regular Expression", "Update", "Change", "Replace", "Modify", "Regex", "Mapping"}) -@CapabilityDescription("Updates the content of a FlowFile by evaluating a Regular Expression against it and replacing the section of the content that " - + "matches the Regular Expression with some alternate value provided in a mapping file.") +@CapabilityDescription(""" + Updates the content of a FlowFile by evaluating a Regular Expression against it and replacing the section of the content that + matches the Regular Expression with some alternate value provided in a mapping file.""") public class ReplaceTextWithMapping extends AbstractProcessor { public static final PropertyDescriptor REGEX = new PropertyDescriptor.Builder() @@ -90,13 +92,13 @@ public class ReplaceTextWithMapping extends AbstractProcessor { .build(); public static final PropertyDescriptor MAPPING_FILE = new PropertyDescriptor.Builder() .name("Mapping File") - .description("The name of the file (including the full path) containing the Mappings.") - .identifiesExternalResource(ResourceCardinality.SINGLE, ResourceType.FILE) + .description("The name of the file (including the full path) containing the Mappings or the actual mapping contents.") + .identifiesExternalResource(ResourceCardinality.SINGLE, ResourceType.FILE, ResourceType.TEXT) .required(true) .build(); public static final PropertyDescriptor MAPPING_FILE_REFRESH_INTERVAL = new PropertyDescriptor.Builder() .name("Mapping File Refresh Interval") - .description("The polling interval to check for updates to the mapping file. The default is 60s.") + .description("The polling interval to check for updates to the mapping file only if the mapping file is a file on the filesystem. The default is 60s.") .addValidator(StandardValidators.TIME_PERIOD_VALIDATOR) .required(true) .defaultValue("60s") @@ -176,6 +178,19 @@ public Set getRelationships() { return RELATIONSHIPS; } + @OnScheduled + public void onScheduled(final ProcessContext context) { + final ResourceReference resourceReference = context.getProperty(MAPPING_FILE).asResource(); + if (resourceReference.getResourceType() == ResourceType.TEXT) { + getLogger().info("Loading mapping content"); + try (final InputStream inputStream = resourceReference.read()) { + setConfigurationState(inputStream); + } catch (IOException ioe) { + getLogger().error("Error reading mapping content", ioe); + } + } + } + @Override public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException { updateMapping(context); @@ -214,7 +229,7 @@ protected String fillReplacementValueBackReferences(String rawReplacementValue, final StringBuilder sb = new StringBuilder(replacement.length() + 1); final int groupStart = backRefMatcher.start(1) + replacementCount++; - sb.append(replacement.substring(0, groupStart - 1)); + sb.append(replacement, 0, groupStart - 1); sb.append("\\"); sb.append(replacement.substring(groupStart - 1)); replacement = sb.toString(); @@ -227,49 +242,56 @@ protected String fillReplacementValueBackReferences(String rawReplacementValue, } private void updateMapping(final ProcessContext context) { - if (processorLock.tryLock()) { - final ComponentLog logger = getLogger(); - try { - // if not queried mapping file lastUpdate time in - // mapppingRefreshPeriodSecs, do so. - long currentTimeSecs = System.currentTimeMillis() / 1000; - long mappingRefreshPeriodSecs = context.getProperty(MAPPING_FILE_REFRESH_INTERVAL).asTimePeriod(TimeUnit.SECONDS); - - boolean retry = (currentTimeSecs > (mappingTestTime.get() + mappingRefreshPeriodSecs)); - if (retry) { - mappingTestTime.set(System.currentTimeMillis() / 1000); - // see if the mapping file needs to be reloaded - final String fileName = context.getProperty(MAPPING_FILE).getValue(); - final File file = new File(fileName); - if (file.exists() && file.isFile() && file.canRead()) { - if (file.lastModified() > lastModified.get()) { - lastModified.getAndSet(file.lastModified()); - try (FileInputStream is = new FileInputStream(file)) { - logger.info("Reloading mapping file: {}", fileName); - - final Map mapping = loadMappingFile(is); - final ConfigurationState newState = new ConfigurationState(mapping); - configurationStateRef.set(newState); - } catch (IOException e) { - logger.error("Error reading mapping file", e); + final ResourceReference resourceReference = context.getProperty(MAPPING_FILE).asResource(); + + if (resourceReference.getResourceType() == ResourceType.FILE) { + if (processorLock.tryLock()) { + final ComponentLog logger = getLogger(); + try { + // if not queried mapping file lastUpdate time in + // mappingRefreshPeriodSecs, do so. + final long currentTimeSecs = System.currentTimeMillis() / 1000; + final long mappingRefreshPeriodSecs = context.getProperty(MAPPING_FILE_REFRESH_INTERVAL).asTimePeriod(TimeUnit.SECONDS); + + final boolean retry = (currentTimeSecs > (mappingTestTime.get() + mappingRefreshPeriodSecs)); + if (retry) { + mappingTestTime.set(System.currentTimeMillis() / 1000); + // see if the mapping file needs to be reloaded + final File file = resourceReference.asFile(); + final String fileName = file.getName(); + if (file.exists() && file.isFile() && file.canRead()) { + if (file.lastModified() > lastModified.get()) { + lastModified.getAndSet(file.lastModified()); + try (InputStream is = resourceReference.read()) { + logger.info("Reloading mapping file: {}", fileName); + setConfigurationState(is); + } catch (IOException e) { + logger.error("Error reading mapping file", e); + } } + } else { + logger.error("Mapping file does not exist or is not readable: {}", fileName); } - } else { - logger.error("Mapping file does not exist or is not readable: {}", fileName); } + } catch (Exception e) { + logger.error("Error loading mapping file", e); + } finally { + processorLock.unlock(); } - } catch (Exception e) { - logger.error("Error loading mapping file", e); - } finally { - processorLock.unlock(); } } } + private void setConfigurationState(InputStream inputStream) throws IOException { + final Map mapping = loadMappingFile(inputStream); + final ConfigurationState newState = new ConfigurationState(mapping); + configurationStateRef.set(newState); + } + protected Map loadMappingFile(InputStream is) throws IOException { Map mapping = new HashMap<>(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - String line = null; + String line; while ((line = reader.readLine()) != null) { final String[] splits = StringUtils.split(line, "\t ", 2); if (splits.length == 1) { @@ -311,14 +333,8 @@ private final class ReplaceTextCallback implements StreamCallback { private final int numCapturingGroups; private final int groupToMatch; - private final AttributeValueDecorator quotedAttributeDecorator = new AttributeValueDecorator() { - @Override - public String decorate(final String attributeValue) { - return Pattern.quote(attributeValue); - } - }; - private ReplaceTextCallback(ProcessContext context, FlowFile flowFile, int maxBufferSize) { + AttributeValueDecorator quotedAttributeDecorator = Pattern::quote; this.regex = context.getProperty(REGEX).evaluateAttributeExpressions(flowFile, quotedAttributeDecorator).getValue(); this.flowFile = flowFile; @@ -348,7 +364,7 @@ public void process(final InputStream in, final OutputStream out) throws IOExcep matcher.reset(); boolean result = matcher.find(); if (result) { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); do { String matched = matcher.group(groupToMatch); String rv = mapping.get(matched); diff --git a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestReplaceTextWithMapping.java b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestReplaceTextWithMapping.java index cd53cda477b9..de17c4611da7 100644 --- a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestReplaceTextWithMapping.java +++ b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestReplaceTextWithMapping.java @@ -19,7 +19,11 @@ import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import java.io.IOException; import java.nio.file.Files; @@ -27,14 +31,17 @@ import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; public class TestReplaceTextWithMapping { + private TestRunner runner; - public TestRunner getRunner() { - TestRunner runner = TestRunners.newTestRunner(ReplaceTextWithMapping.class); + @BeforeEach + public void setUp() { + runner = TestRunners.newTestRunner(ReplaceTextWithMapping.class); /* * we have to disable validation of expression language because the processor will @@ -42,32 +49,37 @@ public TestRunner getRunner() { * the test will throw an error about the evaluation scope */ runner.setValidateExpressionUsage(false); - - return runner; } - @Test - public void testSimple() throws IOException { - final TestRunner runner = getRunner(); - final String mappingFile = Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-mapping.txt").toFile().getAbsolutePath(); + @ParameterizedTest + @MethodSource("simpleTestArgs") + public void testSimple(String mappingFile) throws IOException { runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, mappingFile); runner.enqueue(Paths.get("src/test/resources/TestReplaceTextWithMapping/colors-without-dashes.txt")); runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "roses are apple\n" - + "violets are blueberry\n" - + "something else is grape\n" - + "I'm not good at writing poems"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = """ + roses are apple + violets are blueberry + something else is grape + I'm not good at writing poems"""; assertEquals(expected, outputString); } + private static Stream simpleTestArgs() throws IOException { + final Path mappingFile = Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-mapping.txt"); + return Stream.of( + Arguments.argumentSet("File path", mappingFile.toFile().getAbsolutePath()), + Arguments.argumentSet("File contents", Files.readString(mappingFile)) + ); + } + @Test - public void testExpressionLanguageInText() throws IOException { - final TestRunner runner = getRunner(); + public void testExpressionLanguageInText() { final String mappingFile = Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-mapping.txt").toFile().getAbsolutePath(); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, mappingFile); @@ -77,15 +89,14 @@ public void testExpressionLanguageInText() throws IOException { runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "${foo} apple ${baz}"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = "${foo} apple ${baz}"; assertEquals(expected, outputString); } @Test - public void testExpressionLanguageInText2() throws IOException { - final TestRunner runner = getRunner(); + public void testExpressionLanguageInText2() { final String mappingFile = Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-mapping.txt").toFile().getAbsolutePath(); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, mappingFile); runner.setProperty(ReplaceTextWithMapping.REGEX, "\\|(.*?)\\|"); @@ -97,15 +108,14 @@ public void testExpressionLanguageInText2() throws IOException { runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "${foo}|apple|${baz}"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = "${foo}|apple|${baz}"; assertEquals(expected, outputString); } @Test - public void testExpressionLanguageInText3() throws IOException { - final TestRunner runner = getRunner(); + public void testExpressionLanguageInText3() { final String mappingFile = Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-mapping.txt").toFile().getAbsolutePath(); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, mappingFile); runner.setProperty(ReplaceTextWithMapping.REGEX, ".*\\|(.*?)\\|.*"); @@ -117,15 +127,14 @@ public void testExpressionLanguageInText3() throws IOException { runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "${foo}|apple|${baz}"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = "${foo}|apple|${baz}"; assertEquals(expected, outputString); } @Test public void testWithMatchingGroupAndContext() throws IOException { - final TestRunner runner = getRunner(); runner.setProperty(ReplaceTextWithMapping.REGEX, "-(.*?)-"); runner.setProperty(ReplaceTextWithMapping.MATCHING_GROUP_FOR_LOOKUP_KEY, "1"); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-mapping.txt").toFile().getAbsolutePath()); @@ -134,18 +143,18 @@ public void testWithMatchingGroupAndContext() throws IOException { runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "-roses- are -apple-\n" - + "violets are -blueberry-\n" - + "something else is -grape-\n" - + "I'm not good at writing poems"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = """ + -roses- are -apple- + violets are -blueberry- + something else is -grape- + I'm not good at writing poems"""; assertEquals(expected, outputString); } @Test public void testBackReference() throws IOException { - final TestRunner runner = getRunner(); runner.setProperty(ReplaceTextWithMapping.REGEX, "(\\S+)"); runner.setProperty(ReplaceTextWithMapping.MATCHING_GROUP_FOR_LOOKUP_KEY, "1"); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-backreference-mapping.txt").toFile().getAbsolutePath()); @@ -154,25 +163,25 @@ public void testBackReference() throws IOException { runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "roses are red apple\n" - + "violets are blue blueberry\n" - + "something else is green grape\n" - + "I'm not good at writing poems"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = """ + roses are red apple + violets are blue blueberry + something else is green grape + I'm not good at writing poems"""; assertEquals(expected, outputString); } @Test public void testRoutesToFailureIfTooLarge() throws IOException { - final TestRunner runner = getRunner(); runner.setProperty(ReplaceTextWithMapping.REGEX, "[123]"); runner.setProperty(ReplaceTextWithMapping.MAX_BUFFER_SIZE, "1 b"); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-mapping.txt").toFile().getAbsolutePath()); final Map attributes = new HashMap<>(); attributes.put("abc", "Good"); - runner.enqueue(Paths.get("src/test/resources/TestReplaceTextWithMapping/colors.txt")); + runner.enqueue(Paths.get("src/test/resources/TestReplaceTextWithMapping/colors.txt"), attributes); runner.run(); @@ -181,7 +190,6 @@ public void testRoutesToFailureIfTooLarge() throws IOException { @Test public void testBackReferenceWithTooLargeOfIndexIsEscaped() throws IOException { - final TestRunner runner = getRunner(); runner.setProperty(ReplaceTextWithMapping.REGEX, "-(.*?)-"); runner.setProperty(ReplaceTextWithMapping.MATCHING_GROUP_FOR_LOOKUP_KEY, "1"); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-excessive-backreference-mapping.txt").toFile().getAbsolutePath()); @@ -190,18 +198,18 @@ public void testBackReferenceWithTooLargeOfIndexIsEscaped() throws IOException { runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "-roses- are -red$2 apple-\n" - + "violets are -blue$2 blueberry-\n" - + "something else is -green$2 grape-\n" - + "I'm not good at writing poems"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = """ + -roses- are -red$2 apple- + violets are -blue$2 blueberry- + something else is -green$2 grape- + I'm not good at writing poems"""; assertEquals(expected, outputString); } @Test public void testBackReferenceWithTooLargeOfIndexIsEscapedSimple() throws IOException { - final TestRunner runner = getRunner(); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-excessive-backreference-mapping-simple.txt").toFile().getAbsolutePath()); @@ -209,18 +217,18 @@ public void testBackReferenceWithTooLargeOfIndexIsEscapedSimple() throws IOExcep runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "roses are red$1 apple\n" - + "violets are blue$1 blueberry\n" - + "something else is green$1 grape\n" - + "I'm not good at writing poems"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = """ + roses are red$1 apple + violets are blue$1 blueberry + something else is green$1 grape + I'm not good at writing poems"""; assertEquals(expected, outputString); } @Test public void testBackReferenceWithInvalidReferenceIsEscaped() throws IOException { - final TestRunner runner = getRunner(); runner.setProperty(ReplaceTextWithMapping.REGEX, "(\\S+)"); runner.setProperty(ReplaceTextWithMapping.MATCHING_GROUP_FOR_LOOKUP_KEY, "1"); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-invalid-backreference-mapping.txt").toFile().getAbsolutePath()); @@ -229,18 +237,18 @@ public void testBackReferenceWithInvalidReferenceIsEscaped() throws IOException runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "roses are red$d apple\n" - + "violets are blue$d blueberry\n" - + "something else is green$d grape\n" - + "I'm not good at writing poems"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = """ + roses are red$d apple + violets are blue$d blueberry + something else is green$d grape + I'm not good at writing poems"""; assertEquals(expected, outputString); } @Test public void testEscapingDollarSign() throws IOException { - final TestRunner runner = getRunner(); runner.setProperty(ReplaceTextWithMapping.REGEX, "-(.*?)-"); runner.setProperty(ReplaceTextWithMapping.MATCHING_GROUP_FOR_LOOKUP_KEY, "1"); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-escaped-dollar-mapping.txt").toFile().getAbsolutePath()); @@ -249,72 +257,72 @@ public void testEscapingDollarSign() throws IOException { runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "-roses- are -$1 apple-\n" - + "violets are -$1 blueberry-\n" - + "something else is -$1 grape-\n" - + "I'm not good at writing poems"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = """ + -roses- are -$1 apple- + violets are -$1 blueberry- + something else is -$1 grape- + I'm not good at writing poems"""; assertEquals(expected, outputString); } @Test public void testEscapingDollarSignSimple() throws IOException { - final TestRunner runner = getRunner(); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-escaped-dollar-mapping.txt").toFile().getAbsolutePath()); runner.enqueue(Paths.get("src/test/resources/TestReplaceTextWithMapping/colors-without-dashes.txt")); runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "roses are $1 apple\n" - + "violets are $1 blueberry\n" - + "something else is $1 grape\n" - + "I'm not good at writing poems"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = """ + roses are $1 apple + violets are $1 blueberry + something else is $1 grape + I'm not good at writing poems"""; assertEquals(expected, outputString); } @Test public void testReplaceWithEmptyString() throws IOException { - final TestRunner runner = getRunner(); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-blank-mapping.txt").toFile().getAbsolutePath()); runner.enqueue(Paths.get("src/test/resources/TestReplaceTextWithMapping/colors-without-dashes.txt")); runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "roses are \n" - + "violets are \n" - + "something else is \n" - + "I'm not good at writing poems"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = """ + roses are\s + violets are\s + something else is\s + I'm not good at writing poems"""; assertEquals(expected, outputString); } @Test public void testReplaceWithSpaceInString() throws IOException { - final TestRunner runner = getRunner(); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-space-mapping.txt").toFile().getAbsolutePath()); runner.enqueue(Paths.get("src/test/resources/TestReplaceTextWithMapping/colors-without-dashes.txt")); runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = "roses are really red\n" - + "violets are super blue\n" - + "something else is ultra green\n" - + "I'm not good at writing poems"; + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + String expected = """ + roses are really red + violets are super blue + something else is ultra green + I'm not good at writing poems"""; assertEquals(expected, outputString); } @Test public void testWithNoMatch() throws IOException { - final TestRunner runner = getRunner(); runner.setProperty(ReplaceTextWithMapping.REGEX, "-(.*?)-"); runner.setProperty(ReplaceTextWithMapping.MATCHING_GROUP_FOR_LOOKUP_KEY, "1"); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, Paths.get("src/test/resources/TestReplaceTextWithMapping/color-fruit-no-match-mapping.txt").toFile().getAbsolutePath()); @@ -324,24 +332,20 @@ public void testWithNoMatch() throws IOException { runner.run(); runner.assertAllFlowFilesTransferred(ReplaceTextWithMapping.REL_SUCCESS, 1); - final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).get(0); - String outputString = new String(out.toByteArray()); - String expected = new String(Files.readAllBytes(path)); + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceTextWithMapping.REL_SUCCESS).getFirst(); + final String outputString = out.getContent(); + final String expected = Files.readString(path); assertEquals(expected, outputString); } @Test public void testMatchingGroupForLookupKeyTooLarge() throws IOException { - final TestRunner runner = getRunner(); runner.setProperty(ReplaceTextWithMapping.REGEX, "-(.*?)-"); runner.setProperty(ReplaceTextWithMapping.MATCHING_GROUP_FOR_LOOKUP_KEY, "2"); runner.setProperty(ReplaceTextWithMapping.MAPPING_FILE, Paths.get("src/test/resources/TestReplaceTextWithMapping/color-mapping.txt").toFile().getAbsolutePath()); final Path path = Paths.get("src/test/resources/TestReplaceTextWithMapping/colors.txt"); runner.enqueue(path); - assertThrows(AssertionError.class, () -> { - runner.run(); - }); + assertThrows(AssertionError.class, runner::run); } - }