/*! ******************************************************************************
 *
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2019 by Hitachi Vantara : http://www.pentaho.com
 *
 *******************************************************************************
 *
 * Licensed 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.pentaho.di.trans.steps.replacestring;

import org.apache.commons.lang.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.pentaho.di.core.logging.LoggingObjectInterface;
import org.pentaho.di.core.row.RowMeta;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.value.ValueMetaString;
import org.pentaho.di.trans.steps.mock.StepMockHelper;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
 * <p>There're four (4) main properties that affect the way the <code>processRow</code> method of {@link ReplaceString}
 * works; as so, there're plenty combinations for any set of "input string"/"Match string".</p>
 * <p>This class has a full set of tests to check several scenarios for invoking the processRow method for Non Unicode
 * "Input strings".</p>
 * <p>For Unicode "Input strings", check the {@link ReplaceStringProcessRowUnicodeTest} as they were originally created
 * with the same structure and the same tests. Comparing both of them should be very straightforward.</p>
 */
public class ReplaceStringProcessRowNoUnicodeTest {

  private StepMockHelper<ReplaceStringMeta, ReplaceStringData> stepMockHelper = null;

  /**
   * <p>The string to use as a replacement for any found match.</p>
   */
  private static final String TESTPROCESSROW_REPLACE_BY_STRING = "matched";

  /**
   * <p>The string to be used as input.</p>
   */
  private static final String TESTPROCESSROW_STRING = "aAbBcCdD";
  /**
   * <p>Just the capital letter 'D'.</p>
   */
  private static final String TESTPROCESSROW_SIMPLE_MATCH_PATTERN = "D";

  /**
   * <p>The Regex expression for one or more capital letter 'd'.</p>
   */
  private static final String TESTPROCESSROW_REGEX_MATCH_PATTERN = "(D)+";

  /**
   * <p>A Regex expression that matches the entire string.</p>
   * <p>It matches/expects one or more letters that not 'B', a 'B' and zero or more random characters.</p>
   */
  private static final String TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN = "[^B]+B.*";

  /**
   * <p>Regex expression that splits the input string into two groups.</p>
   * <p>It matches/expects one or more letters 'a', followed by one or more letters that not 'a'.</p>
   *
   * @see #TESTPROCESSROW_REGEX_CONCATENATE_PATTERN
   */
  private static final String TESTPROCESSROW_REGEX_SPLIT_PATTERN = "([a]+)([^a]+)";

  /**
   * <p>The separator to be used in the concatenation of the identified groups.</p>
   *
   * @see #TESTPROCESSROW_REGEX_CONCATENATE_PATTERN
   */
  private static final char TESTPROCESSROW_REGEX_CONCATENATE_SEPARATOR = '-';

  /**
   * <p>Regex expression to concatenate the identified groups.</p>
   * <p>Concatenates the two groups by the same order, separating both with a {@value
   * #TESTPROCESSROW_REGEX_CONCATENATE_SEPARATOR}.</p>
   *
   * @see #TESTPROCESSROW_REGEX_SPLIT_PATTERN
   * @see #TESTPROCESSROW_REGEX_CONCATENATE_SEPARATOR
   */
  private static final String TESTPROCESSROW_REGEX_CONCATENATE_PATTERN =
    "$1" + TESTPROCESSROW_REGEX_CONCATENATE_SEPARATOR + "$2";

  @Before
  public void setUp() throws Exception {
    stepMockHelper = new StepMockHelper<>( "REPLACE STRING TEST", ReplaceStringMeta.class, ReplaceStringData.class );
    when( stepMockHelper.logChannelInterfaceFactory.create( any(), any( LoggingObjectInterface.class ) ) ).thenReturn(
      stepMockHelper.logChannelInterface );
    verify( stepMockHelper.logChannelInterface, never() ).logError( anyString() );
    verify( stepMockHelper.logChannelInterface, never() ).logError( anyString(), any( Object[].class ) );
    verify( stepMockHelper.logChannelInterface, never() ).logError( anyString(), (Throwable) anyObject() );
    when( stepMockHelper.trans.isRunning() ).thenReturn( true );
  }

  @After
  public void tearDown() throws Exception {
    stepMockHelper.cleanUp();
  }

  @Test
  public void testProcessRow_NullInput() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, null, TESTPROCESSROW_SIMPLE_MATCH_PATTERN, TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordNo_UnicodeNo_SimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match each of the two last characters (small and capital letters)
    assertEquals(
      TESTPROCESSROW_STRING.substring( 0, TESTPROCESSROW_STRING.length() - 2 ) + "matchedmatched",
      replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordNo_UnicodeNo_SimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordNo_UnicodeNo_WholeSimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the whole string
    assertEquals( TESTPROCESSROW_REPLACE_BY_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordNo_UnicodeNo_WholeSimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordNo_UnicodeNo_RegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordNo_UnicodeNo_RegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordNo_UnicodeNo_WholeRegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordNo_UnicodeNo_WholeRegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordYes_UnicodeNo_SimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordYes_UnicodeNo_SimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordYes_UnicodeNo_WholeSimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, true, false );

    ReplaceString replaceString = prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING,
      TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the whole string
    assertEquals( TESTPROCESSROW_REPLACE_BY_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordYes_UnicodeNo_WholeSimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordYes_UnicodeNo_RegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordYes_UnicodeNo_RegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordYes_UnicodeNo_WholeRegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveNo_WholeWordYes_UnicodeNo_WholeRegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordNo_UnicodeNo_SimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match only the last character (capital letter)
    assertEquals(
      TESTPROCESSROW_STRING.substring( 0, TESTPROCESSROW_STRING.length() - 1 ) + TESTPROCESSROW_REPLACE_BY_STRING,
      replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordNo_UnicodeNo_SimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordNo_UnicodeNo_WholeSimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, false, false );

    ReplaceString replaceString = prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING,
      TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the whole string
    assertEquals( TESTPROCESSROW_REPLACE_BY_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordNo_UnicodeNo_WholeSimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordNo_UnicodeNo_RegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordNo_UnicodeNo_RegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordNo_UnicodeNo_WholeRegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordNo_UnicodeNo_WholeRegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordYes_UnicodeNo_SimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordYes_UnicodeNo_SimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordYes_UnicodeNo_WholeSimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the whole string
    assertEquals( TESTPROCESSROW_REPLACE_BY_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordYes_UnicodeNo_WholeSimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordYes_UnicodeNo_RegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordYes_UnicodeNo_RegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordYes_UnicodeNo_WholeRegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExNo_CaseSensitiveYes_WholeWordYes_UnicodeNo_WholeRegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, false, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordNo_UnicodeNo_SimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the two last characters (small and capital letters)
    assertEquals(
      TESTPROCESSROW_STRING.substring( 0, TESTPROCESSROW_STRING.length() - 2 ) + "matchedmatched",
      replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordNo_UnicodeNo_SimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordNo_UnicodeNo_WholeSimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the whole string
    assertEquals( TESTPROCESSROW_REPLACE_BY_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordNo_UnicodeNo_WholeSimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordNo_UnicodeNo_RegexSplitAndConcatenate()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_SPLIT_PATTERN,
        TESTPROCESSROW_REGEX_CONCATENATE_PATTERN );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    String[] splits =
      StringUtils.split( (String) replaceString.getRow()[ 1 ], TESTPROCESSROW_REGEX_CONCATENATE_SEPARATOR );
    assertEquals( 2, splits.length );
    assertEquals( 2, splits[ 0 ].length() );
    assertEquals( 6, splits[ 1 ].length() );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordNo_UnicodeNo_RegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match, as one, the two last characters (small and capital letters)
    assertEquals(
      TESTPROCESSROW_STRING.substring( 0, TESTPROCESSROW_STRING.length() - 2 ) + TESTPROCESSROW_REPLACE_BY_STRING,
      replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordNo_UnicodeNo_RegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordNo_UnicodeNo_WholeRegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the whole string
    assertEquals( TESTPROCESSROW_REPLACE_BY_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordNo_UnicodeNo_WholeRegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordYes_UnicodeNo_SimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordYes_UnicodeNo_SimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordYes_UnicodeNo_WholeSimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the whole string
    assertEquals( TESTPROCESSROW_REPLACE_BY_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordYes_UnicodeNo_WholeSimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordYes_UnicodeNo_RegexSplitAndConcatenate()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_SPLIT_PATTERN,
        TESTPROCESSROW_REGEX_CONCATENATE_PATTERN );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    String[] splits =
      StringUtils.split( (String) replaceString.getRow()[ 1 ], TESTPROCESSROW_REGEX_CONCATENATE_SEPARATOR );
    assertEquals( 2, splits.length );
    assertEquals( 2, splits[ 0 ].length() );
    assertEquals( 6, splits[ 1 ].length() );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordYes_UnicodeNo_RegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordYes_UnicodeNo_RegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordYes_UnicodeNo_WholeRegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the whole string
    assertEquals( TESTPROCESSROW_REPLACE_BY_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveNo_WholeWordYes_UnicodeNo_WholeRegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, false, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordNo_UnicodeNo_SimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should only match the last character (capital letter)
    assertEquals(
      TESTPROCESSROW_STRING.substring( 0, TESTPROCESSROW_STRING.length() - 1 ) + TESTPROCESSROW_REPLACE_BY_STRING,
      replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordNo_UnicodeNo_SimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordNo_UnicodeNo_WholeSimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the whole string
    assertEquals( TESTPROCESSROW_REPLACE_BY_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordNo_UnicodeNo_WholeSimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordNo_UnicodeNo_RegexSplitAndConcatenate()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_SPLIT_PATTERN,
        TESTPROCESSROW_REGEX_CONCATENATE_PATTERN );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    String[] splits =
      StringUtils.split( (String) replaceString.getRow()[ 1 ], TESTPROCESSROW_REGEX_CONCATENATE_SEPARATOR );
    assertEquals( 2, splits.length );
    assertEquals( 1, splits[ 0 ].length() );
    assertEquals( 7, splits[ 1 ].length() );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordNo_UnicodeNo_RegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should only match the last character (capital letter)
    assertEquals(
      TESTPROCESSROW_STRING.substring( 0, TESTPROCESSROW_STRING.length() - 1 ) + TESTPROCESSROW_REPLACE_BY_STRING,
      replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordNo_UnicodeNo_RegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordNo_UnicodeNo_WholeRegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the whole string
    assertEquals( TESTPROCESSROW_REPLACE_BY_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordNo_UnicodeNo_WholeRegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, false, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordYes_UnicodeNo_SimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordYes_UnicodeNo_SimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_SIMPLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordYes_UnicodeNo_WholeSimpleMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the whole string
    assertEquals( TESTPROCESSROW_REPLACE_BY_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordYes_UnicodeNo_WholeSimpleMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_STRING, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordYes_UnicodeNo_RegexSplitAndConcatenate()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_SPLIT_PATTERN,
        TESTPROCESSROW_REGEX_CONCATENATE_PATTERN );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    String[] splits =
      StringUtils.split( (String) replaceString.getRow()[ 1 ], TESTPROCESSROW_REGEX_CONCATENATE_SEPARATOR );
    assertEquals( 2, splits.length );
    assertEquals( 1, splits[ 0 ].length() );
    assertEquals( 7, splits[ 1 ].length() );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordYes_UnicodeNo_RegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordYes_UnicodeNo_RegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should return the original string
    assertEquals( TESTPROCESSROW_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordYes_UnicodeNo_WholeRegexMatch() throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN,
        TESTPROCESSROW_REPLACE_BY_STRING );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    assertNotNull( replaceString.getRow()[ 1 ] );
    // Should match the whole string
    assertEquals( TESTPROCESSROW_REPLACE_BY_STRING, replaceString.getRow()[ 1 ] );
  }

  @Test
  public void testProcessRow_UseRegExYes_CaseSensitiveYes_WholeWordYes_UnicodeNo_WholeRegexMatch_NullReplaceBy()
    throws Exception {
    ReplaceStringData data = new ReplaceStringData();
    ReplaceStringMeta meta = getReplaceStringMeta( stepMockHelper, true, true, true, false );

    ReplaceString replaceString =
      prepareTestProcessRow( data, meta, TESTPROCESSROW_STRING, TESTPROCESSROW_REGEX_WHOLE_MATCH_PATTERN, null );

    replaceString.processRow( meta, data );

    assertNotNull( replaceString.getRow() );
    assertEquals( 2, replaceString.getRow().length );
    // Should return null
    assertNull( replaceString.getRow()[ 1 ] );
  }

  private ReplaceString prepareTestProcessRow( ReplaceStringData data, ReplaceStringMeta meta, String unicodeString,
                                               String matchPattern, String matchReplacer ) throws Exception {
    ReplaceString replaceString = Mockito.spy(
      new ReplaceString( stepMockHelper.stepMeta, data, 0, stepMockHelper.transMeta, stepMockHelper.trans ) );
    RowMetaInterface inputRowMeta = new RowMeta();
    Object[] _row = new Object[] { unicodeString, null };
    doReturn( _row ).when( replaceString ).getRow();
    inputRowMeta.addValueMeta( 0, new ValueMetaString( "string" ) );

    doReturn( new String[] { "string" } ).when( meta ).getFieldInStream();
    doReturn( new String[] { "output" } ).when( meta ).getFieldOutStream();
    doReturn( new String[] { matchPattern } ).when( meta ).getReplaceString();
    doReturn( new String[] { StringUtils.EMPTY } ).when( meta ).getFieldReplaceByString();
    doReturn( new String[] { matchReplacer } ).when( meta ).getReplaceByString();
    doReturn( new boolean[] { false } ).when( meta ).isSetEmptyString();

    replaceString.init( meta, data );
    replaceString.setInputRowMeta( inputRowMeta );
    data.outputRowMeta = inputRowMeta;
    data.inputFieldsNr = 1;
    data.numFields = 2;
    data.inStreamNrs = new int[] { 0 };
    data.replaceFieldIndex = new int[] { -1 };
    data.outStreamNrs = new String[] { StringUtils.EMPTY, "1" };
    data.replaceByString = new String[] { "1" };
    data.setEmptyString = new boolean[] { false, false };

    return replaceString;
  }

  private ReplaceStringMeta getReplaceStringMeta( StepMockHelper<ReplaceStringMeta, ReplaceStringData> stepMockHelper,
                                                  boolean parmUseRegEx, boolean parmCaseSensitive,
                                                  boolean parmWholeWord, boolean parmUnicode ) {
    ReplaceStringMeta meta = stepMockHelper.processRowsStepMetaInterface;

    doReturn( new boolean[] { parmUseRegEx } ).when( meta ).getUseRegEx();
    doReturn( new boolean[] { parmCaseSensitive } ).when( meta ).getCaseSensitive();
    doReturn( new boolean[] { parmWholeWord } ).when( meta ).getWholeWord();
    doReturn( new boolean[] { parmUnicode } ).when( meta ).isUnicode();

    return meta;
  }
}
