Java tutorial
/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ package org.pentaho.di.sdk.samples.steps.mymapping; import org.eclipse.swt.SWT; import org.eclipse.swt.events.*; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.*; import org.pentaho.di.core.Const; import org.pentaho.di.core.ObjectLocationSpecificationMethod; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.repository.ObjectId; import org.pentaho.di.trans.TransMeta; import org.pentaho.di.trans.step.BaseStepMeta; import org.pentaho.di.trans.step.StepDialogInterface; import org.pentaho.di.ui.core.widget.LabelText; import org.pentaho.di.ui.trans.step.BaseStepDialog; /** * This class is part of the mymapping step plug-in implementation. * It demonstrates the basics of developing a plug-in step for PDI. * * The mymapping step adds a new string field to the row stream and sets its * value to "Hello World!". The user may select the name of the new field. * * This class is the implementation of StepDialogInterface. * Classes implementing this interface need to: * * - build and open a SWT dialog displaying the step's settings (stored in the step's meta object) * - write back any changes the user makes to the step's meta object * - report whether the user changed any settings when confirming the dialog * */ import org.apache.commons.vfs2.FileObject; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabFolder2Adapter; import org.eclipse.swt.custom.CTabFolderEvent; 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.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; 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.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; 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.gui.SpoonFactory; import org.pentaho.di.core.gui.SpoonInterface; import org.pentaho.di.core.row.RowMeta; import org.pentaho.di.core.row.RowMetaInterface; import org.pentaho.di.core.row.ValueMetaInterface; import org.pentaho.di.core.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.TransHopMeta; 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.trans.steps.mappinginput.MappingInputMeta; import org.pentaho.di.trans.steps.mappingoutput.MappingOutputMeta; 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.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.dialog.TransDialog; import org.pentaho.di.ui.trans.step.BaseStepDialog; import org.pentaho.vfs.ui.VfsFileChooserDialog; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class MyMappingDialog extends BaseStepDialog implements StepDialogInterface { private static Class<?> PKG = MyMappingMeta.class; // for i18n purposes, needed by Translator2!! private MyMappingMeta mappingMeta; // File // private Button radioFilename; private Button wbbFilename; private TextVar wFilename; // Repository by name // private Button radioByName; private TextVar wTransname, wDirectory; private Button wbTrans; // Repository by reference // private Button radioByReference; private Button wbByReference; private TextVar wByReference; private CTabFolder wTabFolder; private TransMeta mappingTransMeta = null; protected boolean transModified; private ModifyListener lsMod; private int middle; private int margin; private MyMappingParameters mappingParameters; private List<MappingIODefinition> inputMappings; private List<MappingIODefinition> outputMappings; private Button wAddInput; private Button wAddOutput; private ObjectId referenceObjectId; private ObjectLocationSpecificationMethod specificationMethod; private Button wMultiInput, wMultiOutput; private interface ApplyChanges { public void applyChanges(); } private class MyMappingParametersTab implements ApplyChanges { private TableView wMappingParameters; private MyMappingParameters parameters; private Button wInheritAll; public MyMappingParametersTab(TableView wMappingParameters, Button wInheritAll, MyMappingParameters 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 MyMappingDefinitionTab implements ApplyChanges { private MappingIODefinition definition; private Text wInputStep; private Text wOutputStep; private Button wMainPath; private Text wDescription; private TableView wFieldMappings; public MyMappingDefinitionTab(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 List<ApplyChanges> changeList; public MyMappingDialog(Shell parent, Object in, TransMeta tr, String sname) { super(parent, (BaseStepMeta) in, tr, sname); mappingMeta = (MyMappingMeta) 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 = (MyMappingParameters) mappingMeta.getMyMappingParameters().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()); } changeList = new ArrayList<ApplyChanges>(); } 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 = Const.FORM_MARGIN; formLayout.marginHeight = Const.FORM_MARGIN; shell.setLayout(formLayout); shell.setText(BaseMessages.getString(PKG, "MappingDialog.Shell.Title")); middle = props.getMiddlePct(); margin = Const.MARGIN; // 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.right = new FormAttachment(middle, -margin); fdlStepname.top = new FormAttachment(0, margin); 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.left = new FormAttachment(middle, 0); fdStepname.top = new FormAttachment(0, margin); fdStepname.right = new FormAttachment(100, 0); wStepname.setLayoutData(fdStepname); // Show a group with 2 main options: a transformation in the repository // or on file // // ////////////////////////////////////////////////// // The key creation box // ////////////////////////////////////////////////// // Group gTransGroup = new Group(shell, SWT.SHADOW_ETCHED_IN); gTransGroup.setText(BaseMessages.getString(PKG, "MappingDialog.TransGroup.Label")); gTransGroup.setBackground(shell.getBackground()); // the default looks // ugly FormLayout transGroupLayout = new FormLayout(); transGroupLayout.marginLeft = margin * 2; transGroupLayout.marginTop = margin * 2; transGroupLayout.marginRight = margin * 2; transGroupLayout.marginBottom = margin * 2; gTransGroup.setLayout(transGroupLayout); // Radio button: The mapping is in a file // radioFilename = new Button(gTransGroup, SWT.RADIO); props.setLook(radioFilename); radioFilename.setSelection(false); radioFilename.setText(BaseMessages.getString(PKG, "MappingDialog.RadioFile.Label")); radioFilename.setToolTipText(BaseMessages.getString(PKG, "MappingDialog.RadioFile.Tooltip", Const.CR)); FormData fdFileRadio = new FormData(); fdFileRadio.left = new FormAttachment(0, 0); fdFileRadio.right = new FormAttachment(100, 0); fdFileRadio.top = new FormAttachment(0, 0); radioFilename.setLayoutData(fdFileRadio); radioFilename.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { setSpecificationMethod(ObjectLocationSpecificationMethod.FILENAME); setRadioButtons(); } }); wbbFilename = new Button(gTransGroup, SWT.PUSH | SWT.CENTER); // Browse props.setLook(wbbFilename); wbbFilename.setText(BaseMessages.getString(PKG, "System.Button.Browse")); wbbFilename.setToolTipText(BaseMessages.getString(PKG, "System.Tooltip.BrowseForFileOrDirAndAdd")); FormData fdbFilename = new FormData(); fdbFilename.right = new FormAttachment(100, 0); fdbFilename.top = new FormAttachment(radioFilename, margin); wbbFilename.setLayoutData(fdbFilename); wbbFilename.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { selectFileTrans(); } }); wFilename = new TextVar(transMeta, gTransGroup, SWT.SINGLE | SWT.LEFT | SWT.BORDER); props.setLook(wFilename); wFilename.addModifyListener(lsMod); FormData fdFilename = new FormData(); fdFilename.left = new FormAttachment(0, 25); fdFilename.right = new FormAttachment(wbbFilename, -margin); fdFilename.top = new FormAttachment(wbbFilename, 0, SWT.CENTER); wFilename.setLayoutData(fdFilename); wFilename.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { setSpecificationMethod(ObjectLocationSpecificationMethod.FILENAME); setRadioButtons(); } }); // Radio button: The mapping is in the repository // radioByName = new Button(gTransGroup, SWT.RADIO); props.setLook(radioByName); radioByName.setSelection(false); radioByName.setText(BaseMessages.getString(PKG, "MappingDialog.RadioRep.Label")); radioByName.setToolTipText(BaseMessages.getString(PKG, "MappingDialog.RadioRep.Tooltip", Const.CR)); FormData fdRepRadio = new FormData(); fdRepRadio.left = new FormAttachment(0, 0); fdRepRadio.right = new FormAttachment(100, 0); fdRepRadio.top = new FormAttachment(wbbFilename, 2 * margin); radioByName.setLayoutData(fdRepRadio); radioByName.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { setSpecificationMethod(ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME); setRadioButtons(); } }); wbTrans = new Button(gTransGroup, SWT.PUSH | SWT.CENTER); // Browse props.setLook(wbTrans); wbTrans.setText(BaseMessages.getString(PKG, "MappingDialog.Select.Button")); wbTrans.setToolTipText(BaseMessages.getString(PKG, "System.Tooltip.BrowseForFileOrDirAndAdd")); FormData fdbTrans = new FormData(); fdbTrans.right = new FormAttachment(100, 0); fdbTrans.top = new FormAttachment(radioByName, 2 * margin); wbTrans.setLayoutData(fdbTrans); wbTrans.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { selectRepositoryTrans(); } }); wDirectory = new TextVar(transMeta, gTransGroup, SWT.SINGLE | SWT.LEFT | SWT.BORDER); props.setLook(wDirectory); wDirectory.addModifyListener(lsMod); FormData fdTransDir = new FormData(); fdTransDir.left = new FormAttachment(middle + (100 - middle) / 2, 0); fdTransDir.right = new FormAttachment(wbTrans, -margin); fdTransDir.top = new FormAttachment(wbTrans, 0, SWT.CENTER); wDirectory.setLayoutData(fdTransDir); wDirectory.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { setSpecificationMethod(ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME); setRadioButtons(); } }); wTransname = new TextVar(transMeta, gTransGroup, SWT.SINGLE | SWT.LEFT | SWT.BORDER); props.setLook(wTransname); wTransname.addModifyListener(lsMod); FormData fdTransName = new FormData(); fdTransName.left = new FormAttachment(0, 25); fdTransName.right = new FormAttachment(wDirectory, -margin); fdTransName.top = new FormAttachment(wbTrans, 0, SWT.CENTER); wTransname.setLayoutData(fdTransName); wTransname.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { setSpecificationMethod(ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME); setRadioButtons(); } }); // Radio button: The mapping is in the repository // radioByReference = new Button(gTransGroup, SWT.RADIO); props.setLook(radioByReference); radioByReference.setSelection(false); radioByReference.setText(BaseMessages.getString(PKG, "MappingDialog.RadioRepByReference.Label")); radioByReference .setToolTipText(BaseMessages.getString(PKG, "MappingDialog.RadioRepByReference.Tooltip", Const.CR)); FormData fdRadioByReference = new FormData(); fdRadioByReference.left = new FormAttachment(0, 0); fdRadioByReference.right = new FormAttachment(100, 0); fdRadioByReference.top = new FormAttachment(wTransname, 2 * margin); radioByReference.setLayoutData(fdRadioByReference); radioByReference.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { setSpecificationMethod(ObjectLocationSpecificationMethod.REPOSITORY_BY_REFERENCE); setRadioButtons(); } }); wbByReference = new Button(gTransGroup, SWT.PUSH | SWT.CENTER); props.setLook(wbByReference); wbByReference.setImage(GUIResource.getInstance().getImageTransGraph()); wbByReference.setToolTipText(BaseMessages.getString(PKG, "MappingDialog.SelectTrans.Tooltip")); FormData fdbByReference = new FormData(); fdbByReference.top = new FormAttachment(radioByReference, margin); fdbByReference.right = new FormAttachment(100, 0); wbByReference.setLayoutData(fdbByReference); wbByReference.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { selectTransformationByReference(); } }); wByReference = new TextVar(transMeta, gTransGroup, SWT.SINGLE | SWT.LEFT | SWT.BORDER | SWT.READ_ONLY); props.setLook(wByReference); wByReference.addModifyListener(lsMod); FormData fdByReference = new FormData(); fdByReference.top = new FormAttachment(radioByReference, margin); fdByReference.left = new FormAttachment(0, 25); fdByReference.right = new FormAttachment(wbByReference, -margin); wByReference.setLayoutData(fdByReference); wByReference.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { setSpecificationMethod(ObjectLocationSpecificationMethod.REPOSITORY_BY_REFERENCE); setRadioButtons(); } }); Button wNewTrans = new Button(gTransGroup, SWT.PUSH | SWT.CENTER); props.setLook(wNewTrans); wNewTrans.setText(BaseMessages.getString(PKG, "MappingDialog.New.Button")); FormData fdNewTrans = new FormData(); fdNewTrans.left = new FormAttachment(0, 0); fdNewTrans.top = new FormAttachment(wByReference, 3 * margin); wNewTrans.setLayoutData(fdNewTrans); wNewTrans.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { newTransformation(); } }); Button wEditTrans = new Button(gTransGroup, SWT.PUSH | SWT.CENTER); props.setLook(wEditTrans); wEditTrans.setText(BaseMessages.getString(PKG, "MappingDialog.Edit.Button")); wEditTrans.setToolTipText(BaseMessages.getString(PKG, "System.Tooltip.BrowseForFileOrDirAndAdd")); FormData fdEditTrans = new FormData(); fdEditTrans.left = new FormAttachment(wNewTrans, 2 * margin); fdEditTrans.top = new FormAttachment(wByReference, 3 * margin); wEditTrans.setLayoutData(fdEditTrans); wEditTrans.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { editTrans(); } }); FormData fdTransGroup = new FormData(); fdTransGroup.left = new FormAttachment(0, 0); fdTransGroup.top = new FormAttachment(wStepname, 2 * margin); fdTransGroup.right = new FormAttachment(100, 0); gTransGroup.setLayoutData(fdTransGroup); Control lastControl = gTransGroup; wMultiInput = new Button(shell, SWT.CHECK); props.setLook(wMultiInput); wMultiInput.setText(BaseMessages.getString(PKG, "MappingDialog.AllowMultipleInputs.Label")); FormData fdMultiInput = new FormData(); fdMultiInput.left = new FormAttachment(0, 0); fdMultiInput.right = new FormAttachment(100, 0); fdMultiInput.top = new FormAttachment(lastControl, margin * 2); wMultiInput.setLayoutData(fdMultiInput); wMultiInput.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { setFlags(); } }); lastControl = wMultiInput; wMultiOutput = new Button(shell, SWT.CHECK); props.setLook(wMultiOutput); wMultiOutput.setText(BaseMessages.getString(PKG, "MappingDialog.AllowMultipleOutputs.Label")); FormData fdMultiOutput = new FormData(); fdMultiOutput.left = new FormAttachment(0, 0); fdMultiOutput.right = new FormAttachment(100, 0); fdMultiOutput.top = new FormAttachment(lastControl, margin); wMultiOutput.setLayoutData(fdMultiOutput); wMultiOutput.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { setFlags(); } }); lastControl = wMultiOutput; // // 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); FormData fdTabFolder = new FormData(); fdTabFolder.left = new FormAttachment(0, 0); fdTabFolder.right = new FormAttachment(100, 0); fdTabFolder.top = new FormAttachment(lastControl, margin * 2); fdTabFolder.bottom = new FormAttachment(100, -75); wTabFolder.setLayoutData(fdTabFolder); // Now add buttons that will allow us to add or remove input or output // tabs... wAddInput = new Button(shell, SWT.PUSH); props.setLook(wAddInput); wAddInput.setText(BaseMessages.getString(PKG, "MappingDialog.button.AddInput")); wAddInput.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { // Simply add a new MappingIODefinition object to the // inputMappings MappingIODefinition definition = new MappingIODefinition(); definition.setRenamingOnOutput(true); inputMappings.add(definition); int index = inputMappings.size() - 1; addInputMappingDefinitionTab(definition, index); setFlags(); } }); wAddOutput = new Button(shell, SWT.PUSH); props.setLook(wAddOutput); wAddOutput.setText(BaseMessages.getString(PKG, "MappingDialog.button.AddOutput")); wAddOutput.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { // Simply add a new MappingIODefinition object to the // inputMappings MappingIODefinition definition = new MappingIODefinition(); outputMappings.add(definition); int index = outputMappings.size() - 1; addOutputMappingDefinitionTab(definition, index); setFlags(); } }); setButtonPositions(new Button[] { wAddInput, wAddOutput }, margin, wTabFolder); // Some buttons wOK = new Button(shell, SWT.PUSH); wOK.setText(BaseMessages.getString(PKG, "System.Button.OK")); wCancel = new Button(shell, SWT.PUSH); wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel")); setButtonPositions(new Button[] { wOK, wCancel }, margin, null); // 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); wFilename.addSelectionListener(lsDef); wTransname.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(); mappingMeta.setChanged(changed); wTabFolder.setSelection(0); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } return stepname; } protected void selectTransformationByReference() { if (repository != null) { SelectObjectDialog sod = new SelectObjectDialog(shell, repository, true, false); sod.open(); RepositoryElementMetaInterface repositoryObject = sod.getRepositoryObject(); if (repositoryObject != null) { setSpecificationMethod(ObjectLocationSpecificationMethod.REPOSITORY_BY_REFERENCE); updateByReferenceField(repositoryObject); setReferenceObjectId(repositoryObject.getObjectId()); setRadioButtons(); } } } 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); wTransname.setText(mappingTransMeta.getName()); wDirectory.setText(mappingTransMeta.getRepositoryDirectory().getPath()); wFilename.setText(""); radioByName.setSelection(true); radioFilename.setSelection(false); setSpecificationMethod(ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME); setRadioButtons(); } } catch (KettleException ke) { new ErrorDialog(shell, BaseMessages.getString(PKG, "MappingDialog.ErrorSelectingObject.DialogTitle"), BaseMessages.getString(PKG, "MappingDialog.ErrorSelectingObject.DialogMessage"), ke); } } 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 = wFilename.getText(); FileObject root; 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 fname; fname = file.getURL().getFile(); if (fname != null) { loadFileTrans(fname); wFilename.setText(mappingTransMeta.getFilename()); wTransname.setText(Const.NVL(mappingTransMeta.getName(), "")); wDirectory.setText(""); setSpecificationMethod(ObjectLocationSpecificationMethod.FILENAME); setRadioButtons(); } } catch (IOException e) { new ErrorDialog(shell, BaseMessages.getString(PKG, "MappingDialog.ErrorLoadingTransformation.DialogTitle"), BaseMessages.getString(PKG, "MappingDialog.ErrorLoadingTransformation.DialogMessage"), e); } catch (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(); } private void editTrans() { // Load the transformation again to make sure it's still there and // refreshed // It's an extra check to make sure it's still OK... // try { loadTransformation(); // If we're still here, mappingTransMeta is valid. // SpoonInterface spoon = SpoonFactory.getInstance(); if (spoon != null) { spoon.addTransGraph(mappingTransMeta); } } catch (KettleException e) { new ErrorDialog(shell, BaseMessages.getString(PKG, "MappingDialog.ErrorShowingTransformation.Title"), BaseMessages.getString(PKG, "MappingDialog.ErrorShowingTransformation.Message"), e); } } // Method is defined as package-protected in order to be accessible by unit tests void loadTransformation() throws KettleException { switch (getSpecificationMethod()) { case FILENAME: loadFileTrans(wFilename.getText()); break; case REPOSITORY_BY_NAME: String realDirectory = transMeta.environmentSubstitute(wDirectory.getText()); String realTransname = transMeta.environmentSubstitute(wTransname.getText()); 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; case REPOSITORY_BY_REFERENCE: if (getReferenceObjectId() == null) { throw new KettleException( BaseMessages.getString(PKG, "MappingDialog.Exception.ReferencedTransformationIdIsNull")); } mappingTransMeta = repository.loadTransformation(getReferenceObjectId(), null); // load the last version mappingTransMeta.clearChanged(); break; default: break; } } public void setActive() { boolean supportsReferences = repository != null && repository.getRepositoryMeta().getRepositoryCapabilities().supportsReferences(); radioByName.setEnabled(repository != null); radioByReference.setEnabled(repository != null && supportsReferences); wFilename.setEnabled(radioFilename.getSelection()); wbbFilename.setEnabled(radioFilename.getSelection()); wTransname.setEnabled(repository != null && radioByName.getSelection()); wDirectory.setEnabled(repository != null && radioByName.getSelection()); wbTrans.setEnabled(repository != null && radioByName.getSelection()); wByReference.setEnabled(repository != null && radioByReference.getSelection() && supportsReferences); wbByReference.setEnabled(repository != null && radioByReference.getSelection() && supportsReferences); } protected void setRadioButtons() { radioFilename.setSelection(getSpecificationMethod() == ObjectLocationSpecificationMethod.FILENAME); radioByName.setSelection(getSpecificationMethod() == ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME); radioByReference.setSelection( getSpecificationMethod() == ObjectLocationSpecificationMethod.REPOSITORY_BY_REFERENCE); setActive(); } /** * Ask the user to fill in the details... */ protected void newTransformation() { // Get input fields for this step so we can put this metadata in the mapping // RowMetaInterface inFields = new RowMeta(); try { inFields = transMeta.getPrevStepFields(stepname); } catch (Exception e) { // Just show the error but continue operations. // new ErrorDialog(shell, "Error", "Unable to get input fields from previous step", e); } TransMeta newTransMeta = new TransMeta(); newTransMeta.getDatabases().addAll(transMeta.getDatabases()); newTransMeta.setRepository(transMeta.getRepository()); newTransMeta.setRepositoryDirectory(transMeta.getRepositoryDirectory()); // Pass some interesting settings from the parent transformations... // newTransMeta.setUsingUniqueConnections(transMeta.isUsingUniqueConnections()); // Add MappingInput and MappingOutput steps // String INPUT_STEP_NAME = "Mapping Input"; MappingInputMeta inputMeta = new MappingInputMeta(); inputMeta.allocate(inFields.size()); //CHECKSTYLE:Indentation:OFF for (int i = 0; i < inFields.size(); i++) { ValueMetaInterface valueMeta = inFields.getValueMeta(i); inputMeta.getFieldName()[i] = valueMeta.getName(); inputMeta.getFieldType()[i] = valueMeta.getType(); inputMeta.getFieldLength()[i] = valueMeta.getLength(); inputMeta.getFieldPrecision()[i] = valueMeta.getPrecision(); } StepMeta inputStep = new StepMeta(INPUT_STEP_NAME, inputMeta); inputStep.setLocation(50, 50); inputStep.setDraw(true); newTransMeta.addStep(inputStep); String OUTPUT_STEP_NAME = "Mapping Output"; MappingOutputMeta outputMeta = new MappingOutputMeta(); outputMeta.allocate(0); StepMeta outputStep = new StepMeta(OUTPUT_STEP_NAME, outputMeta); outputStep.setLocation(500, 50); outputStep.setDraw(true); newTransMeta.addStep(outputStep); newTransMeta.addTransHop(new TransHopMeta(inputStep, outputStep)); TransDialog transDialog = new TransDialog(shell, SWT.NONE, newTransMeta, repository); if (transDialog.open() != null) { Spoon spoon = Spoon.getInstance(); spoon.addTransGraph(newTransMeta); boolean saved = false; try { if (repository != null) { if (!Utils.isEmpty(newTransMeta.getName())) { wStepname.setText(newTransMeta.getName()); } saved = spoon.saveToRepository(newTransMeta, false); if (repository.getRepositoryMeta().getRepositoryCapabilities().supportsReferences()) { setSpecificationMethod(ObjectLocationSpecificationMethod.REPOSITORY_BY_REFERENCE); } else { setSpecificationMethod(ObjectLocationSpecificationMethod.REPOSITORY_BY_NAME); } } else { saved = spoon.saveToFile(newTransMeta); setSpecificationMethod(ObjectLocationSpecificationMethod.FILENAME); } } catch (Exception e) { new ErrorDialog(shell, "Error", "Error saving new transformation", e); } if (saved) { setRadioButtons(); switch (getSpecificationMethod()) { case FILENAME: wFilename.setText(Const.NVL(newTransMeta.getFilename(), "")); break; case REPOSITORY_BY_NAME: wTransname.setText(Const.NVL(newTransMeta.getName(), "")); wDirectory.setText(newTransMeta.getRepositoryDirectory().getPath()); break; case REPOSITORY_BY_REFERENCE: getByReferenceData(newTransMeta.getObjectId()); 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); updateByReferenceField(transInf); } catch (KettleException e) { new ErrorDialog(shell, BaseMessages.getString(PKG, "MappingDialog.Exception.UnableToReferenceObjectId.Title"), BaseMessages.getString(PKG, "MappingDialog.Exception.UnableToReferenceObjectId.Message"), e); } } private void updateByReferenceField(RepositoryElementMetaInterface element) { String path = getPathOf(element); if (path == null) { path = ""; } wByReference.setText(path); } /** * Copy information from the meta-data input to the dialog fields. */ public void getData() { setSpecificationMethod(mappingMeta.getSpecificationMethod()); switch (getSpecificationMethod()) { case FILENAME: wFilename.setText(Const.NVL(mappingMeta.getFileName(), "")); break; case REPOSITORY_BY_NAME: wDirectory.setText(Const.NVL(mappingMeta.getDirectoryPath(), "")); wTransname.setText(Const.NVL(mappingMeta.getTransName(), "")); break; case REPOSITORY_BY_REFERENCE: wByReference.setText(""); if (mappingMeta.getTransObjectId() != null) { setReferenceObjectId(mappingMeta.getTransObjectId()); getByReferenceData(getReferenceObjectId()); } break; default: break; } setRadioButtons(); // Add the parameters tab addParametersTab(mappingParameters); wTabFolder.setSelection(0); wMultiInput.setSelection(mappingMeta.isAllowingMultipleInputs()); wMultiOutput.setSelection(mappingMeta.isAllowingMultipleOutputs()); // Now add the input stream tabs: where is our data coming from? for (int i = 0; i < inputMappings.size(); i++) { addInputMappingDefinitionTab(inputMappings.get(i), i); } // Now add the output stream tabs: where is our data going to? for (int i = 0; i < outputMappings.size(); i++) { addOutputMappingDefinitionTab(outputMappings.get(i), i); } try { loadTransformation(); } catch (Throwable t) { // Ignore errors } setFlags(); wStepname.selectAll(); wStepname.setFocus(); } private void addOutputMappingDefinitionTab(MappingIODefinition definition, int index) { addMappingDefinitionTab(outputMappings.get(index), index + 1 + inputMappings.size(), BaseMessages.getString(PKG, "MappingDialog.OutputTab.Title"), BaseMessages.getString(PKG, "MappingDialog.OutputTab.Tooltip"), 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"), false); } private void addInputMappingDefinitionTab(MappingIODefinition definition, int index) { addMappingDefinitionTab(definition, index + 1, BaseMessages.getString(PKG, "MappingDialog.InputTab.Title"), BaseMessages.getString(PKG, "MappingDialog.InputTab.Tooltip"), 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"), true); } private void addParametersTab(final MyMappingParameters 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 = Const.FORM_MARGIN; parameterTabLayout.marginHeight = Const.FORM_MARGIN; 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, -margin * 2); wMappingParameters.setLayoutData(fdMappings); 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); changeList.add(new MyMappingParametersTab(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(final MappingIODefinition definition, int index, final String tabTitle, final String tabTooltip, String inputStepLabel, String outputStepLabel, String descriptionLabel, String sourceColumnLabel, String targetColumnLabel, final boolean input) { final CTabItem wTab; if (index >= wTabFolder.getItemCount()) { wTab = new CTabItem(wTabFolder, SWT.CLOSE); } else { wTab = new CTabItem(wTabFolder, SWT.CLOSE, index); } setMappingDefinitionTabNameAndToolTip(wTab, tabTitle, tabTooltip, definition, input); Composite wInputComposite = new Composite(wTabFolder, SWT.NONE); props.setLook(wInputComposite); FormLayout tabLayout = new FormLayout(); tabLayout.marginWidth = Const.FORM_MARGIN; tabLayout.marginHeight = Const.FORM_MARGIN; wInputComposite.setLayout(tabLayout); // What's the stepname to read from? (empty is OK too) // final Button wbInputStep = new Button(wInputComposite, SWT.PUSH); props.setLook(wbInputStep); wbInputStep.setText(BaseMessages.getString(PKG, "MappingDialog.button.SourceStepName")); FormData fdbInputStep = new FormData(); fdbInputStep.top = new FormAttachment(0, 0); fdbInputStep.right = new FormAttachment(100, 0); // First one in the // left top corner wbInputStep.setLayoutData(fdbInputStep); final Label wlInputStep = new Label(wInputComposite, SWT.RIGHT); props.setLook(wlInputStep); wlInputStep.setText(inputStepLabel); FormData fdlInputStep = new FormData(); fdlInputStep.top = new FormAttachment(wbInputStep, 0, SWT.CENTER); fdlInputStep.left = new FormAttachment(0, 0); // First one in the left // top corner fdlInputStep.right = new FormAttachment(middle, -margin); wlInputStep.setLayoutData(fdlInputStep); final Text wInputStep = new Text(wInputComposite, SWT.SINGLE | SWT.LEFT | SWT.BORDER); props.setLook(wInputStep); wInputStep.setText(Const.NVL(definition.getInputStepname(), "")); wInputStep.addModifyListener(lsMod); FormData fdInputStep = new FormData(); fdInputStep.top = new FormAttachment(wbInputStep, 0, SWT.CENTER); fdInputStep.left = new FormAttachment(middle, 0); // To the right of // the label fdInputStep.right = new FormAttachment(wbInputStep, -margin); wInputStep.setLayoutData(fdInputStep); wInputStep.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent event) { definition.setInputStepname(wInputStep.getText()); setMappingDefinitionTabNameAndToolTip(wTab, tabTitle, tabTooltip, definition, input); } }); wbInputStep.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { String stepName = selectTransformationStepname(input, input); if (stepName != null) { wInputStep.setText(stepName); definition.setInputStepname(stepName); setMappingDefinitionTabNameAndToolTip(wTab, tabTitle, tabTooltip, definition, input); } } }); // What's the step name to read from? (empty is OK too) // final Button wbOutputStep = new Button(wInputComposite, SWT.PUSH); props.setLook(wbOutputStep); wbOutputStep.setText(BaseMessages.getString(PKG, "MappingDialog.button.SourceStepName")); FormData fdbOutputStep = new FormData(); fdbOutputStep.top = new FormAttachment(wbInputStep, margin); fdbOutputStep.right = new FormAttachment(100, 0); wbOutputStep.setLayoutData(fdbOutputStep); final Label wlOutputStep = new Label(wInputComposite, SWT.RIGHT); props.setLook(wlOutputStep); wlOutputStep.setText(outputStepLabel); FormData fdlOutputStep = new FormData(); fdlOutputStep.top = new FormAttachment(wbOutputStep, 0, SWT.CENTER); fdlOutputStep.left = new FormAttachment(0, 0); fdlOutputStep.right = new FormAttachment(middle, -margin); wlOutputStep.setLayoutData(fdlOutputStep); final Text wOutputStep = new Text(wInputComposite, SWT.SINGLE | SWT.LEFT | SWT.BORDER); props.setLook(wOutputStep); wOutputStep.setText(Const.NVL(definition.getOutputStepname(), "")); wOutputStep.addModifyListener(lsMod); FormData fdOutputStep = new FormData(); fdOutputStep.top = new FormAttachment(wbOutputStep, 0, SWT.CENTER); fdOutputStep.left = new FormAttachment(middle, 0); // To the right of // the label fdOutputStep.right = new FormAttachment(wbOutputStep, -margin); wOutputStep.setLayoutData(fdOutputStep); // Add a checkbox to indicate the main step to read from, the main data // path... // final Label wlMainPath = new Label(wInputComposite, SWT.RIGHT); props.setLook(wlMainPath); wlMainPath.setText(BaseMessages.getString(PKG, "MappingDialog.input.MainDataPath")); FormData fdlMainPath = new FormData(); fdlMainPath.top = new FormAttachment(wbOutputStep, margin); fdlMainPath.left = new FormAttachment(0, 0); fdlMainPath.right = new FormAttachment(middle, -margin); wlMainPath.setLayoutData(fdlMainPath); final Button wMainPath = new Button(wInputComposite, SWT.CHECK); props.setLook(wMainPath); FormData fdMainPath = new FormData(); fdMainPath.top = new FormAttachment(wbOutputStep, margin); fdMainPath.left = new FormAttachment(middle, 0); // fdMainPath.right = new FormAttachment(100, 0); // who cares, it's a // checkbox wMainPath.setLayoutData(fdMainPath); wMainPath.setSelection(definition.isMainDataPath()); wMainPath.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { definition.setMainDataPath(!definition.isMainDataPath()); // flip // the // switch } }); Control lastControl = wMainPath; // Allow for a small description // Label wlDescription = new Label(wInputComposite, SWT.RIGHT); props.setLook(wlDescription); wlDescription.setText(descriptionLabel); FormData fdlDescription = new FormData(); fdlDescription.top = new FormAttachment(lastControl, margin); fdlDescription.left = new FormAttachment(0, 0); // First one in the left // top corner fdlDescription.right = new FormAttachment(middle, -margin); wlDescription.setLayoutData(fdlDescription); final Text wDescription = new Text(wInputComposite, SWT.MULTI | SWT.LEFT | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); props.setLook(wDescription); wDescription.setText(Const.NVL(definition.getDescription(), "")); wDescription.addModifyListener(lsMod); FormData fdDescription = new FormData(); fdDescription.top = new FormAttachment(lastControl, margin); fdDescription.bottom = new FormAttachment(lastControl, 100 + margin); fdDescription.left = new FormAttachment(middle, 0); // To the right of // the label fdDescription.right = new FormAttachment(wbOutputStep, -margin); wDescription.setLayoutData(fdDescription); wDescription.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent event) { definition.setDescription(wDescription.getText()); } }); lastControl = wDescription; // Now add a table view with the 2 columns to specify: input and output // fields for the source and target steps. // final Button wbEnterMapping = new Button(wInputComposite, SWT.PUSH); props.setLook(wbEnterMapping); wbEnterMapping.setText(BaseMessages.getString(PKG, "MappingDialog.button.EnterMapping")); FormData fdbEnterMapping = new FormData(); fdbEnterMapping.top = new FormAttachment(lastControl, margin * 2); fdbEnterMapping.right = new FormAttachment(100, 0); // First one in the // left top corner 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, wInputComposite, SWT.FULL_SELECTION | SWT.SINGLE | SWT.BORDER, colinfo, 1, lsMod, props); props.setLook(wFieldMappings); FormData fdMappings = new FormData(); fdMappings.left = new FormAttachment(0, 0); fdMappings.right = new FormAttachment(wbEnterMapping, -margin); fdMappings.top = new FormAttachment(lastControl, margin * 2); fdMappings.bottom = new FormAttachment(100, -50); wFieldMappings.setLayoutData(fdMappings); lastControl = wFieldMappings; 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); 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); // definition.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); definition.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) { definition.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); definition.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); } } } }); if (input) { // Add a checkbox to indicate that all output mappings need to rename // the values back... // Label wlRenameOutput = new Label(wInputComposite, SWT.RIGHT); props.setLook(wlRenameOutput); wlRenameOutput.setText(BaseMessages.getString(PKG, "MappingDialog.input.RenamingOnOutput")); FormData fdlRenameOutput = new FormData(); fdlRenameOutput.top = new FormAttachment(lastControl, margin); fdlRenameOutput.left = new FormAttachment(0, 0); fdlRenameOutput.right = new FormAttachment(middle, -margin); wlRenameOutput.setLayoutData(fdlRenameOutput); Button wRenameOutput = new Button(wInputComposite, SWT.CHECK); props.setLook(wRenameOutput); FormData fdRenameOutput = new FormData(); fdRenameOutput.top = new FormAttachment(lastControl, margin); fdRenameOutput.left = new FormAttachment(middle, 0); // fdRenameOutput.right = new FormAttachment(100, 0); // who cares, it's // a check box wRenameOutput.setLayoutData(fdRenameOutput); wRenameOutput.setSelection(definition.isRenamingOnOutput()); wRenameOutput.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { definition.setRenamingOnOutput(!definition.isRenamingOnOutput()); // flip // the // switch } }); } 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); wInputComposite.setLayoutData(fdParametersComposite); wInputComposite.layout(); wTab.setControl(wInputComposite); final ApplyChanges applyChanges = new MyMappingDefinitionTab(definition, wInputStep, wOutputStep, wMainPath, wDescription, wFieldMappings); changeList.add(applyChanges); // OK, suppose for some weird reason the user wants to remove an input // or output tab... wTabFolder.addCTabFolder2Listener(new CTabFolder2Adapter() { @Override public void close(CTabFolderEvent event) { if (event.item.equals(wTab)) { // The user has the audacity to try and close this mapping // definition tab. // We really should warn him that this is a bad idea... 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) { event.doit = false; } else { // Remove it from our list to make sure it's gone... if (input) { inputMappings.remove(definition); } else { outputMappings.remove(definition); } // remove it from the changeList too... // Otherwise the dialog leaks memory. // changeList.remove(applyChanges); } setFlags(); } } }); wMultiInput.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent arg0) { setTabFlags(input, wlMainPath, wMainPath, wlInputStep, wInputStep, wbInputStep, wlOutputStep, wOutputStep, wbOutputStep); } }); wMultiOutput.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent arg0) { setTabFlags(input, wlMainPath, wMainPath, wlInputStep, wInputStep, wbInputStep, wlOutputStep, wOutputStep, wbOutputStep); } }); wMainPath.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent arg0) { setTabFlags(input, wlMainPath, wMainPath, wlInputStep, wInputStep, wbInputStep, wlOutputStep, wOutputStep, wbOutputStep); } }); setTabFlags(input, wlMainPath, wMainPath, wlInputStep, wInputStep, wbInputStep, wlOutputStep, wOutputStep, wbOutputStep); wTabFolder.setSelection(wTab); } private void setTabFlags(boolean input, Label wlMainPath, Button wMainPath, Label wlInputStep, Text wInputStep, Button wbInputStep, Label wlOutputStep, Text wOutputStep, Button wbOutputStep) { boolean multiInput = wMultiInput.getSelection(); boolean multiOutput = wMultiOutput.getSelection(); if (multiInput) { wlMainPath.setEnabled(true); wMainPath.setEnabled(true); } else { wMainPath.setSelection(true); wMainPath.setEnabled(false); wlMainPath.setEnabled(false); } boolean mainPath = wMainPath.getSelection(); if (input) { wlInputStep.setEnabled(!mainPath); wInputStep.setEnabled(!mainPath); wbInputStep.setEnabled(!mainPath); wlOutputStep.setEnabled(multiInput); wOutputStep.setEnabled(multiInput); wbOutputStep.setEnabled(multiInput); } else { wlInputStep.setEnabled(multiOutput); wInputStep.setEnabled(multiOutput); wbInputStep.setEnabled(multiOutput); wlOutputStep.setEnabled(!mainPath); wOutputStep.setEnabled(!mainPath); wbOutputStep.setEnabled(!mainPath); } } private void setFlags() { // Enable/disable fields... // boolean allowMultiInput = wMultiInput.getSelection(); boolean allowMultiOutput = wMultiOutput.getSelection(); wAddInput.setEnabled(allowMultiInput || inputMappings.size() == 0); wAddOutput.setEnabled(allowMultiOutput || outputMappings.size() == 0); } /** * 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 setMappingDefinitionTabNameAndToolTip(CTabItem wTab, String tabTitle, String tabTooltip, MappingIODefinition definition, boolean input) { String stepname; if (input) { stepname = definition.getInputStepname(); } else { stepname = definition.getOutputStepname(); } String description = definition.getDescription(); if (Utils.isEmpty(stepname)) { wTab.setText(tabTitle); } else { wTab.setText(tabTitle + " : " + stepname); } String tooltip = tabTooltip; if (!Utils.isEmpty(stepname)) { tooltip += Const.CR + Const.CR + stepname; } if (!Utils.isEmpty(description)) { tooltip += Const.CR + Const.CR + description; } wTab.setToolTipText(tooltip); } 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(wFilename.getText()); mappingMeta.setDirectoryPath(null); mappingMeta.setTransName(null); mappingMeta.setTransObjectId(null); break; case REPOSITORY_BY_NAME: mappingMeta.setDirectoryPath(wDirectory.getText()); mappingMeta.setTransName(wTransname.getText()); mappingMeta.setFileName(null); mappingMeta.setTransObjectId(null); break; case REPOSITORY_BY_REFERENCE: mappingMeta.setFileName(null); mappingMeta.setDirectoryPath(null); mappingMeta.setTransName(null); mappingMeta.setTransObjectId(getReferenceObjectId()); break; default: break; } // Load the information on the tabs, optionally do some // verifications... // collectInformation(); mappingMeta.setMyMappingParameters(mappingParameters); mappingMeta.setInputMappings(inputMappings); // Set the input steps for input mappings mappingMeta.searchInfoAndTargetSteps(transMeta.getSteps()); mappingMeta.setOutputMappings(outputMappings); mappingMeta.setAllowingMultipleInputs(wMultiInput.getSelection()); mappingMeta.setAllowingMultipleOutputs(wMultiOutput.getSelection()); mappingMeta.setChanged(true); dispose(); } private void collectInformation() { for (ApplyChanges applyChanges : changeList) { applyChanges.applyChanges(); // collect information from all // tabs... } } // 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; } }