/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2017 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.ui.trans.steps.mapping; import org.apache.commons.vfs2.FileObject; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.pentaho.di.core.Const; import org.pentaho.di.core.ObjectLocationSpecificationMethod; import org.pentaho.di.core.Props; import org.pentaho.di.core.SourceToTargetMapping; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.row.RowMetaInterface; import org.pentaho.di.core.util.Utils; import org.pentaho.di.core.vfs.KettleVFS; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.repository.ObjectId; import org.pentaho.di.repository.RepositoryDirectoryInterface; import org.pentaho.di.repository.RepositoryObject; import org.pentaho.di.repository.RepositoryObjectType; import org.pentaho.di.trans.TransMeta; import org.pentaho.di.trans.step.BaseStepMeta; import org.pentaho.di.trans.step.StepDialogInterface; import org.pentaho.di.trans.step.StepMeta; import org.pentaho.di.trans.steps.mapping.MappingIODefinition; import org.pentaho.di.trans.steps.mapping.MappingMeta; import org.pentaho.di.trans.steps.mapping.MappingParameters; import org.pentaho.di.trans.steps.mapping.MappingValueRename; import org.pentaho.di.ui.core.ConstUI; import org.pentaho.di.ui.core.dialog.EnterMappingDialog; import org.pentaho.di.ui.core.dialog.EnterSelectionDialog; import org.pentaho.di.ui.core.dialog.ErrorDialog; import org.pentaho.di.ui.core.gui.GUIResource; import org.pentaho.di.ui.core.widget.ColumnInfo; import org.pentaho.di.ui.core.widget.ColumnsResizer; import org.pentaho.di.ui.core.widget.TableView; import org.pentaho.di.ui.core.widget.TextVar; import org.pentaho.di.ui.repository.dialog.SelectObjectDialog; import org.pentaho.di.ui.spoon.Spoon; import org.pentaho.di.ui.trans.step.BaseStepDialog; import org.pentaho.di.ui.util.SwtSvgImageUtil; import org.pentaho.vfs.ui.VfsFileChooserDialog; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class MappingDialog extends BaseStepDialog implements StepDialogInterface { private static Class<?> PKG = MappingMeta.class; // for i18n purposes, needed by Translator2!! private MappingMeta mappingMeta; private Label wlPath; private TextVar wPath; private Button wbBrowse; private CTabFolder wTabFolder; private TransMeta mappingTransMeta = null; protected boolean transModified; private ModifyListener lsMod; private MappingParameters mappingParameters; private List<MappingIODefinition> inputMappings; private List<MappingIODefinition> outputMappings; private ObjectId referenceObjectId; private ObjectLocationSpecificationMethod specificationMethod; private interface ApplyChanges { void applyChanges(); } private class MappingParametersTab implements ApplyChanges { private TableView wMappingParameters; private MappingParameters parameters; private Button wInheritAll; public MappingParametersTab( TableView wMappingParameters, Button wInheritAll, MappingParameters parameters ) { this.wMappingParameters = wMappingParameters; this.wInheritAll = wInheritAll; this.parameters = parameters; } public void applyChanges() { int nrLines = wMappingParameters.nrNonEmpty(); String[] variables = new String[ nrLines ]; String[] inputFields = new String[ nrLines ]; parameters.setVariable( variables ); parameters.setInputField( inputFields ); //CHECKSTYLE:Indentation:OFF for ( int i = 0; i < nrLines; i++ ) { TableItem item = wMappingParameters.getNonEmpty( i ); parameters.getVariable()[ i ] = item.getText( 1 ); parameters.getInputField()[ i ] = item.getText( 2 ); } parameters.setInheritingAllVariables( wInheritAll.getSelection() ); } } private class MappingDefinitionTab implements ApplyChanges { private MappingIODefinition definition; private Text wInputStep; private Text wOutputStep; private Button wMainPath; private Text wDescription; private TableView wFieldMappings; public MappingDefinitionTab( MappingIODefinition definition, Text inputStep, Text outputStep, Button mainPath, Text description, TableView fieldMappings ) { super(); this.definition = definition; wInputStep = inputStep; wOutputStep = outputStep; wMainPath = mainPath; wDescription = description; wFieldMappings = fieldMappings; } public void applyChanges() { // The input step definition.setInputStepname( wInputStep.getText() ); // The output step definition.setOutputStepname( wOutputStep.getText() ); // The description definition.setDescription( wDescription.getText() ); // The main path flag definition.setMainDataPath( wMainPath.getSelection() ); // The grid // int nrLines = wFieldMappings.nrNonEmpty(); definition.getValueRenames().clear(); for ( int i = 0; i < nrLines; i++ ) { TableItem item = wFieldMappings.getNonEmpty( i ); definition.getValueRenames().add( new MappingValueRename( item.getText( 1 ), item.getText( 2 ) ) ); } } } private ApplyChanges parameterChanges; private ApplyChanges tabChanges; public MappingDialog( Shell parent, Object in, TransMeta tr, String sname ) { super( parent, (BaseStepMeta) in, tr, sname ); mappingMeta = (MappingMeta) in; transModified = false; // Make a copy for our own purposes... // This allows us to change everything directly in the classes with // listeners. // Later we need to copy it to the input class on ok() // mappingParameters = (MappingParameters) mappingMeta.getMappingParameters().clone(); inputMappings = new ArrayList<MappingIODefinition>(); outputMappings = new ArrayList<MappingIODefinition>(); for ( int i = 0; i < mappingMeta.getInputMappings().size(); i++ ) { inputMappings.add( (MappingIODefinition) mappingMeta.getInputMappings().get( i ).clone() ); } for ( int i = 0; i < mappingMeta.getOutputMappings().size(); i++ ) { outputMappings.add( (MappingIODefinition) mappingMeta.getOutputMappings().get( i ).clone() ); } } private static int CONST_WIDTH = 200; public String open() { Shell parent = getParent(); Display display = parent.getDisplay(); shell = new Shell( parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX ); props.setLook( shell ); setShellImage( shell, mappingMeta ); lsMod = new ModifyListener() { public void modifyText( ModifyEvent e ) { mappingMeta.setChanged(); } }; changed = mappingMeta.hasChanged(); FormLayout formLayout = new FormLayout(); formLayout.marginWidth = 15; formLayout.marginHeight = 15; shell.setLayout( formLayout ); shell.setText( BaseMessages.getString( PKG, "MappingDialog.Shell.Title" ) ); Label wicon = new Label( shell, SWT.RIGHT ); wicon.setImage( getImage() ); FormData fdlicon = new FormData(); fdlicon.top = new FormAttachment( 0, 0 ); fdlicon.right = new FormAttachment( 100, 0 ); wicon.setLayoutData( fdlicon ); props.setLook( wicon ); // Stepname line wlStepname = new Label( shell, SWT.RIGHT ); wlStepname.setText( BaseMessages.getString( PKG, "MappingDialog.Stepname.Label" ) ); props.setLook( wlStepname ); fdlStepname = new FormData(); fdlStepname.left = new FormAttachment( 0, 0 ); fdlStepname.top = new FormAttachment( 0, 0 ); wlStepname.setLayoutData( fdlStepname ); wStepname = new Text( shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER ); wStepname.setText( stepname ); props.setLook( wStepname ); wStepname.addModifyListener( lsMod ); fdStepname = new FormData(); fdStepname.width = 250; fdStepname.left = new FormAttachment( 0, 0 ); fdStepname.top = new FormAttachment( wlStepname, 5 ); wStepname.setLayoutData( fdStepname ); Label spacer = new Label( shell, SWT.HORIZONTAL | SWT.SEPARATOR ); FormData fdSpacer = new FormData(); fdSpacer.height = 1; fdSpacer.left = new FormAttachment( 0, 0 ); fdSpacer.top = new FormAttachment( wStepname, 15 ); fdSpacer.right = new FormAttachment( 100, 0 ); spacer.setLayoutData( fdSpacer ); wlPath = new Label( shell, SWT.LEFT ); props.setLook( wlPath ); wlPath.setText( BaseMessages.getString( PKG, "MappingDialog.Transformation.Label" ) ); FormData fdlTransformation = new FormData(); fdlTransformation.left = new FormAttachment( 0, 0 ); fdlTransformation.top = new FormAttachment( spacer, 20 ); fdlTransformation.right = new FormAttachment( 50, 0 ); wlPath.setLayoutData( fdlTransformation ); wPath = new TextVar( transMeta, shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER ); props.setLook( wPath ); FormData fdTransformation = new FormData(); fdTransformation.left = new FormAttachment( 0, 0 ); fdTransformation.top = new FormAttachment( wlPath, 5 ); fdTransformation.width = 350; wPath.setLayoutData( fdTransformation ); wbBrowse = new Button( shell, SWT.PUSH ); props.setLook( wbBrowse ); wbBrowse.setText( BaseMessages.getString( PKG, "MappingDialog.Browse.Label" ) ); FormData fdBrowse = new FormData(); fdBrowse.left = new FormAttachment( wPath, 5 ); fdBrowse.top = new FormAttachment( wlPath, 5 ); wbBrowse.setLayoutData( fdBrowse ); wbBrowse.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { if ( repository != null ) { selectRepositoryTrans(); } else { selectFileTrans(); } } } ); // // Add a tab folder for the parameters and various input and output // streams // wTabFolder = new CTabFolder( shell, SWT.BORDER ); props.setLook( wTabFolder, Props.WIDGET_STYLE_TAB ); wTabFolder.setSimple( false ); wTabFolder.setUnselectedCloseVisible( true ); wCancel = new Button( shell, SWT.PUSH ); wCancel.setText( BaseMessages.getString( PKG, "System.Button.Cancel" ) ); FormData fdCancel = new FormData(); fdCancel.right = new FormAttachment( 100, 0 ); fdCancel.bottom = new FormAttachment( 100, 0 ); wCancel.setLayoutData( fdCancel ); wOK = new Button( shell, SWT.PUSH ); wOK.setText( BaseMessages.getString( PKG, "System.Button.OK" ) ); FormData fdOk = new FormData(); fdOk.right = new FormAttachment( wCancel, -5 ); fdOk.bottom = new FormAttachment( 100, 0 ); wOK.setLayoutData( fdOk ); Label hSpacer = new Label( shell, SWT.HORIZONTAL | SWT.SEPARATOR ); FormData fdhSpacer = new FormData(); fdhSpacer.height = 1; fdhSpacer.left = new FormAttachment( 0, 0 ); fdhSpacer.bottom = new FormAttachment( wCancel, -15 ); fdhSpacer.right = new FormAttachment( 100, 0 ); hSpacer.setLayoutData( fdhSpacer ); FormData fdTabFolder = new FormData(); fdTabFolder.left = new FormAttachment( 0, 0 ); fdTabFolder.top = new FormAttachment( wPath, 20 ); fdTabFolder.right = new FormAttachment( 100, 0 ); fdTabFolder.bottom = new FormAttachment( hSpacer, -15 ); wTabFolder.setLayoutData( fdTabFolder ); // Add listeners lsCancel = new Listener() { public void handleEvent( Event e ) { cancel(); } }; lsOK = new Listener() { public void handleEvent( Event e ) { ok(); } }; wCancel.addListener( SWT.Selection, lsCancel ); wOK.addListener( SWT.Selection, lsOK ); lsDef = new SelectionAdapter() { public void widgetDefaultSelected( SelectionEvent e ) { ok(); } }; wStepname.addSelectionListener( lsDef ); // Detect X or ALT-F4 or something that kills this window... shell.addShellListener( new ShellAdapter() { public void shellClosed( ShellEvent e ) { cancel(); } } ); // Set the shell size, based upon previous time... setSize( shell, 670, 690 ); getData(); mappingMeta.setChanged( changed ); wTabFolder.setSelection( 0 ); shell.open(); while ( !shell.isDisposed() ) { if ( !display.readAndDispatch() ) { display.sleep(); } } return stepname; } protected Image getImage() { return SwtSvgImageUtil .getImage( shell.getDisplay(), getClass().getClassLoader(), "MAP.svg", ConstUI.ICON_SIZE, ConstUI.ICON_SIZE ); } private void selectRepositoryTrans() { try { SelectObjectDialog sod = new SelectObjectDialog( shell, repository ); String transName = sod.open(); RepositoryDirectoryInterface repdir = sod.getDirectory(); if ( transName != null && repdir != null ) { loadRepositoryTrans( transName, repdir ); String path = getPath( mappingTransMeta.getRepositoryDirectory().getPath() ); String fullPath = path + "/" + mappingTransMeta.getName(); wPath.setText( fullPath ); specificationMethod = ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME; } } catch ( KettleException ke ) { new ErrorDialog( shell, BaseMessages.getString( PKG, "MappingDialog.ErrorSelectingObject.DialogTitle" ), BaseMessages.getString( PKG, "MappingDialog.ErrorSelectingObject.DialogMessage" ), ke ); } } protected String getPath( String path ) { String parentPath = this.transMeta.getRepositoryDirectory().getPath(); if ( path.startsWith( parentPath ) ) { path = path.replace( parentPath, "${" + Const.INTERNAL_VARIABLE_ENTRY_CURRENT_DIRECTORY + "}" ); } return path; } private void loadRepositoryTrans( String transName, RepositoryDirectoryInterface repdir ) throws KettleException { // Read the transformation... // mappingTransMeta = repository.loadTransformation( transMeta.environmentSubstitute( transName ), repdir, null, true, null ); mappingTransMeta.clearChanged(); } private void selectFileTrans() { String curFile = transMeta.environmentSubstitute( wPath.getText() ); FileObject root = null; String parentFolder = null; try { parentFolder = KettleVFS.getFileObject( transMeta.environmentSubstitute( transMeta.getFilename() ) ).getParent().toString(); } catch ( Exception e ) { // Take no action } try { root = KettleVFS.getFileObject( curFile != null ? curFile : Const.getUserHomeDirectory() ); VfsFileChooserDialog vfsFileChooser = Spoon.getInstance().getVfsFileChooserDialog( root.getParent(), root ); FileObject file = vfsFileChooser.open( shell, null, Const.STRING_TRANS_FILTER_EXT, Const.getTransformationFilterNames(), VfsFileChooserDialog.VFS_DIALOG_OPEN_FILE ); if ( file == null ) { return; } String fileName = file.getName().toString(); if ( fileName != null ) { loadFileTrans( fileName ); if ( parentFolder != null && fileName.startsWith( parentFolder ) ) { fileName = fileName.replace( parentFolder, "${" + Const.INTERNAL_VARIABLE_ENTRY_CURRENT_DIRECTORY + "}" ); } wPath.setText( fileName ); specificationMethod = ObjectLocationSpecificationMethod.FILENAME; } } catch ( IOException | KettleException e ) { new ErrorDialog( shell, BaseMessages.getString( PKG, "MappingDialog.ErrorLoadingTransformation.DialogTitle" ), BaseMessages.getString( PKG, "MappingDialog.ErrorLoadingTransformation.DialogMessage" ), e ); } } private void loadFileTrans( String fname ) throws KettleException { mappingTransMeta = new TransMeta( transMeta.environmentSubstitute( fname ) ); mappingTransMeta.clearChanged(); } // Method is defined as package-protected in order to be accessible by unit tests void loadTransformation() throws KettleException { String filename = wPath.getText(); if ( repository != null ) { specificationMethod = ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME; } else { specificationMethod = ObjectLocationSpecificationMethod.FILENAME; } switch ( getSpecificationMethod() ) { case FILENAME: if ( Utils.isEmpty( filename ) ) { return; } if ( !filename.endsWith( ".ktr" ) ) { filename = filename + ".ktr"; wPath.setText( filename ); } loadFileTrans( filename ); break; case REPOSITORY_BY_NAME: if ( Utils.isEmpty( filename ) ) { return; } if ( filename.endsWith( ".ktr" ) ) { filename = filename.replace( ".ktr", "" ); wPath.setText( filename ); } String transPath = transMeta.environmentSubstitute( filename ); String realTransname = transPath; String realDirectory = ""; int index = transPath.lastIndexOf( "/" ); if ( index != -1 ) { realTransname = transPath.substring( index + 1 ); realDirectory = transPath.substring( 0, index ); } if ( Utils.isEmpty( realDirectory ) || Utils.isEmpty( realTransname ) ) { throw new KettleException( BaseMessages.getString( PKG, "MappingDialog.Exception.NoValidMappingDetailsFound" ) ); } RepositoryDirectoryInterface repdir = repository.findDirectory( realDirectory ); if ( repdir == null ) { throw new KettleException( BaseMessages.getString( PKG, "MappingDialog.Exception.UnableToFindRepositoryDirectory" ) ); } loadRepositoryTrans( realTransname, repdir ); break; default: break; } } private void getByReferenceData( ObjectId transObjectId ) { try { if ( repository == null ) { throw new KettleException( BaseMessages.getString( PKG, "MappingDialog.Exception.NotConnectedToRepository.Message" ) ); } RepositoryObject transInf = repository.getObjectInformation( transObjectId, RepositoryObjectType.TRANSFORMATION ); String path = getPath( transInf.getRepositoryDirectory().getPath() ); String fullPath = Const.NVL( path, "" ) + "/" + Const.NVL( transInf.getName(), "" ); wPath.setText( fullPath ); } catch ( KettleException e ) { new ErrorDialog( shell, BaseMessages.getString( PKG, "MappingDialog.Exception.UnableToReferenceObjectId.Title" ), BaseMessages.getString( PKG, "MappingDialog.Exception.UnableToReferenceObjectId.Message" ), e ); } } /** * Copy information from the meta-data input to the dialog fields. */ public void getData() { setSpecificationMethod( mappingMeta.getSpecificationMethod() ); switch ( getSpecificationMethod() ) { case FILENAME: wPath.setText( Const.NVL( mappingMeta.getFileName(), "" ) ); break; case REPOSITORY_BY_NAME: String fullPath = Const.NVL( mappingMeta.getDirectoryPath(), "" ) + "/" + Const .NVL( mappingMeta.getTransName(), "" ); wPath.setText( fullPath ); break; case REPOSITORY_BY_REFERENCE: referenceObjectId = mappingMeta.getTransObjectId(); getByReferenceData( referenceObjectId ); break; default: break; } // Add the parameters tab addParametersTab( mappingParameters ); wTabFolder.setSelection( 0 ); // Now add the input stream tabs: where is our data coming from? addInputMappingDefinitionTab(); addOutputMappingDefinitionTab(); try { loadTransformation(); } catch ( Throwable t ) { // Ignore errors } wStepname.selectAll(); wStepname.setFocus(); } private void addInputMappingDefinitionTab() { addMappingDefinitionTab( inputMappings, BaseMessages.getString( PKG, "MappingDialog.InputTab.Title" ), BaseMessages.getString( PKG, "MappingDialog.label.AvailableInputs" ), BaseMessages.getString( PKG, "MappingDialog.label.AddInput" ), BaseMessages.getString( PKG, "MappingDialog.label.RemoveInput" ), BaseMessages.getString( PKG, "MappingDialog.InputTab.label.InputSourceStepName" ), BaseMessages.getString( PKG, "MappingDialog.InputTab.label.OutputTargetStepName" ), BaseMessages.getString( PKG, "MappingDialog.InputTab.label.Description" ), BaseMessages.getString( PKG, "MappingDialog.InputTab.column.SourceField" ), BaseMessages.getString( PKG, "MappingDialog.InputTab.column.TargetField" ), BaseMessages.getString( PKG, "MappingDialog.InputTab.label.NoItems" ), true ); } private void addOutputMappingDefinitionTab() { addMappingDefinitionTab( outputMappings, BaseMessages.getString( PKG, "MappingDialog.OutputTab.Title" ), BaseMessages.getString( PKG, "MappingDialog.label.AvailableOutputs" ), BaseMessages.getString( PKG, "MappingDialog.label.AddOutput" ), BaseMessages.getString( PKG, "MappingDialog.label.RemoveOutput" ), BaseMessages.getString( PKG, "MappingDialog.OutputTab.label.InputSourceStepName" ), BaseMessages.getString( PKG, "MappingDialog.OutputTab.label.OutputTargetStepName" ), BaseMessages.getString( PKG, "MappingDialog.OutputTab.label.Description" ), BaseMessages.getString( PKG, "MappingDialog.OutputTab.column.SourceField" ), BaseMessages.getString( PKG, "MappingDialog.OutputTab.column.TargetField" ), BaseMessages.getString( PKG, "MappingDialog.OutputTab.label.NoItems" ), false ); } private void addParametersTab( final MappingParameters parameters ) { CTabItem wParametersTab = new CTabItem( wTabFolder, SWT.NONE ); wParametersTab.setText( BaseMessages.getString( PKG, "MappingDialog.Parameters.Title" ) ); wParametersTab.setToolTipText( BaseMessages.getString( PKG, "MappingDialog.Parameters.Tooltip" ) ); Composite wParametersComposite = new Composite( wTabFolder, SWT.NONE ); props.setLook( wParametersComposite ); FormLayout parameterTabLayout = new FormLayout(); parameterTabLayout.marginWidth = 15; parameterTabLayout.marginHeight = 15; wParametersComposite.setLayout( parameterTabLayout ); // Add a checkbox: inherit all variables... // Button wInheritAll = new Button( wParametersComposite, SWT.CHECK ); wInheritAll.setText( BaseMessages.getString( PKG, "MappingDialog.Parameters.InheritAll" ) ); props.setLook( wInheritAll ); FormData fdInheritAll = new FormData(); fdInheritAll.bottom = new FormAttachment( 100, 0 ); fdInheritAll.left = new FormAttachment( 0, 0 ); fdInheritAll.right = new FormAttachment( 100, -30 ); wInheritAll.setLayoutData( fdInheritAll ); wInheritAll.setSelection( parameters.isInheritingAllVariables() ); // Now add a tableview with the 2 columns to specify: input and output // fields for the source and target steps. // ColumnInfo[] colinfo = new ColumnInfo[] { new ColumnInfo( BaseMessages.getString( PKG, "MappingDialog.Parameters.column.Variable" ), ColumnInfo.COLUMN_TYPE_TEXT, false, false ), new ColumnInfo( BaseMessages.getString( PKG, "MappingDialog.Parameters.column.ValueOrField" ), ColumnInfo.COLUMN_TYPE_TEXT, false, false ), }; colinfo[ 1 ].setUsingVariables( true ); final TableView wMappingParameters = new TableView( transMeta, wParametersComposite, SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER, colinfo, parameters .getVariable().length, lsMod, props ); props.setLook( wMappingParameters ); FormData fdMappings = new FormData(); fdMappings.left = new FormAttachment( 0, 0 ); fdMappings.right = new FormAttachment( 100, 0 ); fdMappings.top = new FormAttachment( 0, 0 ); fdMappings.bottom = new FormAttachment( wInheritAll, -10 ); wMappingParameters.setLayoutData( fdMappings ); wMappingParameters.getTable().addListener( SWT.Resize, new ColumnsResizer( 0, 50, 50 ) ); for ( int i = 0; i < parameters.getVariable().length; i++ ) { TableItem tableItem = wMappingParameters.table.getItem( i ); tableItem.setText( 1, Const.NVL( parameters.getVariable()[ i ], "" ) ); tableItem.setText( 2, Const.NVL( parameters.getInputField()[ i ], "" ) ); } wMappingParameters.setRowNums(); wMappingParameters.optWidth( true ); FormData fdParametersComposite = new FormData(); fdParametersComposite.left = new FormAttachment( 0, 0 ); fdParametersComposite.top = new FormAttachment( 0, 0 ); fdParametersComposite.right = new FormAttachment( 100, 0 ); fdParametersComposite.bottom = new FormAttachment( 100, 0 ); wParametersComposite.setLayoutData( fdParametersComposite ); wParametersComposite.layout(); wParametersTab.setControl( wParametersComposite ); parameterChanges = new MappingParametersTab( wMappingParameters, wInheritAll, parameters ); } protected String selectTransformationStepname( boolean getTransformationStep, boolean mappingInput ) { String dialogTitle; String dialogMessage; if ( getTransformationStep ) { dialogTitle = BaseMessages.getString( PKG, "MappingDialog.SelectTransStep.Title" ); dialogMessage = BaseMessages.getString( PKG, "MappingDialog.SelectTransStep.Message" ); String[] stepnames; if ( mappingInput ) { stepnames = transMeta.getPrevStepNames( stepMeta ); } else { stepnames = transMeta.getNextStepNames( stepMeta ); } EnterSelectionDialog dialog = new EnterSelectionDialog( shell, stepnames, dialogTitle, dialogMessage ); return dialog.open(); } else { dialogTitle = BaseMessages.getString( PKG, "MappingDialog.SelectMappingStep.Title" ); dialogMessage = BaseMessages.getString( PKG, "MappingDialog.SelectMappingStep.Message" ); String[] stepnames = getMappingSteps( mappingTransMeta, mappingInput ); EnterSelectionDialog dialog = new EnterSelectionDialog( shell, stepnames, dialogTitle, dialogMessage ); return dialog.open(); } } public static String[] getMappingSteps( TransMeta mappingTransMeta, boolean mappingInput ) { List<StepMeta> steps = new ArrayList<StepMeta>(); for ( StepMeta stepMeta : mappingTransMeta.getSteps() ) { if ( mappingInput && stepMeta.getStepID().equals( "MappingInput" ) ) { steps.add( stepMeta ); } if ( !mappingInput && stepMeta.getStepID().equals( "MappingOutput" ) ) { steps.add( stepMeta ); } } String[] stepnames = new String[ steps.size() ]; for ( int i = 0; i < stepnames.length; i++ ) { stepnames[ i ] = steps.get( i ).getName(); } return stepnames; } public RowMetaInterface getFieldsFromStep( String stepname, boolean getTransformationStep, boolean mappingInput ) throws KettleException { if ( !( mappingInput ^ getTransformationStep ) ) { if ( Utils.isEmpty( stepname ) ) { // If we don't have a specified stepname we return the input row // metadata // return transMeta.getPrevStepFields( this.stepname ); } else { // OK, a fieldname is specified... // See if we can find it... StepMeta stepMeta = transMeta.findStep( stepname ); if ( stepMeta == null ) { throw new KettleException( BaseMessages.getString( PKG, "MappingDialog.Exception.SpecifiedStepWasNotFound", stepname ) ); } return transMeta.getStepFields( stepMeta ); } } else { if ( mappingTransMeta == null ) { throw new KettleException( BaseMessages.getString( PKG, "MappingDialog.Exception.NoMappingSpecified" ) ); } if ( Utils.isEmpty( stepname ) ) { // If we don't have a specified stepname we select the one and // only "mapping input" step. // String[] stepnames = getMappingSteps( mappingTransMeta, mappingInput ); if ( stepnames.length > 1 ) { throw new KettleException( BaseMessages.getString( PKG, "MappingDialog.Exception.OnlyOneMappingInputStepAllowed", "" + stepnames.length ) ); } if ( stepnames.length == 0 ) { throw new KettleException( BaseMessages.getString( PKG, "MappingDialog.Exception.OneMappingInputStepRequired", "" + stepnames.length ) ); } return mappingTransMeta.getStepFields( stepnames[ 0 ] ); } else { // OK, a fieldname is specified... // See if we can find it... StepMeta stepMeta = mappingTransMeta.findStep( stepname ); if ( stepMeta == null ) { throw new KettleException( BaseMessages.getString( PKG, "MappingDialog.Exception.SpecifiedStepWasNotFound", stepname ) ); } return mappingTransMeta.getStepFields( stepMeta ); } } } private void addMappingDefinitionTab( List<MappingIODefinition> definitions, final String tabTitle, String listLabel, String addToolTip, String removeToolTip, String inputStepLabel, String outputStepLabel, String descriptionLabel, String sourceColumnLabel, String targetColumnLabel, String noItemsLabel, final boolean input ) { final CTabItem wTab = new CTabItem( wTabFolder, SWT.NONE ); wTab.setText( tabTitle ); Composite wInputComposite = new Composite( wTabFolder, SWT.NONE ); props.setLook( wInputComposite ); FormLayout tabLayout = new FormLayout(); tabLayout.marginWidth = 15; tabLayout.marginHeight = 15; wInputComposite.setLayout( tabLayout ); Label wAvailableInputs = new Label( wInputComposite, SWT.LEFT ); props.setLook( wAvailableInputs ); wAvailableInputs.setText( listLabel ); FormData fdwAvailableInputs = new FormData(); fdwAvailableInputs.left = new FormAttachment( 0 ); fdwAvailableInputs.top = new FormAttachment( 0 ); Label wRemoveButton = new Label( wInputComposite, SWT.NONE ); wRemoveButton.setImage( GUIResource.getInstance().getImage( "ui/images/generic-delete.svg" ) ); wRemoveButton.setToolTipText( removeToolTip ); props.setLook( wRemoveButton ); FormData fdwAddInputButton = new FormData(); fdwAddInputButton.top = new FormAttachment( 0 ); fdwAddInputButton.right = new FormAttachment( 30 ); wRemoveButton.setLayoutData( fdwAddInputButton ); Label wAddButton = new Label( wInputComposite, SWT.NONE ); wAddButton.setImage( GUIResource.getInstance().getImage( "ui/images/Add.svg" ) ); wAddButton.setToolTipText( addToolTip ); props.setLook( wAddButton ); FormData fdwAddButton = new FormData(); fdwAddButton.top = new FormAttachment( 0 ); fdwAddButton.right = new FormAttachment( wRemoveButton, -5 ); wAddButton.setLayoutData( fdwAddButton ); org.eclipse.swt.widgets.List wInputList = new org.eclipse.swt.widgets.List( wInputComposite, SWT.BORDER ); FormData fdwInputList = new FormData(); fdwInputList.left = new FormAttachment( 0 ); fdwInputList.top = new FormAttachment( wAvailableInputs, 5 ); fdwInputList.bottom = new FormAttachment( 100 ); fdwInputList.right = new FormAttachment( 30 ); wInputList.setLayoutData( fdwInputList ); for ( int i = 0; i < definitions.size(); i++ ) { String label = !Utils.isEmpty( definitions.get( i ).getInputStepname() ) ? definitions.get( i ).getInputStepname() : tabTitle + ( i > 0 ? String.valueOf( i + 1 ) : "" ); wInputList.add( label ); } final Label wlNoItems = new Label( wInputComposite, SWT.CENTER ); wlNoItems.setText( noItemsLabel ); props.setLook( wlNoItems ); FormData fdlNoItems = new FormData(); fdlNoItems.left = new FormAttachment( wInputList, 30 ); fdlNoItems.right = new FormAttachment( 100 ); fdlNoItems.top = new FormAttachment( 50 ); wlNoItems.setLayoutData( fdlNoItems ); wlNoItems.setVisible( false ); Composite wFieldsComposite = new Composite( wInputComposite, SWT.NONE ); props.setLook( wFieldsComposite ); FormLayout fieldLayout = new FormLayout(); fieldLayout.marginWidth = 0; fieldLayout.marginHeight = 0; wFieldsComposite.setLayout( fieldLayout ); final Button wMainPath = new Button( wFieldsComposite, SWT.CHECK ); wMainPath.setText( BaseMessages.getString( PKG, "MappingDialog.input.MainDataPath" ) ); props.setLook( wMainPath ); FormData fdMainPath = new FormData(); fdMainPath.top = new FormAttachment( 0 ); fdMainPath.left = new FormAttachment( 0 ); wMainPath.setLayoutData( fdMainPath ); wMainPath.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { definitions.get( wInputList.getSelectionIndex() ) .setMainDataPath( !definitions.get( wInputList.getSelectionIndex() ).isMainDataPath() ); } } ); final Label wlInputStep = new Label( wFieldsComposite, SWT.RIGHT ); props.setLook( wlInputStep ); wlInputStep.setText( inputStepLabel ); FormData fdlInputStep = new FormData(); fdlInputStep.top = new FormAttachment( wMainPath, 10 ); fdlInputStep.left = new FormAttachment( 0 ); wlInputStep.setLayoutData( fdlInputStep ); // What's the stepname to read from? (empty is OK too) // final Button wbInputStep = new Button( wFieldsComposite, SWT.PUSH ); props.setLook( wbInputStep ); wbInputStep.setText( BaseMessages.getString( PKG, "MappingDialog.button.SourceStepName" ) ); FormData fdbInputStep = new FormData(); fdbInputStep.top = new FormAttachment( wlInputStep, 5 ); fdbInputStep.right = new FormAttachment( 100 ); // First one in the // left top corner wbInputStep.setLayoutData( fdbInputStep ); final Text wInputStep = new Text( wFieldsComposite, SWT.SINGLE | SWT.LEFT | SWT.BORDER ); props.setLook( wInputStep ); wInputStep.addModifyListener( lsMod ); FormData fdInputStep = new FormData(); fdInputStep.top = new FormAttachment( wlInputStep, 5 ); fdInputStep.left = new FormAttachment( 0 ); // To the right of // the label fdInputStep.right = new FormAttachment( wbInputStep, -5 ); wInputStep.setLayoutData( fdInputStep ); wInputStep.addFocusListener( new FocusAdapter() { @Override public void focusLost( FocusEvent event ) { definitions.get( wInputList.getSelectionIndex() ).setInputStepname( wInputStep.getText() ); String label = !Utils.isEmpty( wInputStep.getText() ) ? wInputStep.getText() : tabTitle + ( wInputList.getSelectionIndex() > 0 ? String.valueOf( wInputList.getSelectionIndex() + 1 ) : "" ); wInputList.setItem( wInputList.getSelectionIndex(), label ); } } ); wbInputStep.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { String stepName = selectTransformationStepname( input, input ); if ( stepName != null ) { wInputStep.setText( stepName ); definitions.get( wInputList.getSelectionIndex() ).setInputStepname( stepName ); } } } ); // What's the step name to read from? (empty is OK too) // final Label wlOutputStep = new Label( wFieldsComposite, SWT.RIGHT ); props.setLook( wlOutputStep ); wlOutputStep.setText( outputStepLabel ); FormData fdlOutputStep = new FormData(); fdlOutputStep.top = new FormAttachment( wInputStep, 10 ); fdlOutputStep.left = new FormAttachment( 0 ); wlOutputStep.setLayoutData( fdlOutputStep ); final Button wbOutputStep = new Button( wFieldsComposite, SWT.PUSH ); props.setLook( wbOutputStep ); wbOutputStep.setText( BaseMessages.getString( PKG, "MappingDialog.button.SourceStepName" ) ); FormData fdbOutputStep = new FormData(); fdbOutputStep.top = new FormAttachment( wlOutputStep, 5 ); fdbOutputStep.right = new FormAttachment( 100 ); wbOutputStep.setLayoutData( fdbOutputStep ); final Text wOutputStep = new Text( wFieldsComposite, SWT.SINGLE | SWT.LEFT | SWT.BORDER ); props.setLook( wOutputStep ); wOutputStep.addModifyListener( lsMod ); FormData fdOutputStep = new FormData(); fdOutputStep.top = new FormAttachment( wlOutputStep, 5 ); fdOutputStep.left = new FormAttachment( 0 ); // To the right of // the label fdOutputStep.right = new FormAttachment( wbOutputStep, -5 ); wOutputStep.setLayoutData( fdOutputStep ); // Allow for a small description // Label wlDescription = new Label( wFieldsComposite, SWT.RIGHT ); props.setLook( wlDescription ); wlDescription.setText( descriptionLabel ); FormData fdlDescription = new FormData(); fdlDescription.top = new FormAttachment( wOutputStep, 5 ); fdlDescription.left = new FormAttachment( 0 ); // First one in the left wlDescription.setLayoutData( fdlDescription ); final Text wDescription = new Text( wFieldsComposite, SWT.SINGLE | SWT.LEFT | SWT.BORDER ); props.setLook( wDescription ); wDescription.addModifyListener( lsMod ); FormData fdDescription = new FormData(); fdDescription.top = new FormAttachment( wlDescription, 5 ); fdDescription.left = new FormAttachment( 0 ); // To the right of // the label fdDescription.right = new FormAttachment( 100 ); wDescription.setLayoutData( fdDescription ); wDescription.addFocusListener( new FocusAdapter() { @Override public void focusLost( FocusEvent event ) { definitions.get( wInputList.getSelectionIndex() ).setDescription( wDescription.getText() ); } } ); final Button wbEnterMapping = new Button( wFieldsComposite, SWT.PUSH ); props.setLook( wbEnterMapping ); wbEnterMapping.setText( BaseMessages.getString( PKG, "MappingDialog.button.EnterMapping" ) ); FormData fdbEnterMapping = new FormData(); fdbEnterMapping.bottom = new FormAttachment( 100 ); fdbEnterMapping.right = new FormAttachment( 100 ); wbEnterMapping.setLayoutData( fdbEnterMapping ); wbEnterMapping.setEnabled( input ); ColumnInfo[] colinfo = new ColumnInfo[] { new ColumnInfo( sourceColumnLabel, ColumnInfo.COLUMN_TYPE_TEXT, false, false ), new ColumnInfo( targetColumnLabel, ColumnInfo.COLUMN_TYPE_TEXT, false, false ), }; final TableView wFieldMappings = new TableView( transMeta, wFieldsComposite, SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER, colinfo, 1, false, lsMod, props, false ); props.setLook( wFieldMappings ); FormData fdMappings = new FormData(); fdMappings.top = new FormAttachment( wDescription, 20 ); fdMappings.bottom = new FormAttachment( wbEnterMapping, -5 ); fdMappings.left = new FormAttachment( 0 ); fdMappings.right = new FormAttachment( 100 ); wFieldMappings.setLayoutData( fdMappings ); wFieldMappings.getTable().addListener( SWT.Resize, new ColumnsResizer( 0, 50, 50 ) ); wbEnterMapping.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent arg0 ) { try { RowMetaInterface sourceRowMeta = getFieldsFromStep( wInputStep.getText(), true, input ); RowMetaInterface targetRowMeta = getFieldsFromStep( wOutputStep.getText(), false, input ); String[] sourceFields = sourceRowMeta.getFieldNames(); String[] targetFields = targetRowMeta.getFieldNames(); EnterMappingDialog dialog = new EnterMappingDialog( shell, sourceFields, targetFields ); List<SourceToTargetMapping> mappings = dialog.open(); if ( mappings != null ) { // first clear the dialog... wFieldMappings.clearAll( false ); // definitions.get( wInputList.getSelectionIndex() ).getValueRenames().clear(); // Now add the new values... for ( SourceToTargetMapping mapping : mappings ) { TableItem item = new TableItem( wFieldMappings.table, SWT.NONE ); item.setText( 1, mapping.getSourceString( sourceFields ) ); item.setText( 2, mapping.getTargetString( targetFields ) ); String source = input ? item.getText( 1 ) : item.getText( 2 ); String target = input ? item.getText( 2 ) : item.getText( 1 ); definitions.get( wInputList.getSelectionIndex() ).getValueRenames().add( new MappingValueRename( source, target ) ); } wFieldMappings.removeEmptyRows(); wFieldMappings.setRowNums(); wFieldMappings.optWidth( true ); } } catch ( KettleException e ) { new ErrorDialog( shell, BaseMessages.getString( PKG, "System.Dialog.Error.Title" ), BaseMessages.getString( PKG, "MappingDialog.Exception.ErrorGettingMappingSourceAndTargetFields", e.toString() ), e ); } } } ); wOutputStep.addFocusListener( new FocusAdapter() { @Override public void focusLost( FocusEvent event ) { definitions.get( wInputList.getSelectionIndex() ).setOutputStepname( wOutputStep.getText() ); try { enableMappingButton( wbEnterMapping, input, wInputStep.getText(), wOutputStep.getText() ); } catch ( KettleException e ) { // Show the missing/wrong step name error // new ErrorDialog( shell, "Error", "Unexpected error", e ); } } } ); wbOutputStep.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { String stepName = selectTransformationStepname( !input, input ); if ( stepName != null ) { wOutputStep.setText( stepName ); definitions.get( wInputList.getSelectionIndex() ).setOutputStepname( stepName ); try { enableMappingButton( wbEnterMapping, input, wInputStep.getText(), wOutputStep.getText() ); } catch ( KettleException e ) { // Show the missing/wrong stepname error new ErrorDialog( shell, "Error", "Unexpected error", e ); } } } } ); final Button wRenameOutput; if ( input ) { // Add a checkbox to indicate that all output mappings need to rename // the values back... // wRenameOutput = new Button( wFieldsComposite, SWT.CHECK ); wRenameOutput.setText( BaseMessages.getString( PKG, "MappingDialog.input.RenamingOnOutput" ) ); props.setLook( wRenameOutput ); FormData fdRenameOutput = new FormData(); fdRenameOutput.top = new FormAttachment( wFieldMappings, 5 ); fdRenameOutput.left = new FormAttachment( 0 ); wRenameOutput.setLayoutData( fdRenameOutput ); wRenameOutput.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent event ) { definitions.get( wInputList.getSelectionIndex() ).setRenamingOnOutput( !definitions.get( wInputList.getSelectionIndex() ).isRenamingOnOutput() ); } } ); } else { wRenameOutput = null; } FormData fdInputComposite = new FormData(); fdInputComposite.left = new FormAttachment( 0 ); fdInputComposite.top = new FormAttachment( 0 ); fdInputComposite.right = new FormAttachment( 100 ); fdInputComposite.bottom = new FormAttachment( 100 ); wInputComposite.setLayoutData( fdInputComposite ); FormData fdFieldsComposite = new FormData(); fdFieldsComposite.left = new FormAttachment( wInputList, 30 ); fdFieldsComposite.right = new FormAttachment( 100 ); fdFieldsComposite.bottom = new FormAttachment( 100 ); fdFieldsComposite.top = new FormAttachment( 0 ); wFieldsComposite.setLayoutData( fdFieldsComposite ); wInputComposite.layout(); wTab.setControl( wInputComposite ); wMainPath.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent arg0 ) { setTabFlags( wMainPath, wlInputStep, wInputStep, wbInputStep, wlOutputStep, wOutputStep, wbOutputStep, wlDescription, wDescription ); } } ); wInputList.addSelectionListener( new SelectionAdapter() { @Override public void widgetSelected( SelectionEvent selectionEvent ) { updateFields( definitions.get( wInputList.getSelectionIndex() ), input, wMainPath, wlInputStep, wInputStep, wbInputStep, wlOutputStep, wOutputStep, wbOutputStep, wlDescription, wDescription, wFieldMappings, wRenameOutput ); } } ); wAddButton.addMouseListener( new MouseAdapter() { @Override public void mouseUp( MouseEvent mouseEvent ) { MappingIODefinition definition = new MappingIODefinition(); definition.setMainDataPath( true ); definitions.add( definition ); wInputList.add( tabTitle + ( definitions.size() > 1 ? String.valueOf( definitions.size() ) : "" ) ); wInputList.select( definitions.size() - 1 ); updateFields( definitions.get( wInputList.getSelectionIndex() ), input, wMainPath, wlInputStep, wInputStep, wbInputStep, wlOutputStep, wOutputStep, wbOutputStep, wlDescription, wDescription, wFieldMappings, wRenameOutput ); wlNoItems.setVisible( false ); wFieldsComposite.setVisible( true ); wRemoveButton.setEnabled( true ); } } ); wRemoveButton.addMouseListener( new MouseAdapter() { @Override public void mouseUp( MouseEvent mouseEvent ) { MessageBox box = new MessageBox( shell, SWT.YES | SWT.NO ); box.setText( BaseMessages.getString( PKG, "MappingDialog.CloseDefinitionTabAreYouSure.Title" ) ); box.setMessage( BaseMessages.getString( PKG, "MappingDialog.CloseDefinitionTabAreYouSure.Message" ) ); int answer = box.open(); if ( answer != SWT.YES ) { return; } int index = wInputList.getSelectionIndex(); definitions.remove( index ); wInputList.removeAll(); for ( int i = 0; i < definitions.size(); i++ ) { String label = !Utils.isEmpty( definitions.get( i ).getInputStepname() ) ? definitions.get( i ).getInputStepname() : tabTitle + ( i > 0 ? String.valueOf( i + 1 ) : "" ); wInputList.add( label ); } if ( index > 0 ) { wInputList.select( index - 1 ); } else if ( definitions.size() > 0 ) { wInputList.select( index ); } else { index = -1; } if ( index != -1 ) { updateFields( definitions.get( wInputList.getSelectionIndex() ), input, wMainPath, wlInputStep, wInputStep, wbInputStep, wlOutputStep, wOutputStep, wbOutputStep, wlDescription, wDescription, wFieldMappings, wRenameOutput ); } if ( definitions.size() == 0 ) { wlNoItems.setVisible( true ); wFieldsComposite.setVisible( false ); wRemoveButton.setEnabled( false ); } } } ); if ( definitions.size() > 0 ) { wInputList.select( 0 ); updateFields( definitions.get( 0 ), input, wMainPath, wlInputStep, wInputStep, wbInputStep, wlOutputStep, wOutputStep, wbOutputStep, wlDescription, wDescription, wFieldMappings, wRenameOutput ); } else { wlNoItems.setVisible( true ); wFieldsComposite.setVisible( false ); wRemoveButton.setEnabled( false ); } setTabFlags( wMainPath, wlInputStep, wInputStep, wbInputStep, wlOutputStep, wOutputStep, wbOutputStep, wlDescription, wDescription ); wTabFolder.setSelection( wTab ); } private void updateFields( MappingIODefinition definition, boolean input, Button wMainPath, Label wlInputStep, Text wInputStep, Button wbInputStep, Label wlOutputStep, Text wOutputStep, Button wbOutputStep, Label wlDescription, Text wDescription, TableView wFieldMappings, Button wRenameOutput ) { if ( tabChanges != null ) { tabChanges.applyChanges(); } wMainPath.setSelection( definition.isMainDataPath() ); wInputStep.setText( Const.NVL( definition.getInputStepname(), "" ) ); wOutputStep.setText( Const.NVL( definition.getOutputStepname(), "" ) ); wDescription.setText( Const.NVL( definition.getDescription(), "" ) ); setTabFlags( wMainPath, wlInputStep, wInputStep, wbInputStep, wlOutputStep, wOutputStep, wbOutputStep, wlDescription, wDescription ); wFieldMappings.removeAll(); for ( MappingValueRename valueRename : definition.getValueRenames() ) { TableItem tableItem = new TableItem( wFieldMappings.table, SWT.NONE ); tableItem.setText( 1, Const.NVL( valueRename.getSourceValueName(), "" ) ); tableItem.setText( 2, Const.NVL( valueRename.getTargetValueName(), "" ) ); } wFieldMappings.removeEmptyRows(); wFieldMappings.setRowNums(); wFieldMappings.optWidth( true ); if ( input ) { wRenameOutput.setSelection( definition.isRenamingOnOutput() ); } tabChanges = new MappingDefinitionTab( definition, wInputStep, wOutputStep, wMainPath, wDescription, wFieldMappings ); } private void setTabFlags( Button wMainPath, Label wlInputStep, Text wInputStep, Button wbInputStep, Label wlOutputStep, Text wOutputStep, Button wbOutputStep, Label wlDescription, Text wDescription ) { boolean mainPath = wMainPath.getSelection(); wlInputStep.setEnabled( !mainPath ); wInputStep.setEnabled( !mainPath ); wbInputStep.setEnabled( !mainPath ); wlOutputStep.setEnabled( !mainPath ); wOutputStep.setEnabled( !mainPath ); wbOutputStep.setEnabled( !mainPath ); wlDescription.setEnabled( !mainPath ); wDescription.setEnabled( !mainPath ); } /** * Enables or disables the mapping button. We can only enable it if the target steps allows a mapping to be made * against it. * * @param button The button to disable or enable * @param input input or output. If it's true, we keep the button enabled all the time. * @param sourceStepname The mapping output step * @param targetStepname The target step to verify * @throws KettleException */ private void enableMappingButton( final Button button, boolean input, String sourceStepname, String targetStepname ) throws KettleException { if ( input ) { return; // nothing to do } boolean enabled = false; if ( mappingTransMeta != null ) { StepMeta mappingInputStep = mappingTransMeta.findMappingInputStep( sourceStepname ); if ( mappingInputStep != null ) { StepMeta mappingOutputStep = transMeta.findMappingOutputStep( targetStepname ); RowMetaInterface requiredFields = mappingOutputStep.getStepMetaInterface().getRequiredFields( transMeta ); if ( requiredFields != null && requiredFields.size() > 0 ) { enabled = true; } } } button.setEnabled( enabled ); } private void cancel() { stepname = null; mappingMeta.setChanged( changed ); dispose(); } private void ok() { if ( Utils.isEmpty( wStepname.getText() ) ) { return; } stepname = wStepname.getText(); // return value try { loadTransformation(); } catch ( KettleException e ) { new ErrorDialog( shell, BaseMessages.getString( PKG, "MappingDialog.ErrorLoadingSpecifiedTransformation.Title" ), BaseMessages.getString( PKG, "MappingDialog.ErrorLoadingSpecifiedTransformation.Message" ), e ); return; } mappingMeta.setSpecificationMethod( getSpecificationMethod() ); switch ( getSpecificationMethod() ) { case FILENAME: mappingMeta.setFileName( wPath.getText() ); mappingMeta.setDirectoryPath( null ); mappingMeta.setTransName( null ); mappingMeta.setTransObjectId( null ); break; case REPOSITORY_BY_NAME: String transPath = wPath.getText(); String transName = transPath; String directory = ""; int index = transPath.lastIndexOf( "/" ); if ( index != -1 ) { transName = transPath.substring( index + 1 ); directory = transPath.substring( 0, index ); } mappingMeta.setDirectoryPath( directory ); mappingMeta.setTransName( transName ); mappingMeta.setFileName( null ); mappingMeta.setTransObjectId( null ); default: break; } // Load the information on the tabs, optionally do some // verifications... // collectInformation(); mappingMeta.setMappingParameters( mappingParameters ); mappingMeta.setInputMappings( inputMappings ); // Set the input steps for input mappings mappingMeta.searchInfoAndTargetSteps( transMeta.getSteps() ); mappingMeta.setOutputMappings( outputMappings ); mappingMeta.setAllowingMultipleInputs( true ); mappingMeta.setAllowingMultipleOutputs( true ); mappingMeta.setChanged( true ); dispose(); } private void collectInformation() { parameterChanges.applyChanges(); tabChanges.applyChanges(); } // Method is defined as package-protected in order to be accessible by unit tests ObjectId getReferenceObjectId() { return referenceObjectId; } private void setReferenceObjectId( ObjectId referenceObjectId ) { this.referenceObjectId = referenceObjectId; } // Method is defined as package-protected in order to be accessible by unit tests ObjectLocationSpecificationMethod getSpecificationMethod() { return specificationMethod; } private void setSpecificationMethod( ObjectLocationSpecificationMethod specificationMethod ) { this.specificationMethod = specificationMethod; } }