Java tutorial
/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2013 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.simplemapping; import org.apache.commons.vfs.FileObject; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; 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.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.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.trans.steps.simplemapping.SimpleMappingMeta; 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 SimpleMappingDialog extends BaseStepDialog implements StepDialogInterface { private static Class<?> PKG = SimpleMappingMeta.class; // for i18n purposes, needed by Translator2!! private SimpleMappingMeta mappingMeta; private Group gTransGroup; // 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; // Edit the mapping transformation in Spoon // private Button wEditTrans; private Button wNewTrans; private CTabFolder wTabFolder; private TransMeta mappingTransMeta = null; protected boolean transModified; private ModifyListener lsMod; private int middle; private int margin; private MappingParameters mappingParameters; private MappingIODefinition inputMapping; private MappingIODefinition outputMapping; private ObjectId referenceObjectId; private ObjectLocationSpecificationMethod specificationMethod; private interface ApplyChanges { public void applyChanges(); } private class MappingParametersTab implements ApplyChanges { private TableView wMappingParameters; private MappingParameters parameters; private Button wInheritAll; public MappingParametersTab(TableView wMappingParameters, Button wInheritAll, MappingParameters parameters) { this.wMappingParameters = wMappingParameters; this.wInheritAll = wInheritAll; this.parameters = parameters; } public void applyChanges() { int nrLines = wMappingParameters.nrNonEmpty(); String[] variables = new String[nrLines]; String[] inputFields = new String[nrLines]; parameters.setVariable(variables); parameters.setInputField(inputFields); //CHECKSTYLE:Indentation:OFF for (int i = 0; i < nrLines; i++) { TableItem item = wMappingParameters.getNonEmpty(i); parameters.getVariable()[i] = item.getText(1); parameters.getInputField()[i] = item.getText(2); } parameters.setInheritingAllVariables(wInheritAll.getSelection()); } } private class MappingDefinitionTab implements ApplyChanges { private MappingIODefinition definition; private TableView wFieldMappings; public MappingDefinitionTab(MappingIODefinition definition, TableView fieldMappings) { super(); this.definition = definition; wFieldMappings = fieldMappings; } public void applyChanges() { // 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 SimpleMappingDialog(Shell parent, Object in, TransMeta tr, String sname) { super(parent, (BaseStepMeta) in, tr, sname); mappingMeta = (SimpleMappingMeta) in; transModified = false; // Make a copy for our own purposes... // This allows us to change everything directly in the classes with // listeners. // Later we need to copy it to the input class on ok() // mappingParameters = (MappingParameters) mappingMeta.getMappingParameters().clone(); inputMapping = (MappingIODefinition) mappingMeta.getInputMapping().clone(); outputMapping = (MappingIODefinition) mappingMeta.getOutputMapping().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, "SimpleMappingDialog.Shell.Title")); middle = props.getMiddlePct(); margin = Const.MARGIN; // Stepname line wlStepname = new Label(shell, SWT.RIGHT); wlStepname.setText(BaseMessages.getString(PKG, "SimpleMappingDialog.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 // ////////////////////////////////////////////////// // gTransGroup = new Group(shell, SWT.SHADOW_ETCHED_IN); gTransGroup.setText(BaseMessages.getString(PKG, "SimpleMappingDialog.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, "SimpleMappingDialog.RadioFile.Label")); radioFilename .setToolTipText(BaseMessages.getString(PKG, "SimpleMappingDialog.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, "SimpleMappingDialog.RadioRep.Label")); radioByName.setToolTipText(BaseMessages.getString(PKG, "SimpleMappingDialog.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, "SimpleMappingDialog.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, "SimpleMappingDialog.RadioRepByReference.Label")); radioByReference.setToolTipText( BaseMessages.getString(PKG, "SimpleMappingDialog.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, "SimpleMappingDialog.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(); } }); wNewTrans = new Button(gTransGroup, SWT.PUSH | SWT.CENTER); // Browse props.setLook(wNewTrans); wNewTrans.setText(BaseMessages.getString(PKG, "SimpleMappingDialog.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(); } }); wEditTrans = new Button(gTransGroup, SWT.PUSH | SWT.CENTER); // Browse props.setLook(wEditTrans); wEditTrans.setText(BaseMessages.getString(PKG, "SimpleMappingDialog.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); // fdTransGroup.bottom = new FormAttachment(wStepname, 350); gTransGroup.setLayoutData(fdTransGroup); Control lastControl = gTransGroup; // // 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); // 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); getByReferenceData(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, "SimpleMappingDialog.ErrorSelectingObject.DialogTitle"), BaseMessages.getString(PKG, "SimpleMappingDialog.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 = null; 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 = null; 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, "SimpleMappingDialog.ErrorLoadingTransformation.DialogTitle"), BaseMessages.getString(PKG, "SimpleMappingDialog.ErrorLoadingTransformation.DialogMessage"), e); } catch (KettleException e) { new ErrorDialog(shell, BaseMessages.getString(PKG, "SimpleMappingDialog.ErrorLoadingTransformation.DialogTitle"), BaseMessages.getString(PKG, "SimpleMappingDialog.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, "SimpleMappingDialog.ErrorShowingTransformation.Title"), BaseMessages.getString(PKG, "SimpleMappingDialog.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 (Const.isEmpty(realDirectory) || Const.isEmpty(realTransname)) { throw new KettleException( BaseMessages.getString(PKG, "SimpleMappingDialog.Exception.NoValidMappingDetailsFound")); } RepositoryDirectoryInterface repdir = repository.findDirectory(realDirectory); if (repdir == null) { throw new KettleException(BaseMessages.getString(PKG, "SimpleMappingDialog.Exception.UnableToFindRepositoryDirectory")); } loadRepositoryTrans(realTransname, repdir); break; case REPOSITORY_BY_REFERENCE: if (getReferenceObjectId() == null) { throw new KettleException(BaseMessages.getString(PKG, "SimpleMappingDialog.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()); // Pass some interesting settings from the parent transformations... // newTransMeta.setUsingUniqueConnections(transMeta.isUsingUniqueConnections()); // Add MappingInput and MappingOutput steps // String INPUTSTEP_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(INPUTSTEP_NAME, inputMeta); inputStep.setLocation(50, 50); inputStep.setDraw(true); newTransMeta.addStep(inputStep); String OUTPUTSTEP_NAME = "Mapping Output"; MappingOutputMeta outputMeta = new MappingOutputMeta(); outputMeta.allocate(0); StepMeta outputStep = new StepMeta(OUTPUTSTEP_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 (!Const.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, "SimpleMappingDialog.Exception.NotConnectedToRepository.Message")); } RepositoryObject transInf = repository.getObjectInformation(transObjectId, RepositoryObjectType.TRANSFORMATION); if (transInf != null) { getByReferenceData(transInf); } } catch (KettleException e) { new ErrorDialog(shell, BaseMessages.getString(PKG, "SimpleMappingDialog.Exception.UnableToReferenceObjectId.Title"), BaseMessages.getString(PKG, "SimpleMappingDialog.Exception.UnableToReferenceObjectId.Message"), e); } } private void getByReferenceData(RepositoryElementMetaInterface transInf) { String path = transInf.getRepositoryDirectory().getPath(); if (!path.endsWith("/")) { path += "/"; } path += transInf.getName(); 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(); addInputMappingDefinitionTab(inputMapping, 0); addOutputMappingDefinitionTab(outputMapping, 1); addParametersTab(mappingParameters); wTabFolder.setSelection(0); try { loadTransformation(); } catch (Throwable t) { // Ignore errors } wStepname.selectAll(); wStepname.setFocus(); } private void addOutputMappingDefinitionTab(MappingIODefinition definition, int index) { addMappingDefinitionTab(definition, index + 1, BaseMessages.getString(PKG, "SimpleMappingDialog.OutputTab.Title"), BaseMessages.getString(PKG, "SimpleMappingDialog.OutputTab.Tooltip"), BaseMessages.getString(PKG, "SimpleMappingDialog.OutputTab.column.SourceField"), BaseMessages.getString(PKG, "SimpleMappingDialog.OutputTab.column.TargetField"), false); } private void addInputMappingDefinitionTab(MappingIODefinition definition, int index) { addMappingDefinitionTab(definition, index + 1, BaseMessages.getString(PKG, "SimpleMappingDialog.InputTab.Title"), BaseMessages.getString(PKG, "SimpleMappingDialog.InputTab.Tooltip"), BaseMessages.getString(PKG, "SimpleMappingDialog.InputTab.column.SourceField"), BaseMessages.getString(PKG, "SimpleMappingDialog.InputTab.column.TargetField"), true); } private void addParametersTab(final MappingParameters parameters) { CTabItem wParametersTab = new CTabItem(wTabFolder, SWT.NONE); wParametersTab.setText(BaseMessages.getString(PKG, "SimpleMappingDialog.Parameters.Title")); wParametersTab.setToolTipText(BaseMessages.getString(PKG, "SimpleMappingDialog.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, "SimpleMappingDialog.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, "SimpleMappingDialog.Parameters.column.Variable"), ColumnInfo.COLUMN_TYPE_TEXT, false, false), new ColumnInfo(BaseMessages.getString(PKG, "SimpleMappingDialog.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, parameters.getVariable()[i]); tableItem.setText(2, 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 MappingParametersTab(wMappingParameters, wInheritAll, parameters)); } protected String selectTransformationStepname(boolean getTransformationStep, boolean mappingInput) { String dialogTitle = BaseMessages.getString(PKG, "SimpleMappingDialog.SelectTransStep.Title"); String dialogMessage = BaseMessages.getString(PKG, "SimpleMappingDialog.SelectTransStep.Message"); if (getTransformationStep) { dialogTitle = BaseMessages.getString(PKG, "SimpleMappingDialog.SelectTransStep.Title"); dialogMessage = BaseMessages.getString(PKG, "SimpleMappingDialog.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, "SimpleMappingDialog.SelectMappingStep.Title"); dialogMessage = BaseMessages.getString(PKG, "SimpleMappingDialog.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(boolean parent, boolean input) throws KettleException { if (input) { // INPUT // if (parent) { return transMeta.getPrevStepFields(stepMeta); } else { if (mappingTransMeta == null) { throw new KettleException( BaseMessages.getString(PKG, "SimpleMappingDialog.Exception.NoMappingSpecified")); } StepMeta mappingInputStepMeta = mappingTransMeta.findMappingInputStep(null); return mappingTransMeta.getStepFields(mappingInputStepMeta); } } else { // OUTPUT // StepMeta mappingOutputStepMeta = mappingTransMeta.findMappingOutputStep(null); return mappingTransMeta.getStepFields(mappingOutputStepMeta); } } private void addMappingDefinitionTab(final MappingIODefinition definition, int index, final String tabTitle, final String tabTooltip, 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); // 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); if (input) { wbEnterMapping.setText(BaseMessages.getString(PKG, "SimpleMappingDialog.button.EnterMapping")); } else { wbEnterMapping.setText(BaseMessages.getString(PKG, "SimpleMappingDialog.button.GetFields")); } FormData fdbEnterMapping = new FormData(); fdbEnterMapping.top = new FormAttachment(0, margin * 2); fdbEnterMapping.right = new FormAttachment(100, 0); wbEnterMapping.setLayoutData(fdbEnterMapping); 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(0, margin * 2); fdMappings.bottom = new FormAttachment(100, -50); wFieldMappings.setLayoutData(fdMappings); Control 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 { if (input) { // INPUT // RowMetaInterface sourceRowMeta = getFieldsFromStep(true, input); RowMetaInterface targetRowMeta = getFieldsFromStep(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 (int i = 0; i < mappings.size(); i++) { SourceToTargetMapping mapping = mappings.get(i); 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); } } else { // OUTPUT // RowMetaInterface sourceRowMeta = getFieldsFromStep(true, input); BaseStepDialog.getFieldsFromPrevious(sourceRowMeta, wFieldMappings, 1, new int[] { 1, }, new int[] {}, -1, -1, null); } } catch (KettleException e) { new ErrorDialog(shell, BaseMessages.getString(PKG, "System.Dialog.Error.Title"), BaseMessages.getString(PKG, "SimpleMappingDialog.Exception.ErrorGettingMappingSourceAndTargetFields", e.toString()), e); } } }); if (input) { Button wRenameOutput = new Button(wInputComposite, SWT.CHECK); props.setLook(wRenameOutput); wRenameOutput.setText(BaseMessages.getString(PKG, "SimpleMappingDialog.input.RenamingOnOutput")); FormData fdRenameOutput = new FormData(); fdRenameOutput.top = new FormAttachment(lastControl, margin); fdRenameOutput.left = new FormAttachment(0, 0); fdRenameOutput.right = new FormAttachment(100, 0); wRenameOutput.setLayoutData(fdRenameOutput); wRenameOutput.setSelection(definition.isRenamingOnOutput()); wRenameOutput.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { // flip the switch definition.setRenamingOnOutput(!definition.isRenamingOnOutput()); } }); lastControl = wRenameOutput; } 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 MappingDefinitionTab(definition, wFieldMappings); changeList.add(applyChanges); wTabFolder.setSelection(wTab); } 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 (Const.isEmpty(stepname)) { wTab.setText(tabTitle); } else { wTab.setText(tabTitle + " : " + stepname); } String tooltip = tabTooltip; if (!Const.isEmpty(stepname)) { tooltip += Const.CR + Const.CR + stepname; } if (!Const.isEmpty(description)) { tooltip += Const.CR + Const.CR + description; } wTab.setToolTipText(tooltip); } private void cancel() { stepname = null; mappingMeta.setChanged(changed); dispose(); } private void ok() { if (Const.isEmpty(wStepname.getText())) { return; } stepname = wStepname.getText(); // return value try { loadTransformation(); } catch (KettleException e) { new ErrorDialog(shell, BaseMessages.getString(PKG, "SimpleMappingDialog.ErrorLoadingSpecifiedTransformation.Title"), BaseMessages.getString(PKG, "SimpleMappingDialog.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.setMappingParameters(mappingParameters); mappingMeta.setInputMapping(inputMapping); mappingMeta.setOutputMapping(outputMapping); 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; } }