/*! ****************************************************************************** * * 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.append; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import org.pentaho.di.core.KettleEnvironment; import org.pentaho.di.core.RowMetaAndData; 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.ValueMetaBigNumber; import org.pentaho.di.core.row.value.ValueMetaBoolean; import org.pentaho.di.core.row.value.ValueMetaDate; import org.pentaho.di.core.row.value.ValueMetaInteger; import org.pentaho.di.core.row.value.ValueMetaNumber; 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.step.errorhandling.StreamInterface; import org.pentaho.di.trans.steps.dummytrans.DummyTransMeta; import org.pentaho.di.trans.steps.injector.InjectorMeta; import junit.framework.TestCase; /** * Test class for the Append step. * * @author Sven Boden */ public class AppendTest extends TestCase { public RowMetaInterface createRowMetaInterface() { RowMetaInterface rm = new RowMeta(); ValueMetaInterface[] valuesMeta = { new ValueMetaString( "field1" ), new ValueMetaInteger( "field2" ), new ValueMetaNumber( "field3" ), new ValueMetaDate( "field4" ), new ValueMetaBoolean( "field5" ), new ValueMetaBigNumber( "field6" ), new ValueMetaBigNumber( "field7" ) }; for ( int i = 0; i < valuesMeta.length; i++ ) { rm.addValueMeta( valuesMeta[i] ); } return rm; } /** * Create data for the first hop. */ public List<RowMetaAndData> createData1() { List<RowMetaAndData> list = new ArrayList<RowMetaAndData>(); RowMetaInterface rm = createRowMetaInterface(); Object[] r1 = new Object[] { "KETTLE1", new Long( 123L ), new Double( 10.5D ), new Date(), Boolean.TRUE, BigDecimal.valueOf( 123.45 ), BigDecimal.valueOf( 123.60 ) }; Object[] r2 = new Object[] { "KETTLE1", new Long( 500L ), new Double( 20.0D ), new Date(), Boolean.FALSE, BigDecimal.valueOf( 123.45 ), BigDecimal.valueOf( 123.60 ) }; Object[] r3 = new Object[] { "KETTLE1", new Long( 501L ), new Double( 21.0D ), new Date(), Boolean.FALSE, BigDecimal.valueOf( 123.45 ), BigDecimal.valueOf( 123.70 ) }; list.add( new RowMetaAndData( rm, r1 ) ); list.add( new RowMetaAndData( rm, r2 ) ); list.add( new RowMetaAndData( rm, r3 ) ); return list; } /** * Create data for the second hop. */ public List<RowMetaAndData> createData2() { List<RowMetaAndData> list = new ArrayList<RowMetaAndData>(); RowMetaInterface rm = createRowMetaInterface(); Object[] r1 = new Object[] { "KETTLE1", Long.valueOf( 123L ), new Double( 10.5D ), new Date(), Boolean.TRUE, BigDecimal.valueOf( 123.45 ), BigDecimal.valueOf( 123.60 ) }; Object[] r2 = new Object[] { "KETTLE1", Long.valueOf( 500L ), new Double( 20.0D ), new Date(), Boolean.FALSE, BigDecimal.valueOf( 123.45 ), BigDecimal.valueOf( 123.60 ) }; Object[] r3 = new Object[] { "KETTLE1", Long.valueOf( 501L ), new Double( 21.0D ), new Date(), Boolean.FALSE, BigDecimal.valueOf( 123.45 ), BigDecimal.valueOf( 123.70 ) }; list.add( new RowMetaAndData( rm, r1 ) ); list.add( new RowMetaAndData( rm, r2 ) ); list.add( new RowMetaAndData( rm, r3 ) ); return list; } /** * Check the 2 lists comparing the rows in order. If they are not the same fail the test. */ public void checkRows( List<RowMetaAndData> rows1, List<RowMetaAndData> rows2 ) { int idx = 1; if ( rows1.size() != rows2.size() ) { fail( "Number of rows is not the same: " + rows1.size() + " and " + rows2.size() ); } Iterator<RowMetaAndData> it1 = rows1.iterator(); Iterator<RowMetaAndData> it2 = rows2.iterator(); while ( it1.hasNext() && it2.hasNext() ) { RowMetaAndData rm1 = it1.next(); RowMetaAndData rm2 = it2.next(); Object[] r1 = rm1.getData(); Object[] r2 = rm2.getData(); if ( r1.length != r2.length ) { fail( "row nr " + idx + "is not equal" ); } int[] fields = new int[r1.length]; for ( int ydx = 0; ydx < r1.length; ydx++ ) { fields[ydx] = ydx; } try { if ( rm1.getRowMeta().compare( r1, r2, fields ) != 0 ) { fail( "row nr " + idx + "is not equal" ); } } catch ( KettleValueException e ) { fail( "row nr " + idx + "is not equal" ); } idx++; } } /** * Test case for Append step. 2 Injector steps to an append step to a dummy step. Rows go in, the order should be as * defined in the append step. */ public void testAppendStep() throws Exception { KettleEnvironment.init(); // // Create a new transformation... // TransMeta transMeta = new TransMeta(); transMeta.setName( "Appendtest" ); PluginRegistry registry = PluginRegistry.getInstance(); // // create an injector step 1... // String injectorStepname1 = "injector step 1"; InjectorMeta im1 = new InjectorMeta(); // Set the information of the injector. String injectorPid1 = registry.getPluginId( StepPluginType.class, im1 ); StepMeta injectorStep1 = new StepMeta( injectorPid1, injectorStepname1, im1 ); transMeta.addStep( injectorStep1 ); // // create an injector step 2... // String injectorStepname2 = "injector step 2"; InjectorMeta im2 = new InjectorMeta(); // Set the information of the injector. String injectorPid2 = registry.getPluginId( StepPluginType.class, im2 ); StepMeta injectorStep2 = new StepMeta( injectorPid2, injectorStepname2, im2 ); transMeta.addStep( injectorStep2 ); // // Create an append step // String appendName = "append step"; AppendMeta am = new AppendMeta(); List<StreamInterface> infoStreams = am.getStepIOMeta().getInfoStreams(); infoStreams.get( 0 ).setStepMeta( injectorStep1 ); infoStreams.get( 1 ).setStepMeta( injectorStep2 ); String appendPid = registry.getPluginId( StepPluginType.class, am ); StepMeta append = new StepMeta( appendPid, appendName, am ); transMeta.addStep( append ); TransHopMeta hi2 = new TransHopMeta( injectorStep1, append ); transMeta.addTransHop( hi2 ); TransHopMeta hi3 = new TransHopMeta( injectorStep2, append ); transMeta.addTransHop( hi3 ); // // Create a dummy step 1 // String dummyStepname1 = "dummy step 1"; DummyTransMeta dm1 = new DummyTransMeta(); String dummyPid1 = registry.getPluginId( StepPluginType.class, dm1 ); StepMeta dummyStep1 = new StepMeta( dummyPid1, dummyStepname1, dm1 ); transMeta.addStep( dummyStep1 ); TransHopMeta hi4 = new TransHopMeta( append, dummyStep1 ); transMeta.addTransHop( hi4 ); // Now execute the transformation... Trans trans = new Trans( transMeta ); trans.prepareExecution( null ); StepInterface si = trans.getStepInterface( appendName, 0 ); RowStepCollector blockingRc = new RowStepCollector(); si.addRowListener( blockingRc ); si = trans.getStepInterface( dummyStepname1, 0 ); RowStepCollector dummyRc1 = new RowStepCollector(); si.addRowListener( dummyRc1 ); RowProducer rp1 = trans.addRowProducer( injectorStepname1, 0 ); RowProducer rp2 = trans.addRowProducer( injectorStepname2, 0 ); trans.startThreads(); // add rows to tail step List<RowMetaAndData> inputList2 = createData2(); Iterator<RowMetaAndData> it2 = inputList2.iterator(); while ( it2.hasNext() ) { RowMetaAndData rm = it2.next(); rp2.putRow( rm.getRowMeta(), rm.getData() ); } rp2.finished(); // add rows to head step List<RowMetaAndData> inputList1 = createData1(); Iterator<RowMetaAndData> it1 = inputList1.iterator(); while ( it1.hasNext() ) { RowMetaAndData rm = it1.next(); rp1.putRow( rm.getRowMeta(), rm.getData() ); } rp1.finished(); trans.waitUntilFinished(); // The result should be that first all rows from injector 1 and // then all rows from injector step 2 List<RowMetaAndData> expectedList = new ArrayList<RowMetaAndData>(); expectedList.addAll( inputList1 ); expectedList.addAll( inputList2 ); List<RowMetaAndData> resultRows1 = dummyRc1.getRowsWritten(); checkRows( resultRows1, expectedList ); } }