void createOutputValueMapping() throws KettleException {
    data.outputRowMeta = getInputRowMeta().clone();
    meta.getFields( getInputRowMeta(), getStepname(), null, null, this, repository, metaStore );

    data.fieldIndex = getInputRowMeta().indexOfValue( meta.getFieldname() );
    if ( data.fieldIndex < 0 ) {
      throw new KettleException( BaseMessages.getString( PKG, "SwitchCase.Exception.UnableToFindFieldName", meta
        .getFieldname() ) );
    }

    data.inputValueMeta = getInputRowMeta().getValueMeta( data.fieldIndex );

    try {
      StepIOMetaInterface ioMeta = meta.getStepIOMeta();

      // There is one or many case target for each target stream.
      // The ioMeta object has one more target stream for the default target though.
      //
      List<StreamInterface> targetStreams = ioMeta.getTargetStreams();
      for ( int i = 0; i < targetStreams.size(); i++ ) {
        SwitchCaseTarget target = (SwitchCaseTarget) targetStreams.get( i ).getSubject();
        if ( target == null ) {
          break; // Skip over default option
        }
        if ( target.caseTargetStep == null ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "SwitchCase.Log.NoTargetStepSpecifiedForValue", target.caseValue ) );
        }

        RowSet rowSet = findOutputRowSet( target.caseTargetStep.getName() );
        if ( rowSet == null ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "SwitchCase.Log.UnableToFindTargetRowSetForStep", target.caseTargetStep ) );
        }

        try {
          Object value =
            data.valueMeta.convertDataFromString(
              target.caseValue, data.stringValueMeta, null, null, ValueMetaInterface.TRIM_TYPE_NONE );

          // If we have a value and a rowset, we can store the combination in the map
          //
          if ( data.valueMeta.isNull( value ) ) {
            data.nullRowSetSet.add( rowSet );
          } else {
            // could not use byte[] as key in Maps, so we need to convert it to his specific hashCode for future
            // comparisons
            value = prepareObjectType( value );
            data.outputMap.put( value, rowSet );
          }
        } catch ( Exception e ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "SwitchCase.Log.UnableToConvertValue", target.caseValue ), e );
        }
      }

      if ( meta.getDefaultTargetStep() != null ) {
        RowSet rowSet = findOutputRowSet( meta.getDefaultTargetStep().getName() );
        if ( rowSet != null ) {
          data.defaultRowSetSet.add( rowSet );
          if ( data.nullRowSetSet.isEmpty() ) {
            data.nullRowSetSet.add( rowSet );
          }
        }
      }
    } catch ( Exception e ) {
      throw new KettleException( e );
    }
  }
@Test
  public void testCreateOutputValueMapping() throws KettleException, URISyntaxException,
    ParserConfigurationException, SAXException, IOException {
    SwitchCaseCustom krasavez = new SwitchCaseCustom( mockHelper );

    // load step info value-case mapping from xml.
    List<DatabaseMeta> emptyList = new ArrayList<DatabaseMeta>();
    krasavez.meta.loadXML( loadStepXmlMetadata( "SwitchCaseTest.xml" ), emptyList, mock( IMetaStore.class ) );

    KeyToRowSetMap expectedNN = new KeyToRowSetMap();
    Set<RowSet> nulls = new HashSet<RowSet>();

    // create real steps for all targets
    List<SwitchCaseTarget> list = krasavez.meta.getCaseTargets();
    for ( SwitchCaseTarget item : list ) {
      StepMetaInterface smInt = new DummyTransMeta();
      StepMeta stepMeta = new StepMeta( item.caseTargetStepname, smInt );
      item.caseTargetStep = stepMeta;

      // create and put row set for this
      RowSet rw = new QueueRowSet();
      krasavez.map.put( item.caseTargetStepname, rw );

      // null values goes to null rowset
      if ( item.caseValue != null ) {
        expectedNN.put( item.caseValue, rw );
      } else {
        nulls.add( rw );
      }
    }

    // create default step
    StepMetaInterface smInt = new DummyTransMeta();
    StepMeta stepMeta = new StepMeta( krasavez.meta.getDefaultTargetStepname(), smInt );
    krasavez.meta.setDefaultTargetStep( stepMeta );
    RowSet rw = new QueueRowSet();
    krasavez.map.put( krasavez.meta.getDefaultTargetStepname(), rw );

    krasavez.createOutputValueMapping();

    // inspect step output data:
    Set<RowSet> ones = krasavez.data.outputMap.get( "1" );
    assertEquals( "Output map for 1 values contains 2 row sets", 2, ones.size() );

    Set<RowSet> twos = krasavez.data.outputMap.get( "2" );
    assertEquals( "Output map for 2 values contains 1 row sets", 1, twos.size() );

    assertEquals( "Null row set contains 2 items: ", 2, krasavez.data.nullRowSetSet.size() );
    assertEquals( "We have at least one default rowset", 1, krasavez.data.defaultRowSetSet.size() );

    // check that rowsets data is correct:
    Set<RowSet> rowsets = expectedNN.get( "1" );
    for ( RowSet rowset : rowsets ) {
      assertTrue( "Output map for 1 values contains expected row set", ones.contains( rowset ) );
    }
    rowsets = expectedNN.get( "2" );
    for ( RowSet rowset : rowsets ) {
      assertTrue( "Output map for 2 values contains expected row set", twos.contains( rowset ) );
    }
    for ( RowSet rowset : krasavez.data.nullRowSetSet ) {
      assertTrue( "Output map for null values contains expected row set", nulls.contains( rowset ) );
    }
    // we have already check that there is only one item.
    for ( RowSet rowset : krasavez.data.defaultRowSetSet ) {
      assertTrue( "Output map for default case contains expected row set", rowset.equals( rw ) );
    }
  }