/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2016 by Pentaho : 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.splitfieldtorows; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.List; import org.junit.Test; import org.pentaho.di.core.util.Utils; import org.pentaho.di.core.KettleEnvironment; import org.pentaho.di.core.RowMetaAndData; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.exception.KettleValueException; import org.pentaho.di.core.plugins.PluginRegistry; import org.pentaho.di.core.plugins.StepPluginType; import org.pentaho.di.core.row.RowMeta; import org.pentaho.di.core.row.RowMetaInterface; import org.pentaho.di.core.row.ValueMetaInterface; import org.pentaho.di.core.row.value.ValueMetaString; import org.pentaho.di.trans.RowProducer; import org.pentaho.di.trans.RowStepCollector; import org.pentaho.di.trans.Trans; import org.pentaho.di.trans.TransHopMeta; import org.pentaho.di.trans.TransMeta; import org.pentaho.di.trans.step.StepInterface; import org.pentaho.di.trans.step.StepMeta; import org.pentaho.di.trans.steps.dummytrans.DummyTransMeta; import org.pentaho.di.trans.steps.injector.InjectorMeta; /** * Test class for the SplitFieldToRows step. * * The expected results were obtained by running the "Split field To Rows" Kettle step with Spoon 4.3.0. * * @author Sean Flatley */ public class SplitFieldToRowsTest { private static final String FIELD_TO_SPLIT_NAME = "FieldToSplit"; private static final String NEW_FIELD_NAME = "NewFieldName"; /** * Creates the row meta interface. * * @return the row meta interface */ private RowMetaInterface createRowMetaInterface() { RowMetaInterface rowMeta = new RowMeta(); ValueMetaInterface[] valuesMeta = { new ValueMetaString( FIELD_TO_SPLIT_NAME ) }; for ( int i = 0; i < valuesMeta.length; i++ ) { rowMeta.addValueMeta( valuesMeta[i] ); } return rowMeta; } /** * Create a list of RowMetaAndData from the passed value and returns it. * * @param value * @return List<RowMetaAndData> */ private List<RowMetaAndData> createData( String value ) { List<RowMetaAndData> list = new ArrayList<RowMetaAndData>(); RowMetaInterface rm = createRowMetaInterface(); Object[] r1 = new Object[] { value }; list.add( new RowMetaAndData( rm, r1 ) ); return list; } /** * Execute a test with the passed parameters. * * @param testName * @param stringToSplit * @param isDelimiterRegex * @param delimiter * @param delimiterVariableValue - Should be null if {@code delimiter} is not variable * @param expectedResult * @throws Exception */ private void test( String testName, String stringToSplit, boolean isDelimiterRegex, String delimiter, String delimiterVariableValue, String[] expectedResult ) { List<RowMetaAndData> result = splitFieldToRows( testName, stringToSplit, isDelimiterRegex, delimiter, delimiterVariableValue ); assertDataEquals( expectedResult, result ); } /** * Splits the "stringToSplit" with the passed "delimiter". The "delimiter" is assumed by this method to be a Kettle * variable. The parameter "delimiterVariableValue" should contain the variables value. * * The "isDelimiterRegex" parameter will process the use regex for pattern matching if true. * * @param testName * @param stringToSplit * @param isDelimiterRegex * @param delimiter * @param delimiterVariableValue * @return * @throws Exception */ private List<RowMetaAndData> splitFieldToRows( String testName, String stringToSplit, boolean isDelimiterRegex, String delimiter, String delimiterVariableValue ) { RowStepCollector rc = new RowStepCollector(); try { KettleEnvironment.init(); // Create a new transformation... TransMeta transMeta = new TransMeta(); transMeta.setName( "Split field to rows test" ); PluginRegistry registry = PluginRegistry.getInstance(); // create an injector step... String injectorStepname = "injector step"; InjectorMeta im = new InjectorMeta(); // Set the information of the injector. String injectorPid = registry.getPluginId( StepPluginType.class, im ); StepMeta injectorStep = new StepMeta( injectorPid, injectorStepname, im ); transMeta.addStep( injectorStep ); // Create a Split Field to Rows step String splitfieldToRowsName = "Split field to rows"; SplitFieldToRowsMeta splitFieldtoRowsMeta = new SplitFieldToRowsMeta(); splitFieldtoRowsMeta.setDelimiter( delimiter ); splitFieldtoRowsMeta.setDelimiterRegex( isDelimiterRegex ); splitFieldtoRowsMeta.setSplitField( FIELD_TO_SPLIT_NAME ); splitFieldtoRowsMeta.setNewFieldname( NEW_FIELD_NAME ); String splitFieldTotRowsPid = registry.getPluginId( StepPluginType.class, splitFieldtoRowsMeta ); StepMeta splitFieldToRows = new StepMeta( splitFieldTotRowsPid, splitfieldToRowsName, splitFieldtoRowsMeta ); transMeta.addStep( splitFieldToRows ); // hop the injector to the split field to rows step TransHopMeta hop_injector_splitfieldToRows = new TransHopMeta( injectorStep, splitFieldToRows ); transMeta.addTransHop( hop_injector_splitfieldToRows ); // Create a dummy step String dummyStepname = "dummy step"; DummyTransMeta dm = new DummyTransMeta(); String dummyPid = registry.getPluginId( StepPluginType.class, dm ); StepMeta dummyStep = new StepMeta( dummyPid, dummyStepname, dm ); transMeta.addStep( dummyStep ); TransHopMeta hop_SplitFieldToRows_Dummy = new TransHopMeta( splitFieldToRows, dummyStep ); transMeta.addTransHop( hop_SplitFieldToRows_Dummy ); if ( !Utils.isEmpty( delimiterVariableValue ) ) { String delimiterVariableName = delimiter.replace( "${", "" ); delimiterVariableName = delimiterVariableName.replace( "}", "" ); transMeta.setVariable( delimiterVariableName, delimiterVariableValue ); } // Now execute the transformation... Trans trans = new Trans( transMeta ); trans.prepareExecution( null ); StepInterface si = trans.getStepInterface( dummyStepname, 0 ); si.addRowListener( rc ); RowProducer rowProducer = trans.addRowProducer( injectorStepname, 0 ); trans.startThreads(); // add rows List<RowMetaAndData> inputList = createData( stringToSplit ); for ( RowMetaAndData rm : inputList ) { rowProducer.putRow( rm.getRowMeta(), rm.getData() ); } rowProducer.finished(); trans.waitUntilFinished(); } catch ( KettleException e ) { fail( "KettleEnvironment exception" + e.getMessage() ); } List<RowMetaAndData> resultRows = rc.getRowsWritten(); return resultRows; } /** * Compares the passed parameters and returns truf if they contain the same data. * * @param expectedData * @param result */ private void assertDataEquals( String[] expectedData, List<RowMetaAndData> result ) { for ( int i = 0; i < expectedData.length; i++ ) { try { String resultElement = result.get( i ).getString( "NewFieldName", "String" ); if ( !expectedData[i].equals( resultElement ) ) { fail("Expected element does not match result element"); } } catch ( ArrayIndexOutOfBoundsException aiobe ) { fail( aiobe.getMessage() ); } catch ( KettleValueException kve ) { fail( kve.getMessage() ); } } } // Non regex tests /** * Test: Non regex, delimiter = ";" */ @Test public void testNonRegex1() { String[] expectedResult = { "Sean", "Flatley" }; test( "Non Regex Test 1", "Sean;Flatley", false, ";", null, expectedResult ); } /** * Test: Non regex, delimiter = "!;" */ @Test public void testNonRegex2() { String[] expectedResult = { "Sean", "Flatley" }; test( "Non Regex Test 2", "Sean!;Flatley", false, "!;", null, expectedResult ); } /** * Test: Non regex, delimiter = ";", "!" appears in field. */ @Test public void testNonRegex3() { String[] expectedResult = { "Sean!", "Flatley" }; test( "Non Regex Test 3", "Sean!;Flatley", false, ";", null, expectedResult ); } /** * Test: Non regex, delimiter = "." */ @Test public void testNonRegex4() { String[] expectedResult = { "Sean", "Flatley" }; test( "Non Regex Test 4", "Sean.Flatley", false, ".", null, expectedResult ); } /** * Test: Non regex, delimiter = "\\.", delmiter "." appears in field. */ @Test public void testNonRegex5() { String[] expectedResult = { "Sean.Flatley" }; test( "Non Regex Test 5", "Sean.Flatley", false, "\\.", null, expectedResult ); } /** * Test: Non regex, delimiter = "${DELIMITER}, value of delimiter = ";" */ @Test public void testNonRegex6() { String[] expectedResult = { "Sean", "Flatley" }; test( "Non Regex Test 6", "Sean;Flatley", false, "${DELIMITER}", ";", expectedResult ); } // Regex tests /** * Test: Regex test, delimiter = ";" */ @Test public void testRegex1() { String[] expectedResult = { "Sean", "Flatley" }; test( "Regex Test 1", "Sean;Flatley", true, ";", null, expectedResult ); } /** * Test: Regex, delimiter = "!;" */ @Test public void testRegex2() { String[] expectedResult = { "Sean", "Flatley" }; test( "Regex Test 2", "Sean!;Flatley", true, "!;", null, expectedResult ); } /** * Test: Regex, delimiter = ";", "!;" appears in the field. */ @Test public void testRegex3() { String[] expectedResult = { "Sean!", "Flatley" }; test( "Regex Test 3", "Sean!;Flatley", true, ";", null, expectedResult ); } /** * Test: Regex, delimiter = "." */ @Test public void testRegex4() { String[] expectedResult = {}; test( "Regex Test 4", "SeanFlatley", true, ".", null, expectedResult ); } /** * Test: Regex, delimiter = "\\." */ @Test public void testRegex5() { String[] expectedResult = { "Sean", "Flatley" }; test( "Regex Test 5", "Sean.Flatley", true, "\\.", null, expectedResult ); } /** * Test: Regex, delimiter = "[0-9]" */ @Test public void testRegex6() { String[] expectedResult = { "Sean", "Flatley" }; test( "Regex Test 6", "Sean1Flatley", true, "[0-9]", null, expectedResult ); } /** * Test: Regex, delimiter = ";", empty characters http://jira.pentaho.com/browse/PDI-11477 */ @Test public void testRegex7() { String[] expectedResult = { "", "1", "", "1", "" }; test( "Regex Test 7", ";1;;1;;", true, ";", null, expectedResult ); } }