/*! ******************************************************************************
*
* 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.metainject;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.vfs2.FileObject;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.ScrolledComposite;
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.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.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
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.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.ObjectLocationSpecificationMethod;
import org.pentaho.di.core.Props;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.injection.bean.BeanInjectionInfo;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.core.row.value.ValueMetaFactory;
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.RepositoryElementMetaInterface;
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.StepInjectionMetaEntry;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.step.StepMetaInjectionInterface;
import org.pentaho.di.trans.step.StepMetaInterface;
import org.pentaho.di.trans.steps.metainject.MetaInject;
import org.pentaho.di.trans.steps.metainject.MetaInjectMeta;
import org.pentaho.di.trans.steps.metainject.MetaInjectOutputField;
import org.pentaho.di.trans.steps.metainject.SourceStepField;
import org.pentaho.di.trans.steps.metainject.TargetStepAttribute;
import org.pentaho.di.ui.core.ConstUI;
import org.pentaho.di.ui.core.dialog.EnterSelectionDialog;
import org.pentaho.di.ui.core.dialog.ErrorDialog;
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.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class MetaInjectDialog extends BaseStepDialog implements StepDialogInterface {
public static final String CONST_VALUE = "<const>";
private static Class<?> PKG = MetaInjectMeta.class; // for i18n purposes, needed by Translator2!!
private MetaInjectMeta metaInjectMeta;
private Label wlPath;
private TextVar wPath;
private Button wbBrowse;
private CTabFolder wTabFolder;
private CTabItem wOptionsTab;
private ScrolledComposite wOptionsSComp;
private Composite wOptionsComp;
private CTabItem wInjectTab;
private ScrolledComposite wInjectSComp;
private Composite wInjectComp;
private TransMeta injectTransMeta = null;
protected boolean transModified;
private ModifyListener lsMod;
private ObjectId referenceObjectId;
private ObjectLocationSpecificationMethod specificationMethod;
// the source step
//
private CCombo wSourceStep;
// The source step output fields...
//
private TableView wSourceFields;
// the target file
//
private TextVar wTargetFile;
// don't execute the transformation
//
private Button wNoExecution;
// the streaming source step
//
private Label wlStreamingSourceStep;
private CCombo wStreamingSourceStep;
// the streaming target step
//
private Label wlStreamingTargetStep;
private CCombo wStreamingTargetStep;
// The tree object to show the options...
//
private Tree wTree;
private Map<TreeItem, TargetStepAttribute> treeItemTargetMap;
private Map<TargetStepAttribute, SourceStepField> targetSourceMapping;
public MetaInjectDialog( Shell parent, Object in, TransMeta tr, String sname ) {
super( parent, (BaseStepMeta) in, tr, sname );
metaInjectMeta = (MetaInjectMeta) in;
transModified = false;
targetSourceMapping = new HashMap<>();
targetSourceMapping.putAll( metaInjectMeta.getTargetSourceMapping() );
}
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, metaInjectMeta );
lsMod = new ModifyListener() {
public void modifyText( ModifyEvent e ) {
metaInjectMeta.setChanged();
}
};
changed = metaInjectMeta.hasChanged();
FormLayout formLayout = new FormLayout();
formLayout.marginWidth = 15;
formLayout.marginHeight = 15;
shell.setLayout( formLayout );
shell.setText( BaseMessages.getString( PKG, "MetaInjectDialog.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, "MetaInjectDialog.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, "MetaInjectDialog.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 );
wPath.addFocusListener( new FocusAdapter() {
@Override public void focusLost( FocusEvent focusEvent ) {
refreshTree();
}
} );
wbBrowse = new Button( shell, SWT.PUSH );
props.setLook( wbBrowse );
wbBrowse.setText( BaseMessages.getString( PKG, "MetaInjectDialog.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( true );
}
refreshTree();
}
} );
wTabFolder = new CTabFolder( shell, SWT.BORDER );
props.setLook( wTabFolder, Props.WIDGET_STYLE_TAB );
wTabFolder.setSimple( false );
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 );
addInjectTab();
addOptionsTab();
// 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();
}
};
wPath.addSelectionListener( lsDef );
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();
getData();
metaInjectMeta.setChanged( changed );
shell.open();
checkInvalidMapping();
while ( !shell.isDisposed() ) {
if ( !display.readAndDispatch() ) {
display.sleep();
}
}
return stepname;
}
private Image getImage() {
return SwtSvgImageUtil
.getImage( shell.getDisplay(), getClass().getClassLoader(), "GenericTransform.svg", ConstUI.ICON_SIZE,
ConstUI.ICON_SIZE );
}
private void checkInvalidMapping() {
if ( injectTransMeta == null ) {
try {
if ( !loadTransformation() ) {
return;
}
} catch ( KettleException e ) {
showErrorOnLoadTransformationDialog( e );
return;
}
}
Set<SourceStepField> unavailableSourceSteps =
MetaInject.getUnavailableSourceSteps( targetSourceMapping, transMeta, stepMeta );
Set<TargetStepAttribute> unavailableTargetSteps =
MetaInject.getUnavailableTargetSteps( targetSourceMapping, injectTransMeta );
Set<TargetStepAttribute> missingTargetKeys =
MetaInject.getUnavailableTargetKeys( targetSourceMapping, injectTransMeta, unavailableTargetSteps );
if ( unavailableSourceSteps.isEmpty() && unavailableTargetSteps.isEmpty() && missingTargetKeys.isEmpty() ) {
return;
}
showInvalidMappingDialog( unavailableSourceSteps, unavailableTargetSteps, missingTargetKeys );
}
private void showInvalidMappingDialog( Set<SourceStepField> unavailableSourceSteps,
Set<TargetStepAttribute> unavailableTargetSteps, Set<TargetStepAttribute> missingTargetKeys ) {
MessageBox mb = new MessageBox( shell, SWT.YES | SWT.NO | SWT.ICON_QUESTION );
mb.setMessage( BaseMessages.getString( PKG, "MetaInjectDialog.InvalidMapping.Question" ) );
mb.setText( BaseMessages.getString( PKG, "MetaInjectDialog.InvalidMapping.Title" ) );
int id = mb.open();
if ( id == SWT.YES ) {
MetaInject.removeUnavailableStepsFromMapping( targetSourceMapping, unavailableSourceSteps,
unavailableTargetSteps );
for ( TargetStepAttribute target : missingTargetKeys ) {
targetSourceMapping.remove( target );
}
}
}
private void showErrorOnLoadTransformationDialog( KettleException e ) {
new ErrorDialog( shell, BaseMessages.getString( PKG, "MetaInjectDialog.ErrorLoadingSpecifiedTransformation.Title" ),
BaseMessages.getString( PKG, "MetaInjectDialog.ErrorLoadingSpecifiedTransformation.Message" ), e );
}
private void addOptionsTab() {
// ////////////////////////
// START OF OPTIONS TAB ///
// ////////////////////////
wOptionsTab = new CTabItem( wTabFolder, SWT.NONE );
wOptionsTab.setText( BaseMessages.getString( PKG, "MetaInjectDialog.OptionsTab.TabTitle" ) );
wOptionsSComp = new ScrolledComposite( wTabFolder, SWT.V_SCROLL | SWT.H_SCROLL );
wOptionsSComp.setLayout( new FillLayout() );
wOptionsComp = new Composite( wOptionsSComp, SWT.NONE );
props.setLook( wOptionsComp );
FormLayout fileLayout = new FormLayout();
fileLayout.marginWidth = 15;
fileLayout.marginHeight = 15;
wOptionsComp.setLayout( fileLayout );
Label wlSourceStep = new Label( wOptionsComp, SWT.RIGHT );
wlSourceStep.setText( BaseMessages.getString( PKG, "MetaInjectDialog.SourceStep.Label" ) );
props.setLook( wlSourceStep );
FormData fdlSourceStep = new FormData();
fdlSourceStep.left = new FormAttachment( 0, 0 );
fdlSourceStep.top = new FormAttachment( 0, 0 );
wlSourceStep.setLayoutData( fdlSourceStep );
wSourceStep = new CCombo( wOptionsComp, SWT.SINGLE | SWT.LEFT | SWT.BORDER );
props.setLook( wSourceStep );
wSourceStep.addModifyListener( lsMod );
FormData fdSourceStep = new FormData();
fdSourceStep.width = 300;
fdSourceStep.left = new FormAttachment( 0, 0 );
fdSourceStep.top = new FormAttachment( wlSourceStep, 5 );
wSourceStep.setLayoutData( fdSourceStep );
wSourceStep.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected( SelectionEvent arg0 ) {
setActive();
}
} );
final int fieldRows = metaInjectMeta.getSourceOutputFields().size();
ColumnInfo[] colinf =
new ColumnInfo[] {
new ColumnInfo(
BaseMessages.getString( PKG, "MetaInjectDialog.ColumnInfo.Fieldname" ), ColumnInfo.COLUMN_TYPE_TEXT,
false ),
new ColumnInfo(
BaseMessages.getString( PKG, "MetaInjectDialog.ColumnInfo.Type" ), ColumnInfo.COLUMN_TYPE_CCOMBO,
ValueMetaFactory.getAllValueMetaNames() ),
new ColumnInfo(
BaseMessages.getString( PKG, "MetaInjectDialog.ColumnInfo.Length" ), ColumnInfo.COLUMN_TYPE_TEXT,
false ),
new ColumnInfo(
BaseMessages.getString( PKG, "MetaInjectDialog.ColumnInfo.Precision" ), ColumnInfo.COLUMN_TYPE_TEXT,
false ), };
wSourceFields =
new TableView( transMeta, wOptionsComp, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI, colinf, fieldRows, false,
lsMod, props, false );
FormData fdFields = new FormData();
fdFields.height = 150;
fdFields.left = new FormAttachment( 0, 0 );
fdFields.top = new FormAttachment( wSourceStep, 10 );
fdFields.right = new FormAttachment( 100, 0 );
wSourceFields.setLayoutData( fdFields );
wSourceFields.getTable().addListener( SWT.Resize, new ColumnsResizer( 0, 25, 25, 25, 25 ) );
Label wlTargetFile = new Label( wOptionsComp, SWT.RIGHT );
wlTargetFile.setText( BaseMessages.getString( PKG, "MetaInjectDialog.TargetFile.Label" ) );
props.setLook( wlTargetFile );
FormData fdlTargetFile = new FormData();
fdlTargetFile.left = new FormAttachment( 0, 0 );
fdlTargetFile.top = new FormAttachment( wSourceFields, 10 );
wlTargetFile.setLayoutData( fdlTargetFile );
wTargetFile = new TextVar( transMeta, wOptionsComp, SWT.SINGLE | SWT.LEFT | SWT.BORDER );
props.setLook( wTargetFile );
wTargetFile.addModifyListener( lsMod );
FormData fdTargetFile = new FormData();
fdTargetFile.width = 300;
fdTargetFile.left = new FormAttachment( 0, 0 );
fdTargetFile.top = new FormAttachment( wlTargetFile, 5 );
wTargetFile.setLayoutData( fdTargetFile );
wlStreamingSourceStep = new Label( wOptionsComp, SWT.RIGHT );
wlStreamingSourceStep.setText( BaseMessages.getString( PKG, "MetaInjectDialog.StreamingSourceStep.Label" ) );
props.setLook( wlStreamingSourceStep );
FormData fdlStreamingSourceStep = new FormData();
fdlStreamingSourceStep.left = new FormAttachment( 0, 0 );
fdlStreamingSourceStep.top = new FormAttachment( wTargetFile, 10 );
wlStreamingSourceStep.setLayoutData( fdlStreamingSourceStep );
wStreamingSourceStep = new CCombo( wOptionsComp, SWT.SINGLE | SWT.LEFT | SWT.BORDER );
props.setLook( wStreamingSourceStep );
FormData fdStreamingSourceStep = new FormData();
fdStreamingSourceStep.width = 300;
fdStreamingSourceStep.left = new FormAttachment( 0, 0 );
fdStreamingSourceStep.top = new FormAttachment( wlStreamingSourceStep, 5 );
wStreamingSourceStep.setLayoutData( fdStreamingSourceStep );
wStreamingSourceStep.setItems( transMeta.getStepNames() );
wStreamingSourceStep.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected( SelectionEvent arg0 ) {
setActive();
}
} );
wlStreamingTargetStep = new Label( wOptionsComp, SWT.RIGHT );
wlStreamingTargetStep.setText( BaseMessages.getString( PKG, "MetaInjectDialog.StreamingTargetStep.Label" ) );
props.setLook( wlStreamingTargetStep );
FormData fdlStreamingTargetStep = new FormData();
fdlStreamingTargetStep.left = new FormAttachment( 0, 0 );
fdlStreamingTargetStep.top = new FormAttachment( wStreamingSourceStep, 10 );
wlStreamingTargetStep.setLayoutData( fdlStreamingTargetStep );
wStreamingTargetStep = new CCombo( wOptionsComp, SWT.SINGLE | SWT.LEFT | SWT.BORDER );
props.setLook( wStreamingTargetStep );
FormData fdStreamingTargetStep = new FormData();
fdStreamingTargetStep.width = 300;
fdStreamingTargetStep.left = new FormAttachment( 0, 0 );
fdStreamingTargetStep.top = new FormAttachment( wlStreamingTargetStep, 5 );
wStreamingTargetStep.setLayoutData( fdStreamingTargetStep );
wNoExecution = new Button( wOptionsComp, SWT.CHECK );
wNoExecution.setText( BaseMessages.getString( PKG, "MetaInjectDialog.NoExecution.Label" ) );
props.setLook( wNoExecution );
FormData fdNoExecution = new FormData();
fdNoExecution.width = 250;
fdNoExecution.left = new FormAttachment( 0, 0 );
fdNoExecution.top = new FormAttachment( wStreamingTargetStep, 10 );
wNoExecution.setLayoutData( fdNoExecution );
FormData fdOptionsComp = new FormData();
fdOptionsComp.left = new FormAttachment( 0, 0 );
fdOptionsComp.top = new FormAttachment( 0, 0 );
fdOptionsComp.right = new FormAttachment( 100, 0 );
fdOptionsComp.bottom = new FormAttachment( 100, 0 );
wOptionsComp.setLayoutData( fdOptionsComp );
wOptionsComp.pack();
Rectangle bounds = wOptionsComp.getBounds();
wOptionsSComp.setContent( wOptionsComp );
wOptionsSComp.setExpandHorizontal( true );
wOptionsSComp.setExpandVertical( true );
wOptionsSComp.setMinWidth( bounds.width );
wOptionsSComp.setMinHeight( bounds.height );
wOptionsTab.setControl( wOptionsSComp );
// ///////////////////////////////////////////////////////////
// / END OF OPTIONS TAB
// ///////////////////////////////////////////////////////////
}
private void addInjectTab() {
// ////////////////////////
// START OF INJECT TAB ///
// ////////////////////////
wInjectTab = new CTabItem( wTabFolder, SWT.NONE );
wInjectTab.setText( BaseMessages.getString( PKG, "MetaInjectDialog.InjectTab.TabTitle" ) );
wInjectSComp = new ScrolledComposite( wTabFolder, SWT.V_SCROLL | SWT.H_SCROLL );
wInjectSComp.setLayout( new FillLayout() );
wInjectComp = new Composite( wInjectSComp, SWT.NONE );
props.setLook( wInjectComp );
FormLayout fileLayout = new FormLayout();
fileLayout.marginWidth = 15;
fileLayout.marginHeight = 15;
wInjectComp.setLayout( fileLayout );
wTree = new Tree( wInjectComp, SWT.SINGLE | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER );
FormData fdTree = new FormData();
fdTree.left = new FormAttachment( 0, 0 );
fdTree.top = new FormAttachment( 0, 0 );
fdTree.right = new FormAttachment( 100, 0 );
fdTree.bottom = new FormAttachment( 100, 0 );
wTree.setLayoutData( fdTree );
ColumnInfo[] colinf =
new ColumnInfo[] {
new ColumnInfo(
BaseMessages.getString( PKG, "MetaInjectDialog.Column.TargetStep" ), ColumnInfo.COLUMN_TYPE_TEXT,
false, true ),
new ColumnInfo(
BaseMessages.getString( PKG, "MetaInjectDialog.Column.TargetDescription" ),
ColumnInfo.COLUMN_TYPE_TEXT, false, true ),
new ColumnInfo(
BaseMessages.getString( PKG, "MetaInjectDialog.Column.SourceStep" ),
ColumnInfo.COLUMN_TYPE_CCOMBO, false, true ),
new ColumnInfo(
BaseMessages.getString( PKG, "MetaInjectDialog.Column.SourceField" ),
ColumnInfo.COLUMN_TYPE_CCOMBO, false, true ), };
wTree.setHeaderVisible( true );
for ( int i = 0; i < colinf.length; i++ ) {
ColumnInfo columnInfo = colinf[i];
TreeColumn treeColumn = new TreeColumn( wTree, columnInfo.getAllignement() );
treeColumn.setText( columnInfo.getName() );
treeColumn.setWidth( 200 );
}
wTree.addListener( SWT.MouseDown, new Listener() {
public void handleEvent( Event event ) {
try {
Point point = new Point( event.x, event.y );
TreeItem item = wTree.getItem( point );
if ( item != null ) {
TargetStepAttribute target = treeItemTargetMap.get( item );
if ( target != null ) {
SourceStepField source = targetSourceMapping.get( target );
String[] prevStepNames = transMeta.getPrevStepNames( stepMeta );
Arrays.sort( prevStepNames );
Map<String, SourceStepField> fieldMap = new HashMap<>();
for ( String prevStepName : prevStepNames ) {
RowMetaInterface fields = transMeta.getStepFields( prevStepName );
for ( ValueMetaInterface field : fields.getValueMetaList() ) {
String key = buildStepFieldKey( prevStepName, field.getName() );
fieldMap.put( key, new SourceStepField( prevStepName, field.getName() ) );
}
}
String[] sourceFields = fieldMap.keySet().toArray( new String[fieldMap.size()] );
Arrays.sort( sourceFields );
String constant = source != null && source.getStepname() == null ? source.getField() : "";
EnterSelectionDialog selectSourceField = new EnterSelectionDialog( shell, sourceFields,
BaseMessages.getString( PKG, "MetaInjectDialog.SourceFieldDialog.Title" ),
BaseMessages.getString( PKG, "MetaInjectDialog.SourceFieldDialog.Label" ), constant, transMeta );
if ( source != null && source.getStepname() != null && !Utils.isEmpty( source.getStepname() ) ) {
String key = buildStepFieldKey( source.getStepname(), source.getField() );
int index = Const.indexOfString( key, sourceFields );
if ( index >= 0 ) {
selectSourceField.setSelectedNrs( new int[] { index, } );
}
}
String selectedStepField = selectSourceField.open();
if ( selectedStepField != null ) {
SourceStepField newSource = fieldMap.get( selectedStepField );
if ( newSource == null ) {
newSource = new SourceStepField( null, selectedStepField );
item.setText( 2, CONST_VALUE );
item.setText( 3, selectedStepField );
} else {
item.setText( 2, newSource.getStepname() );
item.setText( 3, newSource.getField() );
}
targetSourceMapping.put( target, newSource );
} else {
item.setText( 2, "" );
item.setText( 3, "" );
targetSourceMapping.remove( target );
}
/*
* EnterSelectionDialog selectStep = new EnterSelectionDialog(shell, prevStepNames, "Select source step",
* "Select the source step"); if (source!=null && !Utils.isEmpty(source.getStepname())) { int index =
* Const.indexOfString(source.getStepname(), prevStepNames); if (index>=0) { selectStep.setSelectedNrs(new
* int[] {index,}); } } String prevStep = selectStep.open(); if (prevStep!=null) { // OK, now we list the
* fields from that step... // RowMetaInterface fields = transMeta.getStepFields(prevStep); String[]
* fieldNames = fields.getFieldNames(); Arrays.sort(fieldNames); EnterSelectionDialog selectField = new
* EnterSelectionDialog(shell, fieldNames, "Select field", "Select the source field"); if (source!=null &&
* !Utils.isEmpty(source.getField())) { int index = Const.indexOfString(source.getField(), fieldNames); if
* (index>=0) { selectField.setSelectedNrs(new int[] {index,}); } } String fieldName = selectField.open();
* if (fieldName!=null) { // Store the selection, update the UI... // item.setText(2, prevStep);
* item.setText(3, fieldName); source = new SourceStepField(prevStep, fieldName);
* targetSourceMapping.put(target, source); } } else { item.setText(2, ""); item.setText(3, "");
* targetSourceMapping.remove(target); }
*/
}
}
} catch ( Exception e ) {
new ErrorDialog( shell, "Oops", "Unexpected Error", e );
}
}
} );
FormData fdInjectComp = new FormData();
fdInjectComp.left = new FormAttachment( 0, 0 );
fdInjectComp.top = new FormAttachment( 0, 0 );
fdInjectComp.right = new FormAttachment( 100, 0 );
fdInjectComp.bottom = new FormAttachment( 100, 0 );
wInjectComp.setLayoutData( fdInjectComp );
wInjectComp.pack();
Rectangle bounds = wInjectComp.getBounds();
wInjectSComp.setContent( wInjectComp );
wInjectSComp.setExpandHorizontal( true );
wInjectSComp.setExpandVertical( true );
wInjectSComp.setMinWidth( bounds.width );
wInjectSComp.setMinHeight( bounds.height );
wInjectTab.setControl( wInjectSComp );
// ///////////////////////////////////////////////////////////
// / END OF INJECT TAB
// ///////////////////////////////////////////////////////////
}
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( injectTransMeta.getRepositoryDirectory().getPath() );
String fullPath = path + "/" + injectTransMeta.getName();
wPath.setText( fullPath );
specificationMethod = ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME;
}
} catch ( KettleException ke ) {
new ErrorDialog( shell,
BaseMessages.getString( PKG, "SingleThreaderDialog.ErrorSelectingObject.DialogTitle" ),
BaseMessages.getString( PKG, "SingleThreaderDialog.ErrorSelectingObject.DialogMessage" ), ke );
}
}
private 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...
//
injectTransMeta =
repository.loadTransformation( transMeta.environmentSubstitute( transName ), repdir, null, true, null );
injectTransMeta.clearChanged();
}
private void selectFileTrans( boolean useVfs ) {
String curFile = transMeta.environmentSubstitute( wPath.getText() );
if ( useVfs ) {
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, "SingleThreaderDialog.ErrorLoadingTransformation.DialogTitle" ),
BaseMessages.getString( PKG, "SingleThreaderDialog.ErrorLoadingTransformation.DialogMessage" ), e );
}
}
}
private void loadFileTrans( String fname ) throws KettleException {
injectTransMeta = new TransMeta( transMeta.environmentSubstitute( fname ) );
injectTransMeta.clearChanged();
}
private boolean loadTransformation() throws KettleException {
String filename = wPath.getText();
if ( repository != null ) {
specificationMethod = ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME;
} else {
specificationMethod = ObjectLocationSpecificationMethod.FILENAME;
}
switch ( specificationMethod ) {
case FILENAME:
if ( Utils.isEmpty( filename ) ) {
return false;
}
if ( !filename.endsWith( ".ktr" ) ) {
filename = filename + ".ktr";
wPath.setText( filename );
}
loadFileTrans( filename );
break;
case REPOSITORY_BY_NAME:
if ( Utils.isEmpty( filename ) ) {
return false;
}
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, "SingleThreaderDialog.Exception.NoValidMappingDetailsFound" ) );
}
RepositoryDirectoryInterface repdir = repository.findDirectory( realDirectory );
if ( repdir == null ) {
throw new KettleException( BaseMessages.getString(
PKG, "SingleThreaderDialog.Exception.UnableToFindRepositoryDirectory)" ) );
}
loadRepositoryTrans( realTransname, repdir );
break;
case REPOSITORY_BY_REFERENCE:
if ( referenceObjectId == null ) {
return false;
}
injectTransMeta = repository.loadTransformation( referenceObjectId, null ); // load the last version
injectTransMeta.clearChanged();
break;
default:
break;
}
return true;
}
public void setActive() {
boolean outputCapture = !Utils.isEmpty( wSourceStep.getText() );
wSourceFields.setEnabled( outputCapture );
boolean streaming = !Utils.isEmpty( wStreamingSourceStep.getText() );
wStreamingTargetStep.setEnabled( streaming );
wlStreamingTargetStep.setEnabled( streaming );
}
private void getByReferenceData( RepositoryElementMetaInterface transInf ) {
String path = getPath( transInf.getRepositoryDirectory().getPath() );
String fullPath =
Const.NVL( path, "" ) + "/" + Const.NVL( transInf.getName(), "" );
wPath.setText( fullPath );
}
/**
* Copy information from the meta-data input to the dialog fields.
*/
public void getData() {
specificationMethod = metaInjectMeta.getSpecificationMethod();
switch ( specificationMethod ) {
case FILENAME:
wPath.setText( Const.NVL( metaInjectMeta.getFileName(), "" ) );
break;
case REPOSITORY_BY_NAME:
String fullPath = Const.NVL( metaInjectMeta.getDirectoryPath(), "" ) + "/" + Const
.NVL( metaInjectMeta.getTransName(), "" );
wPath.setText( fullPath );
break;
case REPOSITORY_BY_REFERENCE:
referenceObjectId = metaInjectMeta.getTransObjectId();
getByReferenceData( referenceObjectId );
break;
default:
break;
}
wSourceStep.setText( Const.NVL( metaInjectMeta.getSourceStepName(), "" ) );
int rownr = 0;
for ( MetaInjectOutputField field : metaInjectMeta.getSourceOutputFields() ) {
int colnr = 1;
wSourceFields.setText( field.getName(), colnr++, rownr );
wSourceFields.setText( field.getTypeDescription(), colnr++, rownr );
wSourceFields.setText( field.getLength() < 0 ? "" : Integer.toString( field.getLength() ), colnr++, rownr );
wSourceFields.setText( field.getPrecision() < 0 ? "" : Integer.toString( field.getPrecision() ), colnr++, rownr );
rownr++;
}
wTargetFile.setText( Const.NVL( metaInjectMeta.getTargetFile(), "" ) );
wNoExecution.setSelection( !metaInjectMeta.isNoExecution() );
wStreamingSourceStep.setText( Const.NVL(
metaInjectMeta.getStreamSourceStep() == null ? null : metaInjectMeta.getStreamSourceStep().getName(), "" ) );
wStreamingTargetStep.setText( Const.NVL( metaInjectMeta.getStreamTargetStepname(), "" ) );
setActive();
refreshTree();
wTabFolder.setSelection( 0 );
wStepname.selectAll();
wStepname.setFocus();
}
protected String buildStepFieldKey( String stepname, String field ) {
return stepname + " : " + field;
}
private void refreshTree() {
try {
loadTransformation();
treeItemTargetMap = new HashMap<>();
wTree.removeAll();
TreeItem transItem = new TreeItem( wTree, SWT.NONE );
transItem.setExpanded( true );
transItem.setText( injectTransMeta.getName() );
List<StepMeta> injectSteps = new ArrayList<>();
for ( StepMeta stepMeta : injectTransMeta.getUsedSteps() ) {
StepMetaInterface meta = stepMeta.getStepMetaInterface();
if ( meta.getStepMetaInjectionInterface() != null || BeanInjectionInfo
.isInjectionSupported( meta.getClass() ) ) {
injectSteps.add( stepMeta );
}
}
Collections.sort( injectSteps );
for ( StepMeta stepMeta : injectSteps ) {
TreeItem stepItem = new TreeItem( transItem, SWT.NONE );
stepItem.setText( stepMeta.getName() );
stepItem.setExpanded( true );
// For each step, add the keys
//
StepMetaInterface metaInterface = stepMeta.getStepMetaInterface();
if ( BeanInjectionInfo.isInjectionSupported( metaInterface.getClass() ) ) {
processNewMDIDescription( stepMeta, stepItem, metaInterface );
} else {
processOldMDIDescription( stepMeta, stepItem, metaInterface.getStepMetaInjectionInterface() );
}
}
} catch ( Throwable t ) {
// Ignore errors
}
for ( TreeItem item : wTree.getItems() ) {
expandItemAndChildren( item );
}
// Also set the source step combo values
//
if ( injectTransMeta != null ) {
String[] sourceSteps = injectTransMeta.getStepNames();
Arrays.sort( sourceSteps );
wSourceStep.setItems( sourceSteps );
wStreamingTargetStep.setItems( sourceSteps );
}
}
private void processOldMDIDescription( StepMeta stepMeta, TreeItem stepItem, StepMetaInjectionInterface injection )
throws KettleException {
List<StepInjectionMetaEntry> entries = injection.getStepInjectionMetadataEntries();
for ( final StepInjectionMetaEntry entry : entries ) {
if ( entry.getValueType() != ValueMetaInterface.TYPE_NONE ) {
TreeItem entryItem = new TreeItem( stepItem, SWT.NONE );
entryItem.setText( entry.getKey() );
entryItem.setText( 1, entry.getDescription() );
TargetStepAttribute target = new TargetStepAttribute( stepMeta.getName(), entry.getKey(), false );
treeItemTargetMap.put( entryItem, target );
SourceStepField source = targetSourceMapping.get( target );
if ( source != null ) {
entryItem.setText( 2, Const.NVL( source.getStepname(), "" ) );
entryItem.setText( 3, Const.NVL( source.getField(), "" ) );
}
} else {
// Fields...
//
TreeItem listsItem = new TreeItem( stepItem, SWT.NONE );
listsItem.setText( entry.getKey() );
listsItem.setText( 1, entry.getDescription() );
StepInjectionMetaEntry listEntry = entry.getDetails().get( 0 );
listsItem.addListener( SWT.Selection, new Listener() {
@Override
public void handleEvent( Event arg0 ) {
System.out.println( entry.getKey() + " - " + entry.getDescription() );
}
} );
/*
* // Field... // TreeItem listItem = new TreeItem(listsItem, SWT.NONE);
* listItem.setText(listEntry.getKey()); listItem.setText(1, listEntry.getDescription());
*/
for ( StepInjectionMetaEntry me : listEntry.getDetails() ) {
TreeItem treeItem = new TreeItem( listsItem, SWT.NONE );
treeItem.setText( me.getKey() );
treeItem.setText( 1, me.getDescription() );
TargetStepAttribute target = new TargetStepAttribute( stepMeta.getName(), me.getKey(), true );
treeItemTargetMap.put( treeItem, target );
SourceStepField source = targetSourceMapping.get( target );
if ( source != null ) {
treeItem.setText( 2, Const.NVL( source.getStepname(), "" ) );
treeItem.setText( 3, Const.NVL( source.getField(), "" ) );
}
}
}
}
}
private void processNewMDIDescription( StepMeta stepMeta, TreeItem stepItem, StepMetaInterface metaInterface ) {
BeanInjectionInfo stepInjectionInfo = new BeanInjectionInfo( metaInterface.getClass() );
for ( BeanInjectionInfo.Group gr : stepInjectionInfo.getGroups() ) {
boolean rootGroup = StringUtils.isEmpty( gr.getName() );
TreeItem groupItem;
if ( !rootGroup ) {
groupItem = new TreeItem( stepItem, SWT.NONE );
groupItem.setText( gr.getName() );
groupItem.setText( 1, gr.getDescription() );
} else {
groupItem = null;
}
for ( BeanInjectionInfo.Property property : gr.getGroupProperties() ) {
TreeItem treeItem = new TreeItem( rootGroup ? stepItem : groupItem, SWT.NONE );
treeItem.setText( property.getName() );
treeItem.setText( 1, property.getDescription() );
TargetStepAttribute target = new TargetStepAttribute( stepMeta.getName(), property.getName(), !rootGroup );
treeItemTargetMap.put( treeItem, target );
SourceStepField source = targetSourceMapping.get( target );
if ( source != null ) {
treeItem.setText( 2, Const.NVL( source.getStepname() == null ? CONST_VALUE : source.getStepname(), "" ) );
treeItem.setText( 3, Const.NVL( source.getField(), "" ) );
}
}
}
}
private void expandItemAndChildren( TreeItem item ) {
item.setExpanded( true );
for ( TreeItem item2 : item.getItems() ) {
expandItemAndChildren( item2 );
}
}
private void cancel() {
stepname = null;
metaInjectMeta.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, "MetaInjectDialog.ErrorLoadingSpecifiedTransformation.Title" ),
BaseMessages.getString( PKG, "MetaInjectDialog.ErrorLoadingSpecifiedTransformation.Message" ), e );
}
if ( repository != null ) {
specificationMethod = ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME;
} else {
specificationMethod = ObjectLocationSpecificationMethod.FILENAME;
}
metaInjectMeta.setSpecificationMethod( specificationMethod );
switch ( specificationMethod ) {
case FILENAME:
metaInjectMeta.setFileName( wPath.getText() );
metaInjectMeta.setDirectoryPath( null );
metaInjectMeta.setTransName( null );
metaInjectMeta.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 );
}
metaInjectMeta.setDirectoryPath( directory );
metaInjectMeta.setTransName( transName );
metaInjectMeta.setFileName( null );
metaInjectMeta.setTransObjectId( null );
break;
default:
break;
}
metaInjectMeta.setSourceStepName( wSourceStep.getText() );
metaInjectMeta.setSourceOutputFields( new ArrayList<MetaInjectOutputField>() );
for ( int i = 0; i < wSourceFields.nrNonEmpty(); i++ ) {
TableItem item = wSourceFields.getNonEmpty( i );
int colIndex = 1;
String name = item.getText( colIndex++ );
int type = ValueMetaFactory.getIdForValueMeta( item.getText( colIndex++ ) );
int length = Const.toInt( item.getText( colIndex++ ), -1 );
int precision = Const.toInt( item.getText( colIndex++ ), -1 );
metaInjectMeta.getSourceOutputFields().add( new MetaInjectOutputField( name, type, length, precision ) );
}
metaInjectMeta.setTargetFile( wTargetFile.getText() );
metaInjectMeta.setNoExecution( !wNoExecution.getSelection() );
final StepMeta streamSourceStep = transMeta.findStep( wStreamingSourceStep.getText() );
metaInjectMeta.setStreamSourceStep( streamSourceStep );
// PDI-15989 Save streamSourceStepname to find streamSourceStep when loading
metaInjectMeta.setStreamSourceStepname( streamSourceStep != null ? streamSourceStep.getName() : "" );
metaInjectMeta.setStreamTargetStepname( wStreamingTargetStep.getText() );
metaInjectMeta.setTargetSourceMapping( targetSourceMapping );
metaInjectMeta.setChanged( true );
dispose();
}
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.JOB );
if ( transInf != null ) {
getByReferenceData( transInf );
}
} catch ( KettleException e ) {
new ErrorDialog( shell,
BaseMessages.getString( PKG, "MappingDialog.Exception.UnableToReferenceObjectId.Title" ),
BaseMessages.getString( PKG, "MappingDialog.Exception.UnableToReferenceObjectId.Message" ), e );
}
}
}