public StepDialogInterface getStepDialog( StepMetaInterface stepMeta, TransMeta transMeta, String stepName ) throws KettleException {
    Class<?>[] paramClasses = new Class<?>[] { Shell.class, Object.class, TransMeta.class, String.class };
    Object[] paramArgs = new Object[] { spoon.getShell(), stepMeta, transMeta, stepName };

    PluginRegistry registry = PluginRegistry.getInstance();
    PluginInterface plugin = registry.getPlugin( StepPluginType.class, stepMeta );
    String dialogClassName = plugin.getClassMap().get( StepDialogInterface.class );
    if ( dialogClassName == null ) {
      // try the deprecated way
      log.logDebug( "Use of StepMetaInterface#getDialogClassName is deprecated, use PluginDialog annotation instead." );
      dialogClassName = stepMeta.getDialogClassName();
    }

    try {
      Class<StepDialogInterface> dialogClass = registry.getClass( plugin, dialogClassName );
      Constructor<StepDialogInterface> dialogConstructor = dialogClass.getConstructor( paramClasses );
      return dialogConstructor.newInstance( paramArgs );
    } catch ( Exception e ) {
      // try the old way for compatibility
      try {
        Class<?>[] sig = new Class<?>[] { Shell.class, StepMetaInterface.class, TransMeta.class, String.class };
        Method method = stepMeta.getClass().getDeclaredMethod( "getDialog", sig );
        if ( method != null ) {
          log.logDebug( "Use of StepMetaInterface#getDialog is deprecated, use PluginDialog annotation instead." );
          return (StepDialogInterface) method.invoke( stepMeta, paramArgs );
        }
      } catch ( Throwable ignored ) { }

      String errorTitle = BaseMessages.getString( PKG, "Spoon.Dialog.ErrorCreatingStepDialog.Title" );
      String errorMsg = BaseMessages.getString( PKG, "Spoon.Dialog.ErrorCreatingStepDialog.Message", dialogClassName );
      new ErrorDialog( spoon.getShell(), errorTitle, errorMsg, e );
      throw new KettleException( e );
    }
  }
@Test
  public void testGetStepDialogClass() throws Exception {
    PluginMockInterface plugin = mock( PluginMockInterface.class );
    when( plugin.getIds() ).thenReturn( new String[] { "mockPlugin"} );
    when( plugin.matches( "mockPlugin" ) ).thenReturn( true );
    when( plugin.getName() ).thenReturn( "mockPlugin" );

    StepMetaInterface meta = mock( StepMetaInterface.class );
    when( meta.getDialogClassName() ).thenReturn( String.class.getName() );
    when( plugin.getClassMap() ).thenReturn( new HashMap<Class<?>, String>() {{
        put( StepMetaInterface.class, meta.getClass().getName() );
        put( StepDialogInterface.class, StepDialogInterface.class.getName() );
      }} );

    PluginRegistry.getInstance().registerPlugin( StepPluginType.class, plugin );

    SpoonStepsDelegate delegate = mock( SpoonStepsDelegate.class );
    Spoon spoon = mock( Spoon.class );
    delegate.spoon = spoon;
    delegate.log = mock( LogChannelInterface.class );
    when( spoon.getShell() ).thenReturn( mock( Shell.class ) );
    doCallRealMethod().when( delegate ).getStepDialog( any( StepMetaInterface.class ), any( TransMeta.class ), any( String.class ) );

    TransMeta trans = mock( TransMeta.class );

    // verify that dialog class is requested from plugin
    try {
      delegate.getStepDialog( meta, trans, "" ); // exception is expected here
    } catch ( Throwable ignore ) {
      verify( meta, never() ).getDialogClassName();
    }

    // verify that the deprecated way is still valid
    when( plugin.getClassMap() ).thenReturn( new HashMap<Class<?>, String>() {{
        put( StepMetaInterface.class, meta.getClass().getName() );
      }} );
    try {
      delegate.getStepDialog( meta, trans, "" ); // exception is expected here
    } catch ( Throwable ignore ) {
      verify( meta, times( 1 ) ).getDialogClassName();
    }

    // cleanup
    PluginRegistry.getInstance().removePlugin( StepPluginType.class, plugin );
  }