Java tutorial
/********************************************************************** ** ** ** This code belongs to the KETTLE project. ** ** ** ** Kettle, from version 2.2 on, is released into the public domain ** ** under the Lesser GNU Public License (LGPL). ** ** ** ** For more details, please read the document LICENSE.txt, included ** ** in this project ** ** ** ** http://www.kettle.be ** ** info@kettle.be ** ** ** **********************************************************************/ package be.ibridge.kettle.spoon; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; import org.apache.commons.vfs.FileObject; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardDialog; 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.custom.SashForm; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSource; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.DragSourceListener; import org.eclipse.swt.dnd.DropTarget; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.DropTargetListener; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.printing.Printer; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.w3c.dom.Document; import org.w3c.dom.Node; import be.ibridge.kettle.chef.ChefGraph; import be.ibridge.kettle.chef.ChefHistory; import be.ibridge.kettle.chef.ChefHistoryRefresher; import be.ibridge.kettle.chef.ChefLog; import be.ibridge.kettle.cluster.ClusterSchema; import be.ibridge.kettle.cluster.SlaveServer; import be.ibridge.kettle.cluster.dialog.ClusterSchemaDialog; import be.ibridge.kettle.cluster.dialog.SlaveServerDialog; import be.ibridge.kettle.core.AddUndoPositionInterface; import be.ibridge.kettle.core.ChangedFlagInterface; import be.ibridge.kettle.core.Const; import be.ibridge.kettle.core.DBCache; import be.ibridge.kettle.core.DragAndDropContainer; import be.ibridge.kettle.core.GUIResource; import be.ibridge.kettle.core.KettleVariables; import be.ibridge.kettle.core.LastUsedFile; import be.ibridge.kettle.core.LogWriter; import be.ibridge.kettle.core.NotePadMeta; import be.ibridge.kettle.core.Point; import be.ibridge.kettle.core.PrintSpool; import be.ibridge.kettle.core.Props; import be.ibridge.kettle.core.Row; import be.ibridge.kettle.core.SharedObjectInterface; import be.ibridge.kettle.core.SourceToTargetMapping; import be.ibridge.kettle.core.TransAction; import be.ibridge.kettle.core.WindowProperty; import be.ibridge.kettle.core.XMLHandler; import be.ibridge.kettle.core.XMLTransfer; import be.ibridge.kettle.core.clipboard.ImageDataTransfer; import be.ibridge.kettle.core.database.Database; import be.ibridge.kettle.core.database.DatabaseMeta; import be.ibridge.kettle.core.dialog.CheckResultDialog; import be.ibridge.kettle.core.dialog.DatabaseDialog; import be.ibridge.kettle.core.dialog.DatabaseExplorerDialog; import be.ibridge.kettle.core.dialog.EnterMappingDialog; import be.ibridge.kettle.core.dialog.EnterOptionsDialog; import be.ibridge.kettle.core.dialog.EnterSearchDialog; import be.ibridge.kettle.core.dialog.EnterSelectionDialog; import be.ibridge.kettle.core.dialog.EnterStringDialog; import be.ibridge.kettle.core.dialog.EnterStringsDialog; import be.ibridge.kettle.core.dialog.ErrorDialog; import be.ibridge.kettle.core.dialog.PreviewRowsDialog; import be.ibridge.kettle.core.dialog.SQLEditor; import be.ibridge.kettle.core.dialog.SQLStatementsDialog; import be.ibridge.kettle.core.dialog.ShowBrowserDialog; import be.ibridge.kettle.core.dialog.Splash; import be.ibridge.kettle.core.exception.KettleDatabaseException; import be.ibridge.kettle.core.exception.KettleException; import be.ibridge.kettle.core.exception.KettleStepException; import be.ibridge.kettle.core.reflection.StringSearchResult; import be.ibridge.kettle.core.util.EnvUtil; import be.ibridge.kettle.core.value.Value; import be.ibridge.kettle.core.vfs.KettleVFS; import be.ibridge.kettle.core.widget.TreeMemory; import be.ibridge.kettle.core.wizards.createdatabase.CreateDatabaseWizard; import be.ibridge.kettle.i18n.LanguageChoice; import be.ibridge.kettle.job.JobEntryLoader; import be.ibridge.kettle.job.JobHopMeta; import be.ibridge.kettle.job.JobMeta; import be.ibridge.kettle.job.JobPlugin; import be.ibridge.kettle.job.dialog.JobDialog; import be.ibridge.kettle.job.dialog.JobLoadProgressDialog; import be.ibridge.kettle.job.dialog.JobSaveProgressDialog; import be.ibridge.kettle.job.entry.JobEntryCopy; import be.ibridge.kettle.job.entry.JobEntryDialogInterface; import be.ibridge.kettle.job.entry.JobEntryInterface; import be.ibridge.kettle.job.entry.special.JobEntrySpecial; import be.ibridge.kettle.job.entry.sql.JobEntrySQL; import be.ibridge.kettle.job.entry.trans.JobEntryTrans; import be.ibridge.kettle.pan.CommandLineOption; import be.ibridge.kettle.partition.PartitionSchema; import be.ibridge.kettle.partition.dialog.PartitionSchemaDialog; import be.ibridge.kettle.pkg.JarfileGenerator; import be.ibridge.kettle.repository.PermissionMeta; import be.ibridge.kettle.repository.RepositoriesMeta; import be.ibridge.kettle.repository.Repository; import be.ibridge.kettle.repository.RepositoryDirectory; import be.ibridge.kettle.repository.RepositoryMeta; import be.ibridge.kettle.repository.RepositoryObject; import be.ibridge.kettle.repository.UserInfo; import be.ibridge.kettle.repository.dialog.RepositoriesDialog; import be.ibridge.kettle.repository.dialog.RepositoryExplorerDialog; import be.ibridge.kettle.repository.dialog.SelectObjectDialog; import be.ibridge.kettle.repository.dialog.UserDialog; import be.ibridge.kettle.spoon.dialog.AnalyseImpactProgressDialog; import be.ibridge.kettle.spoon.dialog.CheckTransProgressDialog; import be.ibridge.kettle.spoon.dialog.GetJobSQLProgressDialog; import be.ibridge.kettle.spoon.dialog.GetSQLProgressDialog; import be.ibridge.kettle.spoon.dialog.ShowCreditsDialog; import be.ibridge.kettle.spoon.dialog.TipsDialog; import be.ibridge.kettle.spoon.wizards.CopyTableWizardPage1; import be.ibridge.kettle.spoon.wizards.CopyTableWizardPage2; import be.ibridge.kettle.spoon.wizards.RipDatabaseWizardPage1; import be.ibridge.kettle.spoon.wizards.RipDatabaseWizardPage2; import be.ibridge.kettle.spoon.wizards.RipDatabaseWizardPage3; import be.ibridge.kettle.trans.DatabaseImpact; import be.ibridge.kettle.trans.HasDatabasesInterface; import be.ibridge.kettle.trans.StepLoader; import be.ibridge.kettle.trans.StepPlugin; import be.ibridge.kettle.trans.TransConfiguration; import be.ibridge.kettle.trans.TransExecutionConfiguration; import be.ibridge.kettle.trans.TransHopMeta; import be.ibridge.kettle.trans.TransMeta; import be.ibridge.kettle.trans.cluster.TransSplitter; import be.ibridge.kettle.trans.dialog.TransDialog; import be.ibridge.kettle.trans.dialog.TransExecutionConfigurationDialog; import be.ibridge.kettle.trans.dialog.TransHopDialog; import be.ibridge.kettle.trans.dialog.TransLoadProgressDialog; import be.ibridge.kettle.trans.dialog.TransSaveProgressDialog; import be.ibridge.kettle.trans.step.BaseStep; import be.ibridge.kettle.trans.step.StepDialogInterface; import be.ibridge.kettle.trans.step.StepErrorMeta; import be.ibridge.kettle.trans.step.StepErrorMetaDialog; import be.ibridge.kettle.trans.step.StepMeta; import be.ibridge.kettle.trans.step.StepMetaInterface; import be.ibridge.kettle.trans.step.StepPartitioningMeta; import be.ibridge.kettle.trans.step.selectvalues.SelectValuesMeta; import be.ibridge.kettle.trans.step.tableinput.TableInputMeta; import be.ibridge.kettle.trans.step.tableoutput.TableOutputMeta; import be.ibridge.kettle.version.BuildVersion; import be.ibridge.kettle.www.AddTransServlet; import be.ibridge.kettle.www.PrepareExecutionTransServlet; import be.ibridge.kettle.www.StartExecutionTransServlet; import be.ibridge.kettle.www.WebResult; /** * This class handles the main window of the Spoon graphical transformation editor. * * @author Matt * @since 16-may-2003, i18n at 07-Feb-2006, redesign 01-Dec-2006 */ public class Spoon implements AddUndoPositionInterface { public static final String APP_NAME = Messages.getString("Spoon.Application.Name"); //"Spoon"; private static Spoon staticSpoon; private LogWriter log; private Display disp; private Shell shell; private boolean destroy; private SashForm sashform; public CTabFolder tabfolder; public boolean shift; public boolean control; public Row variables; /** * These are the arguments that were given at Spoon launch time... */ private String[] arguments; private boolean stopped; private Cursor cursor_hourglass, cursor_hand; public Props props; public Repository rep; /** * This contains a map between the name of a transformation and the TransMeta object. * If the transformation has no name it will be mapped under a number [1], [2] etc. */ private Map transformationMap; /** * This contains a map between the name of a transformation and the TransMeta object. * If the transformation has no name it will be mapped under a number [1], [2] etc. */ private Map jobMap; /** * This contains a map between the name of the tab name and the object name and type */ private Map tabMap; /** * This contains a map with all the unnamed transformation (just a filename) */ private ToolBar tBar; private Menu msFile; private MenuItem miFileSep3; private MenuItem miEditUndo, miEditRedo; private Tree selectionTree; private TreeItem tiTransBase, tiJobBase; private Tree coreObjectsTree; public static final String STRING_TRANSFORMATIONS = Messages.getString("Spoon.STRING_TRANSFORMATIONS"); // Transformations public static final String STRING_JOBS = Messages.getString("Spoon.STRING_JOBS"); // Jobs public static final String STRING_BUILDING_BLOCKS = Messages.getString("Spoon.STRING_BUILDING_BLOCKS"); // Building blocks public static final String STRING_ELEMENTS = Messages.getString("Spoon.STRING_ELEMENTS"); // Model elements public static final String STRING_CONNECTIONS = Messages.getString("Spoon.STRING_CONNECTIONS"); // Connections public static final String STRING_STEPS = Messages.getString("Spoon.STRING_STEPS"); // Steps public static final String STRING_JOB_ENTRIES = Messages.getString("Spoon.STRING_JOB_ENTRIES"); // Job entries public static final String STRING_HOPS = Messages.getString("Spoon.STRING_HOPS"); // Hops public static final String STRING_PARTITIONS = Messages.getString("Spoon.STRING_PARTITIONS"); // Database Partition schemas public static final String STRING_SLAVES = Messages.getString("Spoon.STRING_SLAVES"); // Slave servers public static final String STRING_CLUSTERS = Messages.getString("Spoon.STRING_CLUSTERS"); // Cluster Schemas public static final String STRING_TRANS_BASE = Messages.getString("Spoon.STRING_BASE"); // Base step types public static final String STRING_JOB_BASE = Messages.getString("Spoon.STRING_JOBENTRY_BASE"); // Base job entry types public static final String STRING_HISTORY = Messages.getString("Spoon.STRING_HISTORY"); // Step creation history public static final String STRING_TRANS_NO_NAME = Messages.getString("Spoon.STRING_TRANS_NO_NAME"); // <unnamed transformation> public static final String STRING_JOB_NO_NAME = Messages.getString("Spoon.STRING_JOB_NO_NAME"); // <unnamed job> public static final String STRING_TRANSFORMATION = Messages.getString("Spoon.STRING_TRANSFORMATION"); // Transformation public static final String STRING_JOB = Messages.getString("Spoon.STRING_JOB"); // Job private static final String APPL_TITLE = APP_NAME; private static final String STRING_WELCOME_TAB_NAME = "Welcome!"; private static final String FILE_WELCOME_PAGE = "docs/English/welcome/kettle_document_map.html"; public static final int STATE_CORE_OBJECTS_NONE = 1; // No core objects public static final int STATE_CORE_OBJECTS_CHEF = 2; // Chef state: job entries public static final int STATE_CORE_OBJECTS_SPOON = 3; // Spoon state: steps public KeyAdapter defKeys; public KeyAdapter modKeys; private Menu mBar; private Composite tabComp; private SashForm leftSash; private TransExecutionConfiguration executionConfiguration; private TreeItem tiTrans, tiJobs; private Menu spoonMenu; // Connections, Steps & hops private MenuItem miFileClose, miFileSave, miFileSaveAs, miFilePrint; private MenuItem miEditSelectAll, miEditUnselectAll, miEditCopy, miEditPaste; private MenuItem miTransRun, miTransPreview, miTransCheck, miTransImpact, miTransSQL, miLastImpact, miLastCheck, miLastPreview, miTransCopy, miTransPaste, miTransImage, miTransDetails; private MenuItem miWizardCopyTable, miWizardNewConnection, miWizardRipDatabase; private MenuItem miRepDisconnect, miRepUser, miRepExplore; private MenuItem miJobRun, miJobCopy, miJobPaste, miJobInfo; private int coreObjectsState = STATE_CORE_OBJECTS_NONE; private ToolItem tiSQL, tiImpact, tiFileCheck, tiFileReplay, tiFilePreview, tiFileRun, tiFilePrint, tiFileSaveAs, tiFileSave; public Spoon(LogWriter l, Repository rep) { this(l, null, null, rep); } public Spoon(LogWriter l, Display d, Repository rep) { this(l, d, null, rep); } public Spoon(LogWriter log, Display d, TransMeta ti, Repository rep) { this.log = log; this.rep = rep; if (d != null) { disp = d; destroy = false; } else { disp = new Display(); destroy = true; } shell = new Shell(disp); shell.setText(APPL_TITLE); FormLayout layout = new FormLayout(); layout.marginWidth = 0; layout.marginHeight = 0; shell.setLayout(layout); transformationMap = new Hashtable(); jobMap = new Hashtable(); tabMap = new Hashtable(); // INIT Data structure if (ti != null) { addTransformation(ti); } if (!Props.isInitialized()) { //log.logDetailed(toString(), "Load properties for Spoon..."); log.logDetailed(toString(), Messages.getString("Spoon.Log.LoadProperties")); Props.init(disp, Props.TYPE_PROPERTIES_SPOON); // things to remember... } props = Props.getInstance(); // Load settings in the props loadSettings(); executionConfiguration = new TransExecutionConfiguration(); // Clean out every time we start, auto-loading etc, is not a good idea // If they are needed that often, set them in the kettle.properties file // variables = new Row(); // props.setLook(shell); shell.setImage(GUIResource.getInstance().getImageSpoon()); cursor_hourglass = new Cursor(disp, SWT.CURSOR_WAIT); cursor_hand = new Cursor(disp, SWT.CURSOR_HAND); // widgets = new WidgetContainer(); defKeys = new KeyAdapter() { public void keyPressed(KeyEvent e) { TransMeta transMeta = getActiveTransformation(); JobMeta jobMeta = getActiveJob(); UndoInterface undoInterface = getActiveUndoInterface(); SpoonLog spoonLog = getActiveSpoonLog(); boolean ctrl = ((e.stateMask & SWT.CONTROL) != 0); boolean alt = ((e.stateMask & SWT.ALT) != 0); // ESC --> Unselect All steps if (e.keyCode == SWT.ESC && !ctrl && !alt) { if (transMeta != null) { transMeta.unselectAll(); refreshGraph(); } if (jobMeta != null) { jobMeta.unselectAll(); refreshGraph(); } } ; // F3 --> createDatabaseWizard if (e.keyCode == SWT.F3 && !ctrl && !alt) { createDatabaseWizard(); } // F4 --> copyTableWizard if (e.keyCode == SWT.F4 && !ctrl && !alt) { copyTableWizard(); } // CTRL-F4 --> close active transformation if (e.keyCode == SWT.F4 && ctrl && !alt) { closeFile(); } // F5 --> refresh if (e.keyCode == SWT.F5 && !ctrl && !alt) { refreshGraph(); refreshTree(); } // F6 --> show last impact analyses if (e.keyCode == SWT.F6 && !ctrl && !alt) { showLastImpactAnalyses(transMeta); } // F7 --> show last verify results if (e.keyCode == SWT.F7 && !ctrl && !alt) { showLastTransCheck(); } // F8 --> show last preview if (e.keyCode == SWT.F8 && !ctrl && !alt) { if (spoonLog != null) { spoonLog.showPreview(); } } // F9 --> run if (e.keyCode == SWT.F9 && !ctrl && !alt) { executeFile(true, false, false, false, null); } // F10 --> preview if (e.keyCode == SWT.F10 && !ctrl && !alt) { executeFile(true, false, false, true, null); } // CTRL-F10 --> ripDB wizard if (e.keyCode == SWT.F10 && ctrl && !alt) { ripDBWizard(); } // F11 --> Verify if (e.keyCode == SWT.F11 && !ctrl && !alt) { checkTrans(transMeta); } // CTRL-A --> Select All steps if (e.character == 1 && ctrl && !alt) { if (transMeta != null) { transMeta.selectAll(); refreshGraph(); } if (jobMeta != null) { jobMeta.selectAll(); refreshGraph(); } } ; // CTRL-D --> Disconnect from repository if (e.character == 4 && ctrl && !alt) { closeRepository(); } ; // CTRL-E --> Explore the repository if (e.character == 5 && ctrl && !alt) { exploreRepository(); } ; // CTRL-F --> Java examination if (e.character == 6 && ctrl && !alt) { searchMetaData(); } ; // CTRL-I --> Import from XML file && (e.keyCode&SWT.CONTROL)!=0 if (e.character == 9 && ctrl && !alt) { openFile(true); } ; // CTRL-ALT-I --> Copy Transformation Image to clipboard if (e.character == 9 && ctrl && alt) { if (transMeta != null) { copyTransformationImage(transMeta); } } // CTRL-J --> Edit job properties if (e.character == 10 && ctrl && !alt) { editJobProperties(jobMeta); } ; // CTRL-ALT-J --> Get variables if (e.character == 10 && ctrl && alt) { getVariables(); } ; // CTRL-K --> Create Kettle archive if (e.character == 11 && ctrl && !alt) { if (transMeta != null) { createKettleArchive(transMeta); } } ; // CTRL-L --> Show variables if (e.character == 12 && ctrl && !alt) { showVariables(); } ; // CTRL-N --> new if (e.character == 14 && ctrl && !alt) { newFile(); } // CTRL-O --> open if (e.character == 15 && ctrl && !alt) { openFile(false); } // CTRL-P --> print if (e.character == 16 && ctrl && !alt) { printFile(); } // CTRL-Q --> Impact analyses if (e.character == 17 && ctrl && !alt) { analyseImpact(transMeta); } // CTRL-R --> Connect to repository if (e.character == 18 && ctrl && !alt) { openRepository(); } ; // CTRL-S --> save if (e.character == 19 && ctrl && !alt) { saveFile(); } // CTRL-ALT-S --> send to slave server if (e.character == 19 && ctrl && alt) { executeFile(false, true, false, false, null); } // CTRL-T --> transformation if (e.character == 20 && ctrl && !alt) { editTransformationProperties(transMeta); } // CTRL-U --> transformation replay if (e.character == 21 && ctrl && !alt) { executeFile(false, false, true, false, null); } // CTRL-Y --> redo action if (e.character == 25 && ctrl && !alt) { redoAction(undoInterface); } // CTRL-Z --> undo action if (e.character == 26 && ctrl && !alt) { undoAction(undoInterface); } } }; modKeys = new KeyAdapter() { public void keyPressed(KeyEvent e) { shift = (e.keyCode == SWT.SHIFT); control = (e.keyCode == SWT.CONTROL); } public void keyReleased(KeyEvent e) { shift = (e.keyCode == SWT.SHIFT); control = (e.keyCode == SWT.CONTROL); } }; addBar(); FormData fdBar = new FormData(); fdBar.left = new FormAttachment(0, 0); fdBar.top = new FormAttachment(0, 0); tBar.setLayoutData(fdBar); sashform = new SashForm(shell, SWT.HORIZONTAL); // props.setLook(sashform); FormData fdSash = new FormData(); fdSash.left = new FormAttachment(0, 0); fdSash.top = new FormAttachment(tBar, 0); fdSash.bottom = new FormAttachment(100, 0); fdSash.right = new FormAttachment(100, 0); sashform.setLayoutData(fdSash); addMenu(); addTree(); addTabs(); // In case someone dares to press the [X] in the corner ;-) shell.addShellListener(new ShellAdapter() { public void shellClosed(ShellEvent e) { e.doit = quitFile(); } }); // Add a browser widget if (props.showWelcomePageOnStartup()) { showWelcomePage(); } shell.layout(); // Set the shell size, based upon previous time... WindowProperty winprop = props.getScreen(APPL_TITLE); if (winprop != null) winprop.setShell(shell); else { shell.pack(); shell.setMaximized(true); // Default = maximized! } } public static Spoon getInstance() { return staticSpoon; } /** * Add a transformation to the * @param transMeta the transformation to add to the map * @return the key used to store the transformation in the map */ public String addTransformation(TransMeta transMeta) { String key = makeTransGraphTabName(transMeta); if (transformationMap.get(key) == null) { transformationMap.put(key, transMeta); } else { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION); mb.setMessage("'" + key + "'" + Const.CR + Const.CR + Messages.getString("Spoon.Dialog.TransAlreadyLoaded.Message")); // Transformation is already loaded mb.setText(Messages.getString("Spoon.Dialog.TransAlreadyLoaded.Title")); // Sorry! mb.open(); } return key; } /** * Add a job to the job map * @param jobMeta the job to add to the map * @return the key used to store the transformation in the map */ public String addJob(JobMeta jobMeta) { String key = makeJobGraphTabName(jobMeta); if (jobMap.get(key) == null) { jobMap.put(key, jobMeta); } else { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION); mb.setMessage("'" + key + "'" + Const.CR + Const.CR + Messages.getString("Spoon.Dialog.JobAlreadyLoaded.Message")); // Transformation is already loaded mb.setText(Messages.getString("Spoon.Dialog.JobAlreadyLoaded.Title")); // Sorry! mb.open(); } return key; } public void closeFile() { TransMeta transMeta = getActiveTransformation(); if (transMeta != null) { // If a transformation is the current active tab, close it closeTransformation(transMeta); } else { // Otherwise try to find the current open job and close it JobMeta jobMeta = getActiveJob(); if (jobMeta != null) closeJob(jobMeta); } } /** * @param transMeta the transformation to close, make sure it's ok to dispose of it BEFORE you call this. */ public void closeTransformation(TransMeta transMeta) { String tabName = makeTransGraphTabName(transMeta); transformationMap.remove(tabName); // Close the associated tabs... CTabItem graphTab = findCTabItem(tabName, TabMapEntry.OBJECT_TYPE_TRANSFORMATION_GRAPH); if (graphTab != null) { graphTab.dispose(); tabMap.remove(tabName); } // Logging String logTabName = makeLogTabName(transMeta); CTabItem logTab = findCTabItem(logTabName, TabMapEntry.OBJECT_TYPE_TRANSFORMATION_LOG); if (logTab != null) { logTab.dispose(); tabMap.remove(logTabName); } //History String historyTabName = makeHistoryTabName(transMeta); CTabItem historyTab = findCTabItem(historyTabName, TabMapEntry.OBJECT_TYPE_TRANSFORMATION_HISTORY); if (historyTab != null) { historyTab.dispose(); tabMap.remove(historyTabName); } refreshTree(); } /** * @param transMeta the transformation to close, make sure it's ok to dispose of it BEFORE you call this. */ public void closeJob(JobMeta jobMeta) { String tabName = makeJobGraphTabName(jobMeta); jobMap.remove(tabName); // Close the associated tabs... CTabItem graphTab = findCTabItem(tabName, TabMapEntry.OBJECT_TYPE_JOB_GRAPH); if (graphTab != null) { tabMap.remove(tabName); graphTab.dispose(); } // Logging String logTabName = makeJobLogTabName(jobMeta); CTabItem logTab = findCTabItem(logTabName, TabMapEntry.OBJECT_TYPE_JOB_LOG); if (logTab != null) { logTab.dispose(); tabMap.remove(logTabName); } //History String historyTabName = makeJobHistoryTabName(jobMeta); CTabItem historyTab = findCTabItem(historyTabName, TabMapEntry.OBJECT_TYPE_JOB_HISTORY); if (historyTab != null) { historyTab.dispose(); tabMap.remove(historyTabName); } refreshTree(); } public void closeSpoonBrowser() { tabMap.remove(STRING_WELCOME_TAB_NAME); CTabItem tab = findCTabItem(STRING_WELCOME_TAB_NAME, TabMapEntry.OBJECT_TYPE_BROWSER); if (tab != null) tab.dispose(); } /** * Search the transformation meta-data. * */ public void searchMetaData() { TransMeta[] transMetas = getLoadedTransformations(); JobMeta[] jobMetas = getLoadedJobs(); if ((transMetas == null || transMetas.length == 0) && (jobMetas == null || jobMetas.length == 0)) return; EnterSearchDialog esd = new EnterSearchDialog(shell); if (!esd.open()) { return; } ArrayList rows = new ArrayList(); for (int t = 0; t < transMetas.length; t++) { TransMeta transMeta = transMetas[t]; String filterString = esd.getFilterString(); String filter = filterString; if (filter != null) filter = filter.toUpperCase(); List stringList = transMeta.getStringList(esd.isSearchingSteps(), esd.isSearchingDatabases(), esd.isSearchingNotes()); for (int i = 0; i < stringList.size(); i++) { StringSearchResult result = (StringSearchResult) stringList.get(i); boolean add = Const.isEmpty(filter); if (filter != null && result.getString().toUpperCase().indexOf(filter) >= 0) add = true; if (filter != null && result.getFieldName().toUpperCase().indexOf(filter) >= 0) add = true; if (filter != null && result.getParentObject().toString().toUpperCase().indexOf(filter) >= 0) add = true; if (filter != null && result.getGrandParentObject().toString().toUpperCase().indexOf(filter) >= 0) add = true; if (add) rows.add(result.toRow()); } } for (int t = 0; t < jobMetas.length; t++) { JobMeta jobMeta = jobMetas[t]; String filterString = esd.getFilterString(); String filter = filterString; if (filter != null) filter = filter.toUpperCase(); List stringList = jobMeta.getStringList(esd.isSearchingSteps(), esd.isSearchingDatabases(), esd.isSearchingNotes()); for (int i = 0; i < stringList.size(); i++) { StringSearchResult result = (StringSearchResult) stringList.get(i); boolean add = Const.isEmpty(filter); if (filter != null && result.getString().toUpperCase().indexOf(filter) >= 0) add = true; if (filter != null && result.getFieldName().toUpperCase().indexOf(filter) >= 0) add = true; if (filter != null && result.getParentObject().toString().toUpperCase().indexOf(filter) >= 0) add = true; if (filter != null && result.getGrandParentObject().toString().toUpperCase().indexOf(filter) >= 0) add = true; if (add) rows.add(result.toRow()); } } if (rows.size() != 0) { PreviewRowsDialog prd = new PreviewRowsDialog(shell, SWT.NONE, Messages.getString("Spoon.StringSearchResult.Title"), rows); prd.open(); } else { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION); mb.setMessage(Messages.getString("Spoon.Dialog.NothingFound.Message")); // Nothing found that matches your criteria mb.setText(Messages.getString("Spoon.Dialog.NothingFound.Title")); // Sorry! mb.open(); } } public void getVariables() { TransMeta[] transMetas = getLoadedTransformations(); JobMeta[] jobMetas = getLoadedJobs(); if ((transMetas == null || transMetas.length == 0) && (jobMetas == null || jobMetas.length == 0)) return; KettleVariables kettleVariables = KettleVariables.getInstance(); Properties sp = new Properties(); sp.putAll(kettleVariables.getProperties()); sp.putAll(System.getProperties()); for (int t = 0; t < transMetas.length; t++) { TransMeta transMeta = transMetas[t]; List list = transMeta.getUsedVariables(); for (int i = 0; i < list.size(); i++) { String varName = (String) list.get(i); String varValue = sp.getProperty(varName, ""); if (variables.searchValueIndex(varName) < 0 && !varName.startsWith(Const.INTERNAL_VARIABLE_PREFIX)) { variables.addValue(new Value(varName, varValue)); } } } for (int t = 0; t < jobMetas.length; t++) { JobMeta jobMeta = jobMetas[t]; List list = jobMeta.getUsedVariables(); for (int i = 0; i < list.size(); i++) { String varName = (String) list.get(i); String varValue = sp.getProperty(varName, ""); if (variables.searchValueIndex(varName) < 0 && !varName.startsWith(Const.INTERNAL_VARIABLE_PREFIX)) { variables.addValue(new Value(varName, varValue)); } } } // Now ask the use for more info on these! EnterStringsDialog esd = new EnterStringsDialog(shell, SWT.NONE, variables); esd.setTitle(Messages.getString("Spoon.Dialog.SetVariables.Title")); esd.setMessage(Messages.getString("Spoon.Dialog.SetVariables.Message")); esd.setReadOnly(false); if (esd.open() != null) { for (int i = 0; i < variables.size(); i++) { Value varval = variables.getValue(i); if (!Const.isEmpty(varval.getString())) { kettleVariables.setVariable(varval.getName(), varval.getString()); } } } } public void showVariables() { Properties sp = new Properties(); KettleVariables kettleVariables = KettleVariables.getInstance(); sp.putAll(kettleVariables.getProperties()); sp.putAll(System.getProperties()); Row allVars = new Row(); Enumeration keys = kettleVariables.getProperties().keys(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); String value = kettleVariables.getVariable(key); allVars.addValue(new Value(key, value)); } // Now ask the use for more info on these! EnterStringsDialog esd = new EnterStringsDialog(shell, SWT.NONE, allVars); esd.setTitle(Messages.getString("Spoon.Dialog.ShowVariables.Title")); esd.setMessage(Messages.getString("Spoon.Dialog.ShowVariables.Message")); esd.setReadOnly(true); esd.open(); } public void open() { shell.open(); // Shared database entries to load from repository? // loadRepositoryObjects(); // Load shared objects from XML file. // loadSharedObjects(); // Perhaps the transformation contains elements at startup? refreshTree(); // Do a complete refresh then... setShellText(); if (props.showTips()) { TipsDialog tip = new TipsDialog(shell); tip.open(); } } public boolean readAndDispatch() { return disp.readAndDispatch(); } /** * @return check whether or not the application was stopped. */ public boolean isStopped() { return stopped; } /** * @param stopped True to stop this application. */ public void setStopped(boolean stopped) { this.stopped = stopped; } /** * @param destroy Whether or not to distroy the display. */ public void setDestroy(boolean destroy) { this.destroy = destroy; } /** * @return Returns whether or not we should distroy the display. */ public boolean doDestroy() { return destroy; } /** * @param arguments The arguments to set. */ public void setArguments(String[] arguments) { this.arguments = arguments; } /** * @return Returns the arguments. */ public String[] getArguments() { return arguments; } public synchronized void dispose() { setStopped(true); cursor_hand.dispose(); cursor_hourglass.dispose(); if (destroy && !disp.isDisposed()) disp.dispose(); } public boolean isDisposed() { return disp.isDisposed(); } public void sleep() { disp.sleep(); } public void addMenu() { if (mBar != null && !mBar.isDisposed()) { mBar.dispose(); } mBar = new Menu(shell, SWT.BAR); shell.setMenuBar(mBar); //////////////////////////////////////////////////////////// // File // // // main File menu... MenuItem mFile = new MenuItem(mBar, SWT.CASCADE); //mFile.setText("&File"); mFile.setText(Messages.getString("Spoon.Menu.File")); if (msFile != null && !msFile.isDisposed()) { msFile.dispose(); } msFile = new Menu(shell, SWT.DROP_DOWN); mFile.setMenu(msFile); // New // MenuItem miFileNew = new MenuItem(msFile, SWT.CASCADE); miFileNew.setText(Messages.getString("Spoon.Menu.File.New")); //miFileNew.setText("&New \tCTRL-N"); miFileNew.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { newFile(); } }); // Open // MenuItem miFileOpen = new MenuItem(msFile, SWT.CASCADE); miFileOpen.setText(Messages.getString("Spoon.Menu.File.Open")); //&Open \tCTRL-O miFileOpen.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { openFile(false); } }); // Open file from URL // MenuItem miFileOpenVFS = new MenuItem(msFile, SWT.CASCADE); miFileOpenVFS.setText(Messages.getString("Spoon.Menu.File.OpenVFS")); //Open file from &URL miFileOpenVFS.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { openFileVFSFile(); } }); // Import from XML // MenuItem miFileImport = new MenuItem(msFile, SWT.CASCADE); miFileImport.setText(Messages.getString("Spoon.Menu.File.Import")); //"&Import from an XML file\tCTRL-I" miFileImport.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { openFile(true); } }); // Export to XML // MenuItem miFileExport = new MenuItem(msFile, SWT.CASCADE); miFileExport.setText(Messages.getString("Spoon.Menu.File.Export")); //&Export to an XML file miFileExport.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { saveXMLFile(); } }); // Save // miFileSave = new MenuItem(msFile, SWT.CASCADE); miFileSave.setText(Messages.getString("Spoon.Menu.File.Save")); //"&Save \tCTRL-S" miFileSave.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { saveFile(); } }); // Save as // miFileSaveAs = new MenuItem(msFile, SWT.CASCADE); miFileSaveAs.setText(Messages.getString("Spoon.Menu.File.SaveAs")); //"Save &as..." miFileSaveAs.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { saveFileAs(); } }); // Close // miFileClose = new MenuItem(msFile, SWT.CASCADE); miFileClose.setText(Messages.getString("Spoon.Menu.File.Close")); //&Close \tCTRL-F4 miFileClose.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { closeFile(); } }); new MenuItem(msFile, SWT.SEPARATOR); // Print // miFilePrint = new MenuItem(msFile, SWT.CASCADE); miFilePrint.setText(Messages.getString("Spoon.Menu.File.Print")); //"&Print \tCTRL-P" miFilePrint.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { printFile(); } }); new MenuItem(msFile, SWT.SEPARATOR); // Quit // MenuItem miFileQuit = new MenuItem(msFile, SWT.CASCADE); miFileQuit.setText(Messages.getString("Spoon.Menu.File.Quit")); //miFileQuit.setText("&Quit"); miFileQuit.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { quitFile(); } }); miFileSep3 = new MenuItem(msFile, SWT.SEPARATOR); // History addMenuLast(); //////////////////////////////////////////////////////////// // Edit // // // main Edit menu... MenuItem mEdit = new MenuItem(mBar, SWT.CASCADE); mEdit.setText(Messages.getString("Spoon.Menu.Edit")); //&Edit Menu msEdit = new Menu(shell, SWT.DROP_DOWN); mEdit.setMenu(msEdit); // Undo // miEditUndo = new MenuItem(msEdit, SWT.CASCADE); miEditUndo.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { undoAction(getActiveUndoInterface()); } }); // Redo // miEditRedo = new MenuItem(msEdit, SWT.CASCADE); miEditRedo.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { redoAction(getActiveUndoInterface()); } }); setUndoMenu(getActiveTransformation()); new MenuItem(msEdit, SWT.SEPARATOR); // Search // MenuItem miEditSearch = new MenuItem(msEdit, SWT.CASCADE); miEditSearch.setText(Messages.getString("Spoon.Menu.Edit.Search")); //Search Metadata \tCTRL-F miEditSearch.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { searchMetaData(); } }); // Set variables // MenuItem miEditVars = new MenuItem(msEdit, SWT.CASCADE); miEditVars.setText(Messages.getString("Spoon.Menu.Edit.Variables")); //Set variables \tCTRL-ALT-J miEditVars.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { getVariables(); } }); // Show variables MenuItem miEditSVars = new MenuItem(msEdit, SWT.CASCADE); miEditSVars.setText(Messages.getString("Spoon.Menu.Edit.ShowVariables")); //Show variables \tCTRL-L miEditSVars.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { showVariables(); } }); new MenuItem(msEdit, SWT.SEPARATOR); // Clear selection // miEditUnselectAll = new MenuItem(msEdit, SWT.CASCADE); miEditUnselectAll.setText(Messages.getString("Spoon.Menu.Edit.ClearSelection")); //&Clear selection \tESC miEditUnselectAll.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { editUnselectAll(getActiveTransformation()); } }); // Select all // miEditSelectAll = new MenuItem(msEdit, SWT.CASCADE); miEditSelectAll.setText(Messages.getString("Spoon.Menu.Edit.SelectAllSteps")); //"&Select all steps \tCTRL-A" miEditSelectAll.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { editSelectAll(getActiveTransformation()); } }); new MenuItem(msEdit, SWT.SEPARATOR); // Copy to clipboard // miEditCopy = new MenuItem(msEdit, SWT.CASCADE); miEditCopy.setText(Messages.getString("Spoon.Menu.Edit.CopyToClipboard")); //Copy selected steps to clipboard\tCTRL-C miEditCopy.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { TransMeta transMeta = getActiveTransformation(); copySelected(transMeta, transMeta.getSelectedSteps(), transMeta.getSelectedNotes()); } }); // Paste from clipboard // miEditPaste = new MenuItem(msEdit, SWT.CASCADE); miEditPaste.setText(Messages.getString("Spoon.Menu.Edit.PasteFromClipboard")); //Paste steps from clipboard\tCTRL-V miEditPaste.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { pasteSteps(); } }); new MenuItem(msEdit, SWT.SEPARATOR); // Refresh // MenuItem miEditRefresh = new MenuItem(msEdit, SWT.CASCADE); miEditRefresh.setText(Messages.getString("Spoon.Menu.Edit.Refresh")); //&Refresh \tF5 new MenuItem(msEdit, SWT.SEPARATOR); // Options // MenuItem miEditOptions = new MenuItem(msEdit, SWT.CASCADE); miEditOptions.setText(Messages.getString("Spoon.Menu.Edit.Options")); //&Options... miEditOptions.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { editOptions(); } }); //////////////////////////////////////////////////////////// // Repository // // // main Repository menu... MenuItem mRep = new MenuItem(mBar, SWT.CASCADE); mRep.setText(Messages.getString("Spoon.Menu.Repository")); //&Repository Menu msRep = new Menu(shell, SWT.DROP_DOWN); mRep.setMenu(msRep); // Connect to repository // MenuItem miRepConnect = new MenuItem(msRep, SWT.CASCADE); miRepConnect.setText(Messages.getString("Spoon.Menu.Repository.ConnectToRepository")); //&Connect to repository \tCTRL-R miRepConnect.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { openRepository(); } }); // Disconnect from repository // miRepDisconnect = new MenuItem(msRep, SWT.CASCADE); miRepDisconnect.setText(Messages.getString("Spoon.Menu.Repository.DisconnectRepository")); //&Disconnect repository \tCTRL-D miRepDisconnect.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { closeRepository(); } }); // Explore the repository // miRepExplore = new MenuItem(msRep, SWT.CASCADE); miRepExplore.setText(Messages.getString("Spoon.Menu.Repository.ExploreRepository")); //&Explore repository \tCTRL-E miRepExplore.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { exploreRepository(); } }); new MenuItem(msRep, SWT.SEPARATOR); // Edit current user // miRepUser = new MenuItem(msRep, SWT.CASCADE); miRepUser.setText(Messages.getString("Spoon.Menu.Repository.EditCurrentUser")); //&Edit current user\tCTRL-U miRepUser.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { editRepositoryUser(); } }); //////////////////////////////////////////////////////////// // Transformation // // // main Transformation menu... MenuItem mTrans = new MenuItem(mBar, SWT.CASCADE); mTrans.setText(Messages.getString("Spoon.Menu.Transformation")); //&Transformation Menu msTrans = new Menu(shell, SWT.DROP_DOWN); mTrans.setMenu(msTrans); // Run // miTransRun = new MenuItem(msTrans, SWT.CASCADE); miTransRun.setText(Messages.getString("Spoon.Menu.Transformation.Run"));//&Run \tF9 miTransRun.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { executeTransformation(getActiveTransformation(), true, false, false, false, null); } }); // Preview // miTransPreview = new MenuItem(msTrans, SWT.CASCADE); miTransPreview.setText(Messages.getString("Spoon.Menu.Transformation.Preview"));//&Preview \tF10 miTransPreview.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { executeTransformation(getActiveTransformation(), true, false, false, true, null); } }); // Check // miTransCheck = new MenuItem(msTrans, SWT.CASCADE); miTransCheck.setText(Messages.getString("Spoon.Menu.Transformation.Verify"));//&Verify \tF11 miTransCheck.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { checkTrans(getActiveTransformation()); } }); // Impact // miTransImpact = new MenuItem(msTrans, SWT.CASCADE); miTransImpact.setText(Messages.getString("Spoon.Menu.Transformation.Impact"));//&Impact miTransImpact.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { analyseImpact(getActiveTransformation()); } }); // SQL // miTransSQL = new MenuItem(msTrans, SWT.CASCADE); miTransSQL.setText(Messages.getString("Spoon.Menu.Transformation.GetSQL"));//&Get SQL miTransSQL.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { getSQL(); } }); new MenuItem(msTrans, SWT.SEPARATOR); // Show last Impact results // miLastImpact = new MenuItem(msTrans, SWT.CASCADE); miLastImpact.setText(Messages.getString("Spoon.Menu.Transformation.ShowLastImpactAnalyses"));//Show last impact analyses \tF6 miLastImpact.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { showLastImpactAnalyses(getActiveTransformation()); } }); // Show last verify results // miLastCheck = new MenuItem(msTrans, SWT.CASCADE); miLastCheck.setText(Messages.getString("Spoon.Menu.Transformation.ShowLastVerifyResults"));//Show last verify results \tF7 miLastCheck.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { showLastTransCheck(); } }); // Show last preview results // miLastPreview = new MenuItem(msTrans, SWT.CASCADE); miLastPreview.setText(Messages.getString("Spoon.Menu.Transformation.ShowLastPreviewResults"));//Show last preview results \tF8 miLastPreview.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { SpoonLog spoonLog = getActiveSpoonLog(); if (spoonLog != null) spoonLog.showPreview(); } }); new MenuItem(msTrans, SWT.SEPARATOR); // Copy transformation to clipboard // miTransCopy = new MenuItem(msTrans, SWT.CASCADE); miTransCopy.setText(Messages.getString("Spoon.Menu.Transformation.CopyTransformationToClipboard"));//&Copy transformation to clipboard miTransCopy.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { copyTransformation(getActiveTransformation()); } }); // Paste transformation to clipboard // miTransPaste = new MenuItem(msTrans, SWT.CASCADE); miTransPaste.setText(Messages.getString("Spoon.Menu.Transformation.PasteTransformationFromClipboard"));//P&aste transformation from clipboard miTransPaste.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { pasteTransformation(); } }); // Copy image of transformation to clipboard // miTransImage = new MenuItem(msTrans, SWT.CASCADE); miTransImage.setText(Messages.getString("Spoon.Menu.Transformation.CopyTransformationImageClipboard"));//Copy the transformation image clipboard \tCTRL-ALT-I miTransImage.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { copyTransformationImage(getActiveTransformation()); } }); new MenuItem(msTrans, SWT.SEPARATOR); // Edit transformation setttings // miTransDetails = new MenuItem(msTrans, SWT.CASCADE); miTransDetails.setText(Messages.getString("Spoon.Menu.Transformation.Settings"));//&Settings... \tCTRL-T miTransDetails.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { editTransformationProperties(getActiveTransformation()); } }); //////////////////////////////////////////////////////////// // Job // // // The main job menu MenuItem mJob = new MenuItem(mBar, SWT.CASCADE); mJob.setText(Messages.getString("Spoon.Menu.Job")); //$NON-NLS-1$ Menu msJob = new Menu(shell, SWT.DROP_DOWN); mJob.setMenu(msJob); // Run // miJobRun = new MenuItem(msJob, SWT.CASCADE); miJobRun.setText(Messages.getString("Spoon.Menu.Job.Run")); //$NON-NLS-1$ new MenuItem(msJob, SWT.SEPARATOR); miJobRun.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { executeJob(getActiveJob(), true, false, false, false, null); } }); // Copy to clipboard // miJobCopy = new MenuItem(msJob, SWT.CASCADE); miJobCopy.setText(Messages.getString("Spoon.Menu.Job.CopyToClipboard")); //$NON-NLS-1$ miJobCopy.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { copyJob(getActiveJob()); } }); // Paste job from the clipboard // miJobPaste = new MenuItem(msJob, SWT.CASCADE); miJobPaste.setText(Messages.getString("Spoon.Menu.Job.PasteJobFromClipboard"));//P&aste job from clipboard miJobPaste.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { pasteJob(); } }); new MenuItem(msJob, SWT.SEPARATOR); // Edit job properties // miJobInfo = new MenuItem(msJob, SWT.CASCADE); miJobInfo.setText(Messages.getString("Spoon.Menu.Job.Settings")); //$NON-NLS-1$ miJobInfo.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { editJobProperties(getActiveJob()); } }); //////////////////////////////////////////////////////////// // Wizard // // // Wizard menu MenuItem mWizard = new MenuItem(mBar, SWT.CASCADE); mWizard.setText(Messages.getString("Spoon.Menu.Wizard")); //"&Wizard" Menu msWizard = new Menu(shell, SWT.DROP_DOWN); mWizard.setMenu(msWizard); // New database connection wizard // miWizardNewConnection = new MenuItem(msWizard, SWT.CASCADE); miWizardNewConnection.setText(Messages.getString("Spoon.Menu.Wizard.CreateDatabaseConnectionWizard"));//&Create database connection wizard...\tF3 miWizardNewConnection.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { createDatabaseWizard(); } }); // Copy table wizard // miWizardCopyTable = new MenuItem(msWizard, SWT.CASCADE); miWizardCopyTable.setText(Messages.getString("Spoon.Menu.Wizard.CopyTableWizard"));//&Copy table wizard...\tF4 miWizardCopyTable.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { copyTableWizard(); } }); miWizardRipDatabase = new MenuItem(msWizard, SWT.CASCADE); miWizardRipDatabase.setText(Messages.getString("Spoon.Menu.Wizard.CopyTables")); //$NON-NLS-1$ Listener lsWizardRipDatabase = new Listener() { public void handleEvent(Event e) { ripDBWizard(); } }; miWizardRipDatabase.addListener(SWT.Selection, lsWizardRipDatabase); //////////////////////////////////////////////////////////// // Help // // // main Help menu... MenuItem mHelp = new MenuItem(mBar, SWT.CASCADE); mHelp.setText(Messages.getString("Spoon.Menu.Help")); //"&Help" Menu msHelp = new Menu(shell, SWT.DROP_DOWN); mHelp.setMenu(msHelp); // Credits // MenuItem miHelpCredit = new MenuItem(msHelp, SWT.CASCADE); miHelpCredit.setText(Messages.getString("Spoon.Menu.Help.Credits"));//&Credits miHelpCredit.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { ShowCreditsDialog scd = new ShowCreditsDialog(shell, props, GUIResource.getInstance().getImageCredits()); scd.open(); } }); // Tip of the day // MenuItem miHelpTOTD = new MenuItem(msHelp, SWT.CASCADE); miHelpTOTD.setText(Messages.getString("Spoon.Menu.Help.Tip"));//&Tip of the day miHelpTOTD.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { new TipsDialog(shell).open(); } }); // Welcome screen // MenuItem miHelpWelcome = new MenuItem(msHelp, SWT.CASCADE); miHelpWelcome.setText(Messages.getString("Spoon.Menu.Help.Welcome")); //&Welcome screen miHelpWelcome.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { showWelcomePage(); } }); new MenuItem(msHelp, SWT.SEPARATOR); // About // MenuItem miHelpAbout = new MenuItem(msHelp, SWT.CASCADE); miHelpAbout.setText(Messages.getString("Spoon.Menu.About"));//"&About" miHelpAbout.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { helpAbout(); } }); } protected void showWelcomePage() { try { File file = new File(FILE_WELCOME_PAGE); addSpoonBrowser(STRING_WELCOME_TAB_NAME, file.toURL().toString()); // ./docs/English/tips/index.htm } catch (MalformedURLException e1) { log.logError(toString(), Const.getStackTracker(e1)); } } private void addMenuLast() { int idx = msFile.indexOf(miFileSep3); int max = msFile.getItemCount(); // Remove everything until end... for (int i = max - 1; i > idx; i--) { MenuItem mi = msFile.getItem(i); mi.dispose(); } // Previously loaded files... List lastUsedFiles = props.getLastUsedFiles(); for (int i = 0; i < lastUsedFiles.size(); i++) { final LastUsedFile lastUsedFile = (LastUsedFile) lastUsedFiles.get(i); MenuItem miFileLast = new MenuItem(msFile, SWT.CASCADE); if (lastUsedFile.isTransformation()) { miFileLast.setImage(GUIResource.getInstance().getImageSpoonGraph()); } else if (lastUsedFile.isJob()) { miFileLast.setImage(GUIResource.getInstance().getImageChefGraph()); } char chr = (char) ('1' + i); int accel = SWT.CTRL | chr; if (i < 9) { miFileLast.setAccelerator(accel); miFileLast.setText("&" + chr + " " + lastUsedFile + "\tCTRL-" + chr); } else { miFileLast.setText(" " + lastUsedFile); } Listener lsFileLast = new Listener() { public void handleEvent(Event e) { // If the file comes from a repository and it's not the same as // the one we're connected to, ask for a username/password! // boolean cancelled = false; if (lastUsedFile.isSourceRepository() && (rep == null || !rep.getRepositoryInfo().getName() .equalsIgnoreCase(lastUsedFile.getRepositoryName()))) { // Ask for a username password to get the required repository access // int perms[] = new int[] { PermissionMeta.TYPE_PERMISSION_TRANSFORMATION }; RepositoriesDialog rd = new RepositoriesDialog(disp, perms, Messages.getString("Spoon.Application.Name")); // RepositoriesDialog.ToolName="Spoon" rd.setRepositoryName(lastUsedFile.getRepositoryName()); if (rd.open()) { // Close the previous connection... if (rep != null) rep.disconnect(); rep = new Repository(log, rd.getRepository(), rd.getUser()); try { rep.connect(APP_NAME); } catch (KettleException ke) { rep = null; new ErrorDialog(shell, Messages.getString("Spoon.Dialog.UnableConnectRepository.Title"), //$NON-NLS-1$ Messages.getString("Spoon.Dialog.UnableConnectRepository.Message"), ke); //$NON-NLS-1$ } } else { cancelled = true; } } if (!cancelled) { try { RepositoryMeta meta = (rep == null ? null : rep.getRepositoryInfo()); loadLastUsedFile(lastUsedFile, meta); addMenuLast(); refreshHistory(); } catch (KettleException ke) { // "Error loading transformation", "I was unable to load this transformation from the // XML file because of an error" new ErrorDialog(shell, Messages.getString("Spoon.Dialog.LoadTransformationError.Title"), Messages.getString("Spoon.Dialog.LoadTransformationError.Message"), ke); } } } }; miFileLast.addListener(SWT.Selection, lsFileLast); } } private void addBar() { tBar = new ToolBar(shell, SWT.HORIZONTAL | SWT.FLAT); // props.setLook(tBar); final ToolItem tiFileNew = new ToolItem(tBar, SWT.PUSH); final Image imFileNew = new Image(disp, getClass().getResourceAsStream(Const.IMAGE_DIRECTORY + "new.png")); tiFileNew.setImage(imFileNew); tiFileNew.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { newFile(); } }); tiFileNew.setToolTipText(Messages.getString("Spoon.Tooltip.NewTranformation"));//New transformation, clear all settings final ToolItem tiFileOpen = new ToolItem(tBar, SWT.PUSH); final Image imFileOpen = new Image(disp, getClass().getResourceAsStream(Const.IMAGE_DIRECTORY + "open.png")); tiFileOpen.setImage(imFileOpen); tiFileOpen.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { openFile(false); } }); tiFileOpen.setToolTipText(Messages.getString("Spoon.Tooltip.OpenTranformation"));//Open tranformation tiFileSave = new ToolItem(tBar, SWT.PUSH); final Image imFileSave = new Image(disp, getClass().getResourceAsStream(Const.IMAGE_DIRECTORY + "save.png")); tiFileSave.setImage(imFileSave); tiFileSave.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { saveFile(); } }); tiFileSave.setToolTipText(Messages.getString("Spoon.Tooltip.SaveCurrentTranformation"));//Save current transformation tiFileSaveAs = new ToolItem(tBar, SWT.PUSH); final Image imFileSaveAs = new Image(disp, getClass().getResourceAsStream(Const.IMAGE_DIRECTORY + "saveas.png")); tiFileSaveAs.setImage(imFileSaveAs); tiFileSaveAs.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { saveFileAs(); } }); tiFileSaveAs.setToolTipText(Messages.getString("Spoon.Tooltip.SaveDifferentNameTranformation"));//Save transformation with different name new ToolItem(tBar, SWT.SEPARATOR); tiFilePrint = new ToolItem(tBar, SWT.PUSH); final Image imFilePrint = new Image(disp, getClass().getResourceAsStream(Const.IMAGE_DIRECTORY + "print.png")); tiFilePrint.setImage(imFilePrint); tiFilePrint.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { printFile(); } }); tiFilePrint.setToolTipText(Messages.getString("Spoon.Tooltip.Print"));//Print new ToolItem(tBar, SWT.SEPARATOR); tiFileRun = new ToolItem(tBar, SWT.PUSH); final Image imFileRun = new Image(disp, getClass().getResourceAsStream(Const.IMAGE_DIRECTORY + "run.png")); tiFileRun.setImage(imFileRun); tiFileRun.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { executeFile(true, false, false, false, null); } }); tiFileRun.setToolTipText(Messages.getString("Spoon.Tooltip.RunTranformation"));//Run this transformation tiFilePreview = new ToolItem(tBar, SWT.PUSH); final Image imFilePreview = new Image(disp, getClass().getResourceAsStream(Const.IMAGE_DIRECTORY + "preview.png")); tiFilePreview.setImage(imFilePreview); tiFilePreview.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { executeFile(true, false, false, true, null); } }); tiFilePreview.setToolTipText(Messages.getString("Spoon.Tooltip.PreviewTranformation"));//Preview this transformation tiFileReplay = new ToolItem(tBar, SWT.PUSH); final Image imFileReplay = new Image(disp, getClass().getResourceAsStream(Const.IMAGE_DIRECTORY + "replay.png")); tiFileReplay.setImage(imFileReplay); tiFileReplay.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { executeFile(true, false, false, true, null); } }); tiFileReplay.setToolTipText("Replay this transformation"); new ToolItem(tBar, SWT.SEPARATOR); tiFileCheck = new ToolItem(tBar, SWT.PUSH); final Image imFileCheck = new Image(disp, getClass().getResourceAsStream(Const.IMAGE_DIRECTORY + "check.png")); tiFileCheck.setImage(imFileCheck); tiFileCheck.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { checkTrans(getActiveTransformation()); } }); tiFileCheck.setToolTipText(Messages.getString("Spoon.Tooltip.VerifyTranformation"));//Verify this transformation new ToolItem(tBar, SWT.SEPARATOR); tiImpact = new ToolItem(tBar, SWT.PUSH); final Image imImpact = new Image(disp, getClass().getResourceAsStream(Const.IMAGE_DIRECTORY + "impact.png")); // Can't seem to get the transparency correct for this image! ImageData idImpact = imImpact.getImageData(); int impactPixel = idImpact.palette.getPixel(new RGB(255, 255, 255)); idImpact.transparentPixel = impactPixel; Image imImpact2 = new Image(disp, idImpact); tiImpact.setImage(imImpact2); tiImpact.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { analyseImpact(getActiveTransformation()); } }); tiImpact.setToolTipText(Messages.getString("Spoon.Tooltip.AnalyzeTranformation"));//Analyze the impact of this transformation on the database(s) new ToolItem(tBar, SWT.SEPARATOR); tiSQL = new ToolItem(tBar, SWT.PUSH); final Image imSQL = new Image(disp, getClass().getResourceAsStream(Const.IMAGE_DIRECTORY + "SQLbutton.png")); // Can't seem to get the transparency correct for this image! ImageData idSQL = imSQL.getImageData(); int sqlPixel = idSQL.palette.getPixel(new RGB(255, 255, 255)); idSQL.transparentPixel = sqlPixel; Image imSQL2 = new Image(disp, idSQL); tiSQL.setImage(imSQL2); tiSQL.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { getSQL(); } }); tiSQL.setToolTipText(Messages.getString("Spoon.Tooltip.GenerateSQLForTranformation"));//Generate the SQL needed to run this transformation tBar.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { imFileNew.dispose(); imFileOpen.dispose(); imFileSave.dispose(); imFileSaveAs.dispose(); } }); tBar.addKeyListener(defKeys); tBar.addKeyListener(modKeys); tBar.pack(); } private static final String STRING_SPOON_MAIN_TREE = Messages.getString("Spoon.MainTree.Label"); private static final String STRING_SPOON_CORE_OBJECTS_TREE = Messages.getString("Spoon.CoreObjectsTree.Label"); private void addTree() { if (leftSash != null) { leftSash.dispose(); } // Split the left side of the screen in half leftSash = new SashForm(sashform, SWT.VERTICAL); // Now set up the main CSH tree selectionTree = new Tree(leftSash, SWT.SINGLE | SWT.BORDER); props.setLook(selectionTree); selectionTree.setLayout(new FillLayout()); // Add a tree memory as well... TreeMemory.addTreeListener(selectionTree, STRING_SPOON_MAIN_TREE); tiTrans = new TreeItem(selectionTree, SWT.NONE); tiTrans.setText(STRING_TRANSFORMATIONS); tiJobs = new TreeItem(selectionTree, SWT.NONE); tiJobs.setText(STRING_JOBS); // Default selection (double-click, enter) // lsNewDef = new SelectionAdapter() { public void widgetDefaultSelected(SelectionEvent e){ newSelected(); } }; // Add all the listeners... // selectionTree.addSelectionListener(lsEditDef); // double click somewhere in the tree... // tCSH.addSelectionListener(lsNewDef); // double click somewhere in the tree... selectionTree.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { setMenu(); } }); selectionTree.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { showSelection(); } }); selectionTree.addSelectionListener(new SelectionAdapter() { public void widgetDefaultSelected(SelectionEvent e) { doubleClickedInTree(); } }); // Keyboard shortcuts! selectionTree.addKeyListener(defKeys); selectionTree.addKeyListener(modKeys); // Set a listener on the tree addDragSourceToTree(selectionTree); // OK, now add a list of often-used icons to the bottom of the tree... coreObjectsTree = new Tree(leftSash, SWT.SINGLE); // Add a tree memory as well... TreeMemory.addTreeListener(coreObjectsTree, STRING_SPOON_CORE_OBJECTS_TREE); refreshCoreObjectsTree(); tiJobBase.setExpanded(true); // Scroll to the top coreObjectsTree.setSelection(tiTransBase); coreObjectsTree.showSelection(); // Add tooltips for history tree too addToolTipsToTree(coreObjectsTree); // Set the same listener on this tree addDragSourceToTree(coreObjectsTree); leftSash.setWeights(new int[] { 50, 50 }); setTreeImages(); } private void refreshCoreObjectsTree() { clearCoreObjectsTree(); addCoreObjectsToTree(); } private void clearCoreObjectsTree() { setCoreObjectsState(STATE_CORE_OBJECTS_NONE); TreeItem[] items = coreObjectsTree.getItems(); for (int i = 0; i < items.length; i++) items[i].dispose(); } private void addCoreObjectsToTree() { boolean showTrans = getActiveTransformation() != null; boolean showJob = getActiveJob() != null; int nrTabs = tabMap.size(); if (showTrans || nrTabs == 0) { tiTransBase = new TreeItem(coreObjectsTree, SWT.NONE); tiTransBase.setText(STRING_TRANS_BASE); tiTransBase.setImage(GUIResource.getInstance().getImageBol()); // Fill the base components... ////////////////////////////////////////////////////////////////////////////////////////////////// // TRANSFORMATIONS ////////////////////////////////////////////////////////////////////////////////////////////////// String locale = LanguageChoice.getInstance().getDefaultLocale().toString().toLowerCase(); StepLoader steploader = StepLoader.getInstance(); StepPlugin basesteps[] = steploader.getStepsWithType(StepPlugin.TYPE_ALL); String basecat[] = steploader.getCategories(StepPlugin.TYPE_ALL, locale); for (int i = 0; i < basecat.length; i++) { TreeItem tiBaseCat = new TreeItem(tiTransBase, SWT.NONE); tiBaseCat.setText(basecat[i]); tiBaseCat.setImage(GUIResource.getInstance().getImageBol()); for (int j = 0; j < basesteps.length; j++) { if (basesteps[j].getCategory(locale).equalsIgnoreCase(basecat[i])) { TreeItem treeItem = new TreeItem(tiBaseCat, 0); treeItem.setText(basesteps[j].getDescription(locale)); if (basesteps[j].isPlugin()) treeItem.setFont(GUIResource.getInstance().getFontBold()); Image stepimg = (Image) GUIResource.getInstance().getImagesStepsSmall() .get(basesteps[j].getID()[0]); if (stepimg != null) { treeItem.setImage(stepimg); } } } } setCoreObjectsState(STATE_CORE_OBJECTS_SPOON); } if (showJob || nrTabs == 0) { tiJobBase = new TreeItem(coreObjectsTree, SWT.NONE); tiJobBase.setText(STRING_JOB_BASE); tiJobBase.setImage(GUIResource.getInstance().getImageBol()); ////////////////////////////////////////////////////////////////////////////////////////////////// // JOBS ////////////////////////////////////////////////////////////////////////////////////////////////// // First add a few "Special entries: Start, Dummy, OK, ERROR // String specialText[] = new String[] { JobMeta.STRING_SPECIAL_START, JobMeta.STRING_SPECIAL_DUMMY }; Image specialImage[] = new Image[] { GUIResource.getInstance().getImageStart(), GUIResource.getInstance().getImageDummy() }; for (int i = 0; i < specialText.length; i++) { TreeItem treeItem = new TreeItem(tiJobBase, SWT.NONE); treeItem.setText(specialText[i]); treeItem.setImage(specialImage[i]); } JobEntryLoader jobEntryLoader = JobEntryLoader.getInstance(); JobPlugin baseEntries[] = jobEntryLoader.getJobEntriesWithType(JobPlugin.TYPE_ALL); for (int i = 0; i < baseEntries.length; i++) { if (!baseEntries[i].getID().equals("SPECIAL")) { TreeItem tiBaseItem = new TreeItem(tiJobBase, SWT.NONE); tiBaseItem.setText(baseEntries[i].getDescription()); if (baseEntries[i].isPlugin()) tiBaseItem.setFont(GUIResource.getInstance().getFontBold()); Image image = (Image) GUIResource.getInstance().getImagesJobentriesSmall() .get(baseEntries[i].getID()); tiBaseItem.setImage(image); Image jobEntryImg = (Image) GUIResource.getInstance().getImagesJobentriesSmall() .get(baseEntries[i].getID()); if (jobEntryImg != null) { tiBaseItem.setImage(jobEntryImg); } } } setCoreObjectsState(STATE_CORE_OBJECTS_CHEF); } TreeMemory.setExpandedFromMemory(coreObjectsTree, STRING_SPOON_CORE_OBJECTS_TREE); } protected void shareObject(SharedObjectInterface sharedObjectInterface) { sharedObjectInterface.setShared(true); refreshTree(); } /** * @return The object that is selected in the tree or null if we couldn't figure it out. (titles etc. == null) */ public TreeSelection[] getTreeObjects(final Tree tree) { List objects = new ArrayList(); if (tree.equals(selectionTree)) { TreeItem[] selection = selectionTree.getSelection(); for (int s = 0; s < selection.length; s++) { TreeItem treeItem = selection[s]; String[] path = Const.getTreeStrings(treeItem); TreeSelection object = null; switch (path.length) { case 0: break; case 1: // ------complete----- if (path[0].equals(STRING_TRANSFORMATIONS)) // the top level Transformations entry { object = new TreeSelection(path[0], TransMeta.class); } if (path[0].equals(STRING_JOBS)) // the top level Jobs entry { object = new TreeSelection(path[0], JobMeta.class); } break; case 2: // ------complete----- if (path[0].equals(STRING_BUILDING_BLOCKS)) // the top level Transformations entry { if (path[1].equals(STRING_TRANS_BASE)) { object = new TreeSelection(path[1], StepPlugin.class); } } if (path[0].equals(STRING_TRANSFORMATIONS)) // Transformations title { object = new TreeSelection(path[1], findTransformation(path[1])); } if (path[0].equals(STRING_JOBS)) // Jobs title { object = new TreeSelection(path[1], findJob(path[1])); } break; case 3: // ------complete----- if (path[0].equals(STRING_TRANSFORMATIONS)) // Transformations title { TransMeta transMeta = findTransformation(path[1]); if (path[2].equals(STRING_CONNECTIONS)) object = new TreeSelection(path[2], DatabaseMeta.class, transMeta); if (path[2].equals(STRING_STEPS)) object = new TreeSelection(path[2], StepMeta.class, transMeta); if (path[2].equals(STRING_HOPS)) object = new TreeSelection(path[2], TransHopMeta.class, transMeta); if (path[2].equals(STRING_PARTITIONS)) object = new TreeSelection(path[2], PartitionSchema.class, transMeta); if (path[2].equals(STRING_SLAVES)) object = new TreeSelection(path[2], SlaveServer.class, transMeta); if (path[2].equals(STRING_CLUSTERS)) object = new TreeSelection(path[2], ClusterSchema.class, transMeta); } if (path[0].equals(STRING_JOBS)) // Jobs title { JobMeta jobMeta = findJob(path[1]); if (path[2].equals(STRING_CONNECTIONS)) object = new TreeSelection(path[2], DatabaseMeta.class, jobMeta); if (path[2].equals(STRING_JOB_ENTRIES)) object = new TreeSelection(path[2], JobEntryCopy.class, jobMeta); } break; case 4: // ------complete----- if (path[0].equals(STRING_TRANSFORMATIONS)) // The name of a transformation { TransMeta transMeta = findTransformation(path[1]); if (path[2].equals(STRING_CONNECTIONS)) object = new TreeSelection(path[3], transMeta.findDatabase(path[3]), transMeta); if (path[2].equals(STRING_STEPS)) object = new TreeSelection(path[3], transMeta.findStep(path[3]), transMeta); if (path[2].equals(STRING_HOPS)) object = new TreeSelection(path[3], transMeta.findTransHop(path[3]), transMeta); if (path[2].equals(STRING_PARTITIONS)) object = new TreeSelection(path[3], transMeta.findPartitionSchema(path[3]), transMeta); if (path[2].equals(STRING_SLAVES)) object = new TreeSelection(path[3], transMeta.findSlaveServer(path[3]), transMeta); if (path[2].equals(STRING_CLUSTERS)) object = new TreeSelection(path[3], transMeta.findClusterSchema(path[3]), transMeta); } if (path[0].equals(STRING_JOBS)) // The name of a job { JobMeta jobMeta = findJob(path[1]); if (jobMeta != null && path[2].equals(STRING_CONNECTIONS)) object = new TreeSelection(path[3], jobMeta.findDatabase(path[3]), jobMeta); if (jobMeta != null && path[2].equals(STRING_JOB_ENTRIES)) object = new TreeSelection(path[3], jobMeta.findJobEntry(path[3]), jobMeta); } break; case 5: if (path[0].equals(STRING_TRANSFORMATIONS)) // The name of a transformation { TransMeta transMeta = findTransformation(path[1]); if (transMeta != null && path[2].equals(STRING_CLUSTERS)) { ClusterSchema clusterSchema = transMeta.findClusterSchema(path[3]); object = new TreeSelection(path[4], clusterSchema.findSlaveServer(path[4]), clusterSchema, transMeta); } } break; default: break; } if (object != null) { objects.add(object); } } } if (tree.equals(coreObjectsTree)) { TreeItem[] selection = coreObjectsTree.getSelection(); for (int s = 0; s < selection.length; s++) { TreeItem treeItem = selection[s]; String[] path = Const.getTreeStrings(treeItem); TreeSelection object = null; switch (path.length) { case 0: break; case 1: break; // nothing case 2: // Job entries if (path[0].equals(STRING_JOB_BASE)) { JobPlugin jobPlugin = JobEntryLoader.getInstance().findJobEntriesWithDescription(path[1]); if (jobPlugin != null) { object = new TreeSelection(path[1], jobPlugin); } else { object = new TreeSelection(path[1], JobPlugin.class); // Special entries Start, Dummy, ... } } break; case 3: // Steps if (path[0].equals(STRING_TRANS_BASE)) { object = new TreeSelection(path[2], StepLoader.getInstance().findStepPluginWithDescription(path[2])); } break; default: break; } if (object != null) { objects.add(object); } } } return (TreeSelection[]) objects.toArray(new TreeSelection[objects.size()]); } private void addToolTipsToTree(Tree tree) { tree.addListener(SWT.MouseHover, new Listener() { public void handleEvent(Event e) { String tooltip = null; Tree tree = (Tree) e.widget; TreeItem item = tree.getItem(new org.eclipse.swt.graphics.Point(e.x, e.y)); if (item != null) { String locale = LanguageChoice.getInstance().getDefaultLocale().toString().toLowerCase(); StepLoader steploader = StepLoader.getInstance(); StepPlugin sp = steploader.findStepPluginWithDescription(item.getText(), locale); if (sp != null) { tooltip = sp.getTooltip(locale); } else { JobEntryLoader jobEntryLoader = JobEntryLoader.getInstance(); JobPlugin jobPlugin = jobEntryLoader.findJobEntriesWithDescription(item.getText()); if (jobPlugin != null) { tooltip = jobPlugin.getTooltip(); } else { if (item.getText().equalsIgnoreCase(STRING_TRANS_BASE)) { tooltip = Messages.getString("Spoon.Tooltip.SelectStepType", Const.CR); //"Select one of the step types listed below and"+Const.CR+"drag it onto the graphical view tab to the right."; } } } } tree.setToolTipText(tooltip); } }); } private void addDragSourceToTree(final Tree tree) { // Drag & Drop for steps Transfer[] ttypes = new Transfer[] { XMLTransfer.getInstance() }; DragSource ddSource = new DragSource(tree, DND.DROP_MOVE); ddSource.setTransfer(ttypes); ddSource.addDragListener(new DragSourceListener() { public void dragStart(DragSourceEvent event) { } public void dragSetData(DragSourceEvent event) { TreeSelection[] treeObjects = getTreeObjects(tree); if (treeObjects.length == 0) { event.doit = false; return; } int type = 0; String data = null; TreeSelection treeObject = treeObjects[0]; Object object = treeObject.getSelection(); JobMeta jobMeta = getActiveJob(); if (object instanceof StepMeta) { StepMeta stepMeta = (StepMeta) object; type = DragAndDropContainer.TYPE_STEP; data = stepMeta.getName(); // name of the step. } else if (object instanceof StepPlugin) { StepPlugin stepPlugin = (StepPlugin) object; type = DragAndDropContainer.TYPE_BASE_STEP_TYPE; data = stepPlugin.getDescription(); // Step type description } else if (object instanceof DatabaseMeta) { DatabaseMeta databaseMeta = (DatabaseMeta) object; type = DragAndDropContainer.TYPE_DATABASE_CONNECTION; data = databaseMeta.getName(); } else if (object instanceof TransHopMeta) { TransHopMeta hop = (TransHopMeta) object; type = DragAndDropContainer.TYPE_TRANS_HOP; data = hop.toString(); // nothing for really ;-) } else if (object instanceof JobEntryCopy) { JobEntryCopy jobEntryCopy = (JobEntryCopy) object; type = DragAndDropContainer.TYPE_JOB_ENTRY; data = jobEntryCopy.getName(); // name of the job entry. } else if (object instanceof JobPlugin) { JobPlugin jobPlugin = (JobPlugin) object; type = DragAndDropContainer.TYPE_BASE_JOB_ENTRY; data = jobPlugin.getDescription(); // Step type } else if (object instanceof Class && object.equals(JobPlugin.class)) { JobEntryCopy dummy = null; if (jobMeta != null) dummy = jobMeta.findJobEntry("Dummy", 0, true); if (JobMeta.STRING_SPECIAL_DUMMY.equalsIgnoreCase(treeObject.getItemText()) && dummy != null) { // if dummy already exists, add a copy type = DragAndDropContainer.TYPE_JOB_ENTRY; data = dummy.getName(); } else { type = DragAndDropContainer.TYPE_BASE_JOB_ENTRY; data = treeObject.getItemText(); } } else { event.doit = false; return; // ignore anything else you drag. } event.data = new DragAndDropContainer(type, data); } public void dragFinished(DragSourceEvent event) { } }); } /** * If you click in the tree, you might want to show the corresponding window. */ public void showSelection() { TreeSelection[] objects = getTreeObjects(selectionTree); if (objects.length != 1) return; // not yet supported, we can do this later when the OSX bug goes away TreeSelection object = objects[0]; final Object selection = object.getSelection(); final Object parent = object.getParent(); TransMeta transMeta = null; if (selection instanceof TransMeta) transMeta = (TransMeta) selection; if (parent instanceof TransMeta) transMeta = (TransMeta) parent; if (transMeta != null) { // Search the corresponding SpoonGraph tab CTabItem tabItem = findCTabItem(makeTransGraphTabName(transMeta), TabMapEntry.OBJECT_TYPE_TRANSFORMATION_GRAPH); if (tabItem != null) { int current = tabfolder.getSelectionIndex(); int desired = tabfolder.indexOf(tabItem); if (current != desired) tabfolder.setSelection(desired); if (getCoreObjectsState() != STATE_CORE_OBJECTS_SPOON) { // Switch the core objects in the lower left corner to the spoon trans types refreshCoreObjectsTree(); } } } JobMeta jobMeta = null; if (selection instanceof JobMeta) jobMeta = (JobMeta) selection; if (parent instanceof JobMeta) jobMeta = (JobMeta) parent; if (jobMeta != null) { // Search the corresponding SpoonGraph tab CTabItem tabItem = findCTabItem(makeJobGraphTabName(jobMeta), TabMapEntry.OBJECT_TYPE_JOB_GRAPH); if (tabItem != null) { int current = tabfolder.getSelectionIndex(); int desired = tabfolder.indexOf(tabItem); if (current != desired) tabfolder.setSelection(desired); if (getCoreObjectsState() != STATE_CORE_OBJECTS_CHEF) { // Switch the core objects in the lower left corner to the spoon job types refreshCoreObjectsTree(); } } } } private void setMenu() { if (spoonMenu == null) { spoonMenu = new Menu(shell, SWT.POP_UP); } else { MenuItem[] items = spoonMenu.getItems(); for (int i = 0; i < items.length; i++) items[i].dispose(); } TreeSelection[] objects = getTreeObjects(selectionTree); if (objects.length != 1) return; // not yet supported, we can do this later when the OSX bug goes away TreeSelection object = objects[0]; final Object selection = object.getSelection(); final Object parent = object.getParent(); // final Object grandParent = object.getGrandParent(); // Not clicked on a real object: returns a class if (selection instanceof Class) { if (selection.equals(TransMeta.class)) { // New MenuItem miNew = new MenuItem(spoonMenu, SWT.PUSH); miNew.setText(Messages.getString("Spoon.Menu.Popup.BASE.New")); miNew.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { newTransFile(); } }); } if (selection.equals(JobMeta.class)) { // New MenuItem miNew = new MenuItem(spoonMenu, SWT.PUSH); miNew.setText(Messages.getString("Spoon.Menu.Popup.BASE.New")); miNew.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { newJobFile(); } }); } if (selection.equals(TransHopMeta.class)) { // New MenuItem miNew = new MenuItem(spoonMenu, SWT.PUSH); miNew.setText(Messages.getString("Spoon.Menu.Popup.BASE.New")); miNew.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { newHop((TransMeta) parent); } }); // Sort hops MenuItem miSort = new MenuItem(spoonMenu, SWT.PUSH); miSort.setText(Messages.getString("Spoon.Menu.Popup.HOPS.SortHops")); miSort.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { ((TransMeta) parent).sortHops(); refreshTree(); } }); } if (selection.equals(DatabaseMeta.class)) { // New MenuItem miNew = new MenuItem(spoonMenu, SWT.PUSH); miNew.setText(Messages.getString("Spoon.Menu.Popup.BASE.New")); miNew.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { newConnection(); } }); // New Connection Wizard MenuItem miWizard = new MenuItem(spoonMenu, SWT.PUSH); miWizard.setText(Messages.getString("Spoon.Menu.Popup.CONNECTIONS.NewConnectionWizard")); miWizard.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent arg0) { createDatabaseWizard(); } }); // Clear complete DB Cache MenuItem miCache = new MenuItem(spoonMenu, SWT.PUSH); miCache.setText(Messages.getString("Spoon.Menu.Popup.CONNECTIONS.ClearDBCacheComplete")); miCache.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { clearDBCache(); } }); } if (selection.equals(PartitionSchema.class)) { // New MenuItem miNew = new MenuItem(spoonMenu, SWT.PUSH); miNew.setText(Messages.getString("Spoon.Menu.Popup.BASE.New")); miNew.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { newDatabasePartitioningSchema((TransMeta) parent); } }); } if (selection.equals(ClusterSchema.class)) { MenuItem miNew = new MenuItem(spoonMenu, SWT.PUSH); miNew.setText(Messages.getString("Spoon.Menu.Popup.CLUSTERS.New"));//New clustering schema miNew.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { newClusteringSchema((TransMeta) parent); } }); } if (selection.equals(SlaveServer.class)) { MenuItem miNew = new MenuItem(spoonMenu, SWT.PUSH); miNew.setText(Messages.getString("Spoon.Menu.Popup.SLAVE_SERVER.New"));// New slave server miNew.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { newSlaveServer((TransMeta) parent); } }); } } else { if (selection instanceof TransMeta) { // Edit transformation properties MenuItem miEdit = new MenuItem(spoonMenu, SWT.PUSH); miEdit.setText(Messages.getString("Spoon.Menu.Transformation.Settings")); //Settings... miEdit.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { editTransformationProperties((TransMeta) selection); } }); // Open log window MenuItem miLog = new MenuItem(spoonMenu, SWT.PUSH); miLog.setText(Messages.getString("Spoon.Menu.Popup.BASE.LogWindow")); miLog.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { addSpoonLog((TransMeta) selection); } }); // Open history window MenuItem miHistory = new MenuItem(spoonMenu, SWT.PUSH); miHistory.setText(Messages.getString("Spoon.Menu.Popup.BASE.HistoryWindow")); miHistory.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { addSpoonHistory((TransMeta) selection, true); } }); } if (selection instanceof JobMeta) { // Edit transformation properties MenuItem miEdit = new MenuItem(spoonMenu, SWT.PUSH); miEdit.setText(Messages.getString("Spoon.Menu.Job.Settings")); //Settings... miEdit.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { editJobProperties((JobMeta) selection); } }); // Open log window MenuItem miLog = new MenuItem(spoonMenu, SWT.PUSH); miLog.setText(Messages.getString("Spoon.Menu.Popup.BASE.LogWindow")); miLog.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { addChefLog((JobMeta) selection); } }); // Open history windows MenuItem miHistory = new MenuItem(spoonMenu, SWT.PUSH); miHistory.setText(Messages.getString("Spoon.Menu.Popup.BASE.HistoryWindow")); miHistory.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { addChefHistory((JobMeta) selection, true); } }); } if (selection instanceof StepPlugin) { // New MenuItem miNew = new MenuItem(spoonMenu, SWT.PUSH); miNew.setText(Messages.getString("Spoon.Menu.Popup.BASE.New")); miNew.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { newStep(getActiveTransformation()); } }); } if (selection instanceof DatabaseMeta) { final DatabaseMeta databaseMeta = (DatabaseMeta) selection; final HasDatabasesInterface hasDatabasesInterface = (HasDatabasesInterface) parent; MenuItem miNew = new MenuItem(spoonMenu, SWT.PUSH); miNew.setText(Messages.getString("Spoon.Menu.Popup.CONNECTIONS.New"));//New miNew.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { newConnection(); } }); MenuItem miEdit = new MenuItem(spoonMenu, SWT.PUSH); miEdit.setText(Messages.getString("Spoon.Menu.Popup.CONNECTIONS.Edit"));//Edit miEdit.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { editConnection(databaseMeta); } }); MenuItem miDupe = new MenuItem(spoonMenu, SWT.PUSH); miDupe.setText(Messages.getString("Spoon.Menu.Popup.CONNECTIONS.Duplicate"));//Duplicate miDupe.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { dupeConnection(hasDatabasesInterface, databaseMeta); } }); MenuItem miCopy = new MenuItem(spoonMenu, SWT.PUSH); miCopy.setText(Messages.getString("Spoon.Menu.Popup.CONNECTIONS.CopyToClipboard"));//Copy to clipboard miCopy.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { clipConnection(databaseMeta); } }); MenuItem miDel = new MenuItem(spoonMenu, SWT.PUSH); miDel.setText(Messages.getString("Spoon.Menu.Popup.CONNECTIONS.Delete"));//Delete miDel.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { delConnection(hasDatabasesInterface, databaseMeta); } }); new MenuItem(spoonMenu, SWT.SEPARATOR); MenuItem miSQL = new MenuItem(spoonMenu, SWT.PUSH); miSQL.setText(Messages.getString("Spoon.Menu.Popup.CONNECTIONS.SQLEditor"));//SQL Editor miSQL.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { sqlConnection(databaseMeta); } }); MenuItem miCache = new MenuItem(spoonMenu, SWT.PUSH); miCache.setText( Messages.getString("Spoon.Menu.Popup.CONNECTIONS.ClearDBCache") + databaseMeta.getName());//Clear DB Cache of miCache.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { clearDBCache(databaseMeta); } }); new MenuItem(spoonMenu, SWT.SEPARATOR); MenuItem miShare = new MenuItem(spoonMenu, SWT.PUSH); miShare.setText(Messages.getString("Spoon.Menu.Popup.CONNECTIONS.Share")); miShare.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { shareObject(databaseMeta); } }); new MenuItem(spoonMenu, SWT.SEPARATOR); MenuItem miExpl = new MenuItem(spoonMenu, SWT.PUSH); miExpl.setText(Messages.getString("Spoon.Menu.Popup.CONNECTIONS.Explore"));//Explore miExpl.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { exploreDB(databaseMeta); } }); // disable for now if the connection is an SAP R/3 type of database... if (databaseMeta.getDatabaseType() == DatabaseMeta.TYPE_DATABASE_SAPR3) miExpl.setEnabled(false); } if (selection instanceof StepMeta) { final TransMeta transMeta = (TransMeta) parent; final StepMeta stepMeta = (StepMeta) selection; // Edit MenuItem miEdit = new MenuItem(spoonMenu, SWT.PUSH); miEdit.setText(Messages.getString("Spoon.Menu.Popup.STEPS.Edit")); miEdit.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { editStep(transMeta, stepMeta); } }); // Duplicate MenuItem miDupe = new MenuItem(spoonMenu, SWT.PUSH); miDupe.setText(Messages.getString("Spoon.Menu.Popup.STEPS.Duplicate")); miDupe.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { dupeStep(transMeta, stepMeta); } }); // Delete MenuItem miDel = new MenuItem(spoonMenu, SWT.PUSH); miDel.setText(Messages.getString("Spoon.Menu.Popup.STEPS.Delete")); miDel.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { delStep(transMeta, stepMeta); } }); MenuItem miShare = new MenuItem(spoonMenu, SWT.PUSH); miShare.setText(Messages.getString("Spoon.Menu.Popup.STEPS.Share")); miShare.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { shareObject(stepMeta); } }); } if (selection instanceof JobEntryCopy) { final JobMeta jobMeta = (JobMeta) parent; final JobEntryCopy jobEntry = (JobEntryCopy) selection; // Edit MenuItem miEdit = new MenuItem(spoonMenu, SWT.PUSH); miEdit.setText(Messages.getString("Spoon.Menu.Popup.JOBENTRIES.Edit")); miEdit.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { editJobEntry(jobMeta, jobEntry); } }); // Duplicate MenuItem miDupe = new MenuItem(spoonMenu, SWT.PUSH); miDupe.setText(Messages.getString("Spoon.Menu.Popup.JOBENTRIES.Duplicate")); miDupe.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { dupeJobEntry(jobMeta, jobEntry); } }); // Delete MenuItem miDel = new MenuItem(spoonMenu, SWT.PUSH); miDel.setText(Messages.getString("Spoon.Menu.Popup.JOBENTRIES.Delete")); miDel.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { deleteJobEntryCopies(jobMeta, jobEntry); } }); } if (selection instanceof TransHopMeta) { final TransMeta transMeta = (TransMeta) parent; final TransHopMeta transHopMeta = (TransHopMeta) selection; MenuItem miEdit = new MenuItem(spoonMenu, SWT.PUSH); miEdit.setText(Messages.getString("Spoon.Menu.Popup.HOPS.Edit"));//Edit miEdit.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { editHop(transMeta, transHopMeta); } }); MenuItem miDel = new MenuItem(spoonMenu, SWT.PUSH); miDel.setText(Messages.getString("Spoon.Menu.Popup.HOPS.Delete"));//Delete miDel.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { delHop(transMeta, transHopMeta); } }); } if (selection instanceof PartitionSchema) { final TransMeta transMeta = (TransMeta) parent; final PartitionSchema partitionSchema = (PartitionSchema) selection; MenuItem miEdit = new MenuItem(spoonMenu, SWT.PUSH); miEdit.setText(Messages.getString("Spoon.Menu.Popup.PARTITIONS.Edit"));//Edit miEdit.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { editPartitionSchema(transMeta, partitionSchema); } }); MenuItem miDel = new MenuItem(spoonMenu, SWT.PUSH); miDel.setText(Messages.getString("Spoon.Menu.Popup.PARTITIONS.Delete"));//Delete miDel.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { delPartitionSchema(transMeta, partitionSchema); } }); MenuItem miShare = new MenuItem(spoonMenu, SWT.PUSH); miShare.setText(Messages.getString("Spoon.Menu.Popup.PARTITIONS.Share")); miShare.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { shareObject(partitionSchema); } }); } if (selection instanceof ClusterSchema) { final TransMeta transMeta = (TransMeta) parent; final ClusterSchema clusterSchema = (ClusterSchema) selection; MenuItem miEdit = new MenuItem(spoonMenu, SWT.PUSH); miEdit.setText(Messages.getString("Spoon.Menu.Popup.CLUSTERS.Edit"));//Edit miEdit.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { editClusterSchema(transMeta, clusterSchema); } }); MenuItem miDel = new MenuItem(spoonMenu, SWT.PUSH); miDel.setText(Messages.getString("Spoon.Menu.Popup.CLUSTERS.Delete"));//Delete miDel.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { delClusterSchema(transMeta, clusterSchema); } }); MenuItem miShare = new MenuItem(spoonMenu, SWT.PUSH); miShare.setText(Messages.getString("Spoon.Menu.Popup.CLUSTERS.Share")); miShare.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { shareObject(clusterSchema); } }); MenuItem miMonitor = new MenuItem(spoonMenu, SWT.PUSH); miMonitor.setText(Messages.getString("Spoon.Menu.Popup.CLUSTERS.Monitor"));//New miMonitor.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { monitorClusterSchema(clusterSchema); } }); } // Right click on a slave server if (selection instanceof SlaveServer) { final TransMeta transMeta = (TransMeta) parent; final SlaveServer slaveServer = (SlaveServer) selection; MenuItem miEdit = new MenuItem(spoonMenu, SWT.PUSH); miEdit.setText(Messages.getString("Spoon.Menu.Popup.SLAVE_SERVER.Edit"));//New miEdit.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { editSlaveServer(slaveServer); } }); MenuItem miDel = new MenuItem(spoonMenu, SWT.PUSH); miDel.setText(Messages.getString("Spoon.Menu.Popup.SLAVE_SERVER.Delete"));//Delete miDel.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { delSlaveServer(transMeta, slaveServer); } }); MenuItem miMonitor = new MenuItem(spoonMenu, SWT.PUSH); miMonitor.setText(Messages.getString("Spoon.Menu.Popup.SLAVE_SERVER.Monitor"));//New miMonitor.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { addSpoonSlave(slaveServer); } }); new MenuItem(spoonMenu, SWT.SEPARATOR); MenuItem miShare = new MenuItem(spoonMenu, SWT.PUSH); miShare.setText(Messages.getString("Spoon.Menu.Popup.SLAVE_SERVER.Share")); miShare.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { shareObject(slaveServer); } }); } } selectionTree.setMenu(spoonMenu); } /** * Reaction to double click * */ private void doubleClickedInTree() { TreeSelection[] objects = getTreeObjects(selectionTree); if (objects.length != 1) return; // not yet supported, we can do this later when the OSX bug goes away TreeSelection object = objects[0]; final Object selection = object.getSelection(); final Object parent = object.getParent(); if (selection instanceof Class) { if (selection.equals(TransMeta.class)) newTransFile(); if (selection.equals(JobMeta.class)) newJobFile(); if (selection.equals(TransHopMeta.class)) newHop((TransMeta) parent); if (selection.equals(DatabaseMeta.class)) newConnection(); if (selection.equals(PartitionSchema.class)) newDatabasePartitioningSchema((TransMeta) parent); if (selection.equals(ClusterSchema.class)) newClusteringSchema((TransMeta) parent); if (selection.equals(SlaveServer.class)) newSlaveServer((TransMeta) parent); } else { if (selection instanceof TransMeta) editTransformationProperties((TransMeta) selection); if (selection instanceof JobMeta) editJobProperties((JobMeta) selection); if (selection instanceof StepPlugin) newStep(getActiveTransformation()); if (selection instanceof DatabaseMeta) editConnection((DatabaseMeta) selection); if (selection instanceof StepMeta) editStep((TransMeta) parent, (StepMeta) selection); if (selection instanceof JobEntryCopy) editJobEntry((JobMeta) parent, (JobEntryCopy) selection); if (selection instanceof TransHopMeta) editHop((TransMeta) parent, (TransHopMeta) selection); if (selection instanceof PartitionSchema) editPartitionSchema((HasDatabasesInterface) parent, (PartitionSchema) selection); if (selection instanceof ClusterSchema) editClusterSchema((TransMeta) parent, (ClusterSchema) selection); if (selection instanceof SlaveServer) editSlaveServer((SlaveServer) selection); } } protected void monitorClusterSchema(ClusterSchema clusterSchema) { for (int i = 0; i < clusterSchema.getSlaveServers().size(); i++) { SlaveServer slaveServer = (SlaveServer) clusterSchema.getSlaveServers().get(i); addSpoonSlave(slaveServer); } } protected void editSlaveServer(SlaveServer slaveServer) { SlaveServerDialog dialog = new SlaveServerDialog(shell, slaveServer); if (dialog.open()) { refreshTree(); refreshGraph(); } } private void addTabs() { if (tabComp != null) { tabComp.dispose(); } tabComp = new Composite(sashform, SWT.BORDER); props.setLook(tabComp); tabComp.setLayout(new GridLayout()); tabfolder = new CTabFolder(tabComp, SWT.BORDER); tabfolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); props.setLook(tabfolder, Props.WIDGET_STYLE_TAB); tabfolder.setSimple(false); tabfolder.setUnselectedImageVisible(true); tabfolder.setUnselectedCloseVisible(true); tabfolder.addKeyListener(defKeys); tabfolder.addKeyListener(modKeys); // tabfolder.setSelection(0); sashform.addKeyListener(defKeys); sashform.addKeyListener(modKeys); int weights[] = props.getSashWeights(); sashform.setWeights(weights); sashform.setVisible(true); tabfolder.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { ArrayList collection = new ArrayList(); collection.addAll(tabMap.values()); for (Iterator iter = collection.iterator(); iter.hasNext();) { TabMapEntry entry = (TabMapEntry) iter.next(); if (event.item.equals(entry.getTabItem())) { // TabItemInterface itemInterface = entry.getObject(); // // Another way to implement this may be to keep track of the // state of the core object tree in method addCoreObjectsToTree() // if (event.doit && entry.getObject() instanceof SpoonGraph) { if (getCoreObjectsState() != STATE_CORE_OBJECTS_SPOON) { refreshCoreObjectsTree(); } } if (event.doit && entry.getObject() instanceof ChefGraph) { if (getCoreObjectsState() != STATE_CORE_OBJECTS_CHEF) { refreshCoreObjectsTree(); } } } } } }); tabfolder.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent selectionEvent) { enableMenus(); } }); tabfolder.addCTabFolder2Listener(new CTabFolder2Adapter() { public void close(CTabFolderEvent event) { // Try to find the tab-item that's being closed. ArrayList collection = new ArrayList(); collection.addAll(tabMap.values()); for (Iterator iter = collection.iterator(); iter.hasNext();) { TabMapEntry entry = (TabMapEntry) iter.next(); if (event.item.equals(entry.getTabItem())) { TabItemInterface itemInterface = entry.getObject(); boolean close = true; // Can we close this tab? if (!itemInterface.canBeClosed()) { int reply = itemInterface.showChangedWarning(); if (reply == SWT.YES) { close = itemInterface.applyChanges(); } else { if (reply == SWT.CANCEL) { close = false; } else { close = true; } } } event.doit = close; // Also clean up the log/history associated with this transformation/job // if (event.doit && entry.getObject() instanceof SpoonGraph) { TransMeta transMeta = (TransMeta) entry.getObject().getManagedObject(); closeTransformation(transMeta); refreshTree(); } if (event.doit && entry.getObject() instanceof ChefGraph) { JobMeta jobMeta = (JobMeta) entry.getObject().getManagedObject(); closeJob(jobMeta); refreshTree(); } if (event.doit && entry.getObject() instanceof SpoonBrowser) { closeSpoonBrowser(); refreshTree(); } } } } }); // Drag & Drop for steps Transfer[] ttypes = new Transfer[] { XMLTransfer.getInstance() }; DropTarget ddTarget = new DropTarget(tabfolder, DND.DROP_MOVE); ddTarget.setTransfer(ttypes); ddTarget.addDropListener(new DropTargetListener() { public void dragEnter(DropTargetEvent event) { } public void dragLeave(DropTargetEvent event) { } public void dragOperationChanged(DropTargetEvent event) { } public void dragOver(DropTargetEvent event) { } public void drop(DropTargetEvent event) { // no data to copy, indicate failure in event.detail if (event.data == null) { event.detail = DND.DROP_NONE; return; } // What's the real drop position? Point p = new Point(event.x, event.y); // Subtract locations of parents... Composite follow = tabfolder; while (follow.getParent() != null) { follow = follow.getParent(); org.eclipse.swt.graphics.Point parentLoc = follow.getLocation(); p.x -= parentLoc.x; p.y -= parentLoc.y; } p.x -= 10; p.y -= 75; // // We expect a Drag and Drop container... (encased in XML) try { DragAndDropContainer container = (DragAndDropContainer) event.data; switch (container.getType()) { // Create a new step // Since we drag onto the tabfolder, there is no graph to accept this // Therefor we need to create a new transformation. // case DragAndDropContainer.TYPE_BASE_STEP_TYPE: { // Add the transformation. // Since there is no transformation or job loaded, it should be safe to do so. // TransMeta transMeta = new TransMeta(); try { transMeta.readSharedObjects(rep); } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorReadingSharedObjects.Title"), Messages.getString("Spoon.Dialog.ErrorReadingSharedObjects.Message", makeTransGraphTabName(transMeta)), e); } addSpoonGraph(transMeta); // Not an existing step: data refers to the type of step to create String steptype = container.getData(); StepMeta stepMeta = newStep(transMeta, steptype, steptype, false, true); stepMeta.setLocation(p); stepMeta.setDraw(true); addUndoNew(transMeta, new StepMeta[] { stepMeta }, new int[] { 0 }); refreshTree(); } break; // Create a new TableInput step using the selected connection... case DragAndDropContainer.TYPE_BASE_JOB_ENTRY: { // Add the job. // Since there is no job or job loaded, it should be safe to do so. // JobMeta jobMeta = new JobMeta(log); try { jobMeta.readSharedObjects(rep); } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorReadingSharedObjects.Title"), Messages.getString("Spoon.Dialog.ErrorReadingSharedObjects.Message", makeJobGraphTabName(jobMeta)), e); } addChefGraph(jobMeta); // Not an existing entry: data refers to the type of step to create String steptype = container.getData(); JobEntryCopy jobEntry = newJobEntry(jobMeta, steptype, false); jobEntry.setLocation(p); jobEntry.setDrawn(true); refreshGraph(); refreshTree(); } break; } } catch (Exception e) { new ErrorDialog(shell, Messages.getString("SpoonGraph.Dialog.ErrorDroppingObject.Message"), Messages.getString("SpoonGraph.Dialog.ErrorDroppingObject.Title"), e); } } public void dropAccept(DropTargetEvent event) { } }); } public String getRepositoryName() { if (rep == null) return null; return rep.getRepositoryInfo().getName(); } public void sqlConnection(DatabaseMeta databaseMeta) { SQLEditor sql = new SQLEditor(shell, SWT.NONE, databaseMeta, DBCache.getInstance(), ""); sql.open(); } public void editConnection(DatabaseMeta databaseMeta) { HasDatabasesInterface hasDatabasesInterface = getActiveHasDatabasesInterface(); if (hasDatabasesInterface == null) return; // program error, exit just to make sure. DatabaseMeta before = (DatabaseMeta) databaseMeta.clone(); DatabaseDialog con = new DatabaseDialog(shell, databaseMeta); con.setDatabases(hasDatabasesInterface.getDatabases()); String newname = con.open(); if (!Const.isEmpty(newname)) // null: CANCEL { // newname = db.verifyAndModifyDatabaseName(transMeta.getDatabases(), name); // Store undo/redo information DatabaseMeta after = (DatabaseMeta) databaseMeta.clone(); addUndoChange((UndoInterface) hasDatabasesInterface, new DatabaseMeta[] { before }, new DatabaseMeta[] { after }, new int[] { hasDatabasesInterface.indexOfDatabase(databaseMeta) }); saveConnection(databaseMeta); refreshTree(); } setShellText(); } public void dupeConnection(HasDatabasesInterface hasDatabasesInterface, DatabaseMeta databaseMeta) { String name = databaseMeta.getName(); int pos = hasDatabasesInterface.indexOfDatabase(databaseMeta); if (databaseMeta != null) { DatabaseMeta databaseMetaCopy = (DatabaseMeta) databaseMeta.clone(); String dupename = Messages.getString("Spoon.Various.DupeName") + name; //"(copy of) " databaseMetaCopy.setName(dupename); DatabaseDialog con = new DatabaseDialog(shell, databaseMetaCopy); String newname = con.open(); if (newname != null) // null: CANCEL { databaseMetaCopy.verifyAndModifyDatabaseName(hasDatabasesInterface.getDatabases(), name); hasDatabasesInterface.addDatabase(pos + 1, databaseMetaCopy); addUndoNew((UndoInterface) hasDatabasesInterface, new DatabaseMeta[] { (DatabaseMeta) databaseMetaCopy.clone() }, new int[] { pos + 1 }); saveConnection(databaseMetaCopy); refreshTree(); } } } public void clipConnection(DatabaseMeta databaseMeta) { String xml = XMLHandler.getXMLHeader() + databaseMeta.getXML(); toClipboard(xml); } /** * Delete a database connection * @param name The name of the database connection. */ public void delConnection(HasDatabasesInterface hasDatabasesInterface, DatabaseMeta db) { int pos = hasDatabasesInterface.indexOfDatabase(db); boolean worked = false; // delete from repository? if (rep != null) { if (!rep.getUserInfo().isReadonly()) { try { long id_database = rep.getDatabaseID(db.getName()); rep.delDatabase(id_database); worked = true; } catch (KettleDatabaseException dbe) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorDeletingConnection.Title"), Messages.getString("Spoon.Dialog.ErrorDeletingConnection.Message", db.getName()), dbe);//"Error deleting connection ["+db+"] from repository!" } } else { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorDeletingConnection.Title"), Messages.getString("Spoon.Dialog.ErrorDeletingConnection.Message", db.getName()), new KettleException(Messages.getString("Spoon.Dialog.Exception.ReadOnlyUser")));//"Error deleting connection ["+db+"] from repository!" //This user is read-only! } } if (rep == null || worked) { addUndoDelete((UndoInterface) hasDatabasesInterface, new DatabaseMeta[] { (DatabaseMeta) db.clone() }, new int[] { pos }); hasDatabasesInterface.removeDatabase(pos); } refreshTree(); setShellText(); } public String editStep(TransMeta transMeta, StepMeta stepMeta) { boolean refresh = false; try { String name = stepMeta.getName(); // Before we do anything, let's store the situation the way it was... StepMeta before = (StepMeta) stepMeta.clone(); StepMetaInterface stepint = stepMeta.getStepMetaInterface(); StepDialogInterface dialog = stepint.getDialog(shell, stepMeta.getStepMetaInterface(), transMeta, name); dialog.setRepository(rep); String stepname = dialog.open(); if (stepname != null) { // // See if the new name the user enter, doesn't collide with another step. // If so, change the stepname and warn the user! // String newname = stepname; StepMeta smeta = transMeta.findStep(newname, stepMeta); int nr = 2; while (smeta != null) { newname = stepname + " " + nr; smeta = transMeta.findStep(newname); nr++; } if (nr > 2) { stepname = newname; MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION); mb.setMessage(Messages.getString("Spoon.Dialog.StepnameExists.Message", stepname)); // $NON-NLS-1$ mb.setText(Messages.getString("Spoon.Dialog.StepnameExists.Title")); // $NON-NLS-1$ mb.open(); } if (!stepname.equals(name)) refresh = true; stepMeta.setName(stepname); // // OK, so the step has changed... // Backup the situation for undo/redo // StepMeta after = (StepMeta) stepMeta.clone(); addUndoChange(transMeta, new StepMeta[] { before }, new StepMeta[] { after }, new int[] { transMeta.indexOfStep(stepMeta) }); } else { // Scenario: change connections and click cancel... // Perhaps new connections were created in the step dialog? if (transMeta.haveConnectionsChanged()) { refresh = true; } } refreshGraph(); // name is displayed on the graph too. // TODO: verify "double pathway" steps for bug #4365 // After the step was edited we can complain about the possible deadlock here. // } catch (Throwable e) { if (shell.isDisposed()) return null; new ErrorDialog(shell, Messages.getString("Spoon.Dialog.UnableOpenDialog.Title"), Messages.getString("Spoon.Dialog.UnableOpenDialog.Message"), new Exception(e));//"Unable to open dialog for this step" } if (refresh) refreshTree(); // Perhaps new connections were created in the step dialog or the step name changed. return stepMeta.getName(); } public void editStepErrorHandling(TransMeta transMeta, StepMeta stepMeta) { if (stepMeta != null && stepMeta.supportsErrorHandling()) { StepErrorMeta stepErrorMeta = stepMeta.getStepErrorMeta(); if (stepErrorMeta == null) { stepErrorMeta = new StepErrorMeta(stepMeta); } List targetSteps = new ArrayList(); int nrNext = transMeta.findNrNextSteps(stepMeta); for (int i = 0; i < nrNext; i++) targetSteps.add(transMeta.findNextStep(stepMeta, i)); // now edit this stepErrorMeta object: StepErrorMetaDialog dialog = new StepErrorMetaDialog(shell, stepErrorMeta, targetSteps); if (dialog.open()) { stepMeta.setStepErrorMeta(stepErrorMeta); refreshGraph(); } } } public void dupeStep(TransMeta transMeta, StepMeta stepMeta) { log.logDebug(toString(), Messages.getString("Spoon.Log.DuplicateStep") + stepMeta.getName());//Duplicate step: StepMeta stMeta = (StepMeta) stepMeta.clone(); if (stMeta != null) { String newname = transMeta.getAlternativeStepname(stepMeta.getName()); int nr = 2; while (transMeta.findStep(newname) != null) { newname = stepMeta.getName() + " (copy " + nr + ")"; nr++; } stMeta.setName(newname); // Don't select this new step! stMeta.setSelected(false); Point loc = stMeta.getLocation(); stMeta.setLocation(loc.x + 20, loc.y + 20); transMeta.addStep(stMeta); addUndoNew(transMeta, new StepMeta[] { (StepMeta) stMeta.clone() }, new int[] { transMeta.indexOfStep(stMeta) }); refreshTree(); refreshGraph(); } } public void clipStep(StepMeta stepMeta) { String xml = stepMeta.getXML(); toClipboard(xml); } public void pasteXML(TransMeta transMeta, String clipcontent, Point loc) { try { Document doc = XMLHandler.loadXMLString(clipcontent); Node transnode = XMLHandler.getSubNode(doc, "transformation"); // De-select all, re-select pasted steps... transMeta.unselectAll(); Node stepsnode = XMLHandler.getSubNode(transnode, "steps"); int nr = XMLHandler.countNodes(stepsnode, "step"); log.logDebug(toString(), Messages.getString("Spoon.Log.FoundSteps", "" + nr) + loc);//"I found "+nr+" steps to paste on location: " StepMeta steps[] = new StepMeta[nr]; //Point min = new Point(loc.x, loc.y); Point min = new Point(99999999, 99999999); // Load the steps... for (int i = 0; i < nr; i++) { Node stepnode = XMLHandler.getSubNodeByNr(stepsnode, "step", i); steps[i] = new StepMeta(stepnode, transMeta.getDatabases(), transMeta.getCounters()); if (loc != null) { Point p = steps[i].getLocation(); if (min.x > p.x) min.x = p.x; if (min.y > p.y) min.y = p.y; } } // Load the hops... Node hopsnode = XMLHandler.getSubNode(transnode, "order"); nr = XMLHandler.countNodes(hopsnode, "hop"); log.logDebug(toString(), Messages.getString("Spoon.Log.FoundHops", "" + nr));//"I found "+nr+" hops to paste." TransHopMeta hops[] = new TransHopMeta[nr]; ArrayList alSteps = new ArrayList(); for (int i = 0; i < steps.length; i++) alSteps.add(steps[i]); for (int i = 0; i < nr; i++) { Node hopnode = XMLHandler.getSubNodeByNr(hopsnode, "hop", i); hops[i] = new TransHopMeta(hopnode, alSteps); } // What's the difference between loc and min? // This is the offset: Point offset = new Point(loc.x - min.x, loc.y - min.y); // Undo/redo object positions... int position[] = new int[steps.length]; for (int i = 0; i < steps.length; i++) { Point p = steps[i].getLocation(); String name = steps[i].getName(); steps[i].setLocation(p.x + offset.x, p.y + offset.y); steps[i].setDraw(true); // Check the name, find alternative... steps[i].setName(transMeta.getAlternativeStepname(name)); transMeta.addStep(steps[i]); position[i] = transMeta.indexOfStep(steps[i]); steps[i].setSelected(true); } // Add the hops too... for (int i = 0; i < hops.length; i++) { transMeta.addTransHop(hops[i]); } // Load the notes... Node notesnode = XMLHandler.getSubNode(transnode, "notepads"); nr = XMLHandler.countNodes(notesnode, "notepad"); log.logDebug(toString(), Messages.getString("Spoon.Log.FoundNotepads", "" + nr));//"I found "+nr+" notepads to paste." NotePadMeta notes[] = new NotePadMeta[nr]; for (int i = 0; i < notes.length; i++) { Node notenode = XMLHandler.getSubNodeByNr(notesnode, "notepad", i); notes[i] = new NotePadMeta(notenode); Point p = notes[i].getLocation(); notes[i].setLocation(p.x + offset.x, p.y + offset.y); transMeta.addNote(notes[i]); notes[i].setSelected(true); } // Set the source and target steps ... for (int i = 0; i < steps.length; i++) { StepMetaInterface smi = steps[i].getStepMetaInterface(); smi.searchInfoAndTargetSteps(transMeta.getSteps()); } // Save undo information too... addUndoNew(transMeta, steps, position, false); int hoppos[] = new int[hops.length]; for (int i = 0; i < hops.length; i++) hoppos[i] = transMeta.indexOfTransHop(hops[i]); addUndoNew(transMeta, hops, hoppos, true); int notepos[] = new int[notes.length]; for (int i = 0; i < notes.length; i++) notepos[i] = transMeta.indexOfNote(notes[i]); addUndoNew(transMeta, notes, notepos, true); if (transMeta.haveStepsChanged()) { refreshTree(); refreshGraph(); } } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.UnablePasteSteps.Title"), Messages.getString("Spoon.Dialog.UnablePasteSteps.Message"), e);//"Error pasting steps...", "I was unable to paste steps to this transformation" } } public void copySelected(TransMeta transMeta, StepMeta stepMeta[], NotePadMeta notePadMeta[]) { if (stepMeta == null || stepMeta.length == 0) return; String xml = XMLHandler.getXMLHeader(); xml += "<transformation>" + Const.CR; xml += " <steps>" + Const.CR; for (int i = 0; i < stepMeta.length; i++) { xml += stepMeta[i].getXML(); } xml += " </steps>" + Const.CR; // // Also check for the hops in between the selected steps... // xml += "<order>" + Const.CR; if (stepMeta != null) for (int i = 0; i < stepMeta.length; i++) { for (int j = 0; j < stepMeta.length; j++) { if (i != j) { TransHopMeta hop = transMeta.findTransHop(stepMeta[i], stepMeta[j], true); if (hop != null) // Ok, we found one... { xml += hop.getXML() + Const.CR; } } } } xml += " </order>" + Const.CR; xml += " <notepads>" + Const.CR; if (notePadMeta != null) for (int i = 0; i < notePadMeta.length; i++) { xml += notePadMeta[i].getXML(); } xml += " </notepads>" + Const.CR; xml += " </transformation>" + Const.CR; toClipboard(xml); } public void delStep(TransMeta transMeta, StepMeta stepMeta) { log.logDebug(toString(), Messages.getString("Spoon.Log.DeleteStep") + stepMeta.getName());//"Delete step: " for (int i = transMeta.nrTransHops() - 1; i >= 0; i--) { TransHopMeta hi = transMeta.getTransHop(i); if (hi.getFromStep().equals(stepMeta) || hi.getToStep().equals(stepMeta)) { addUndoDelete(transMeta, new TransHopMeta[] { hi }, new int[] { transMeta.indexOfTransHop(hi) }, true); transMeta.removeTransHop(i); refreshTree(); } } int pos = transMeta.indexOfStep(stepMeta); transMeta.removeStep(pos); addUndoDelete(transMeta, new StepMeta[] { stepMeta }, new int[] { pos }); refreshTree(); refreshGraph(); } public void editHop(TransMeta transMeta, TransHopMeta transHopMeta) { // Backup situation BEFORE edit: String name = transHopMeta.toString(); TransHopMeta before = (TransHopMeta) transHopMeta.clone(); TransHopDialog hd = new TransHopDialog(shell, SWT.NONE, transHopMeta, transMeta); if (hd.open() != null) { // Backup situation for redo/undo: TransHopMeta after = (TransHopMeta) transHopMeta.clone(); addUndoChange(transMeta, new TransHopMeta[] { before }, new TransHopMeta[] { after }, new int[] { transMeta.indexOfTransHop(transHopMeta) }); String newname = transHopMeta.toString(); if (!name.equalsIgnoreCase(newname)) { refreshTree(); refreshGraph(); // color, nr of copies... } } setShellText(); } public void delHop(TransMeta transMeta, TransHopMeta transHopMeta) { int i = transMeta.indexOfTransHop(transHopMeta); addUndoDelete(transMeta, new Object[] { (TransHopMeta) transHopMeta.clone() }, new int[] { transMeta.indexOfTransHop(transHopMeta) }); transMeta.removeTransHop(i); refreshTree(); refreshGraph(); } public void newHop(TransMeta transMeta, StepMeta fr, StepMeta to) { TransHopMeta hi = new TransHopMeta(fr, to); TransHopDialog hd = new TransHopDialog(shell, SWT.NONE, hi, transMeta); if (hd.open() != null) { boolean error = false; if (transMeta.findTransHop(hi.getFromStep(), hi.getToStep()) != null) { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR); mb.setMessage(Messages.getString("Spoon.Dialog.HopExists.Message"));//"This hop already exists!" mb.setText(Messages.getString("Spoon.Dialog.HopExists.Title"));//Error! mb.open(); error = true; } if (transMeta.hasLoop(fr) || transMeta.hasLoop(to)) { refreshTree(); refreshGraph(); MessageBox mb = new MessageBox(shell, SWT.YES | SWT.ICON_WARNING); mb.setMessage(Messages.getString("Spoon.Dialog.AddingHopCausesLoop.Message"));//Adding this hop causes a loop in the transformation. Loops are not allowed! mb.setText(Messages.getString("Spoon.Dialog.AddingHopCausesLoop.Title"));//Warning! mb.open(); error = true; } if (!error) { transMeta.addTransHop(hi); addUndoNew(transMeta, new TransHopMeta[] { (TransHopMeta) hi.clone() }, new int[] { transMeta.indexOfTransHop(hi) }); hi.getFromStep().drawStep(); hi.getToStep().drawStep(); refreshTree(); refreshGraph(); // Check if there are 2 hops coming out of the "From" step. verifyCopyDistribute(transMeta, fr); } } } public void verifyCopyDistribute(TransMeta transMeta, StepMeta fr) { int nrNextSteps = transMeta.findNrNextSteps(fr); // don't show it for 3 or more hops, by then you should have had the message if (nrNextSteps == 2) { boolean distributes = false; if (props.showCopyOrDistributeWarning()) { MessageDialogWithToggle md = new MessageDialogWithToggle(shell, Messages.getString("System.Warning"), //"Warning!" null, Messages.getString("Spoon.Dialog.CopyOrDistribute.Message", fr.getName(), Integer.toString(nrNextSteps)), MessageDialog.WARNING, new String[] { Messages.getString("Spoon.Dialog.CopyOrDistribute.Copy"), Messages.getString("Spoon.Dialog.CopyOrDistribute.Distribute") }, //"Copy Distribute 0, Messages.getString("Spoon.Message.Warning.NotShowWarning"), //"Please, don't show this warning anymore." !props.showCopyOrDistributeWarning()); int idx = md.open(); props.setShowCopyOrDistributeWarning(!md.getToggleState()); props.saveProps(); distributes = (idx & 0xFF) == 1; } if (distributes) { fr.setDistributes(true); } else { fr.setDistributes(false); } refreshTree(); refreshGraph(); } } public void newHop(TransMeta transMeta) { newHop(transMeta, null, null); } public void newConnection() { HasDatabasesInterface hasDatabasesInterface = getActiveHasDatabasesInterface(); if (hasDatabasesInterface == null) return; DatabaseMeta databaseMeta = new DatabaseMeta(); DatabaseDialog con = new DatabaseDialog(shell, databaseMeta); String con_name = con.open(); if (!Const.isEmpty(con_name)) { databaseMeta.verifyAndModifyDatabaseName(hasDatabasesInterface.getDatabases(), null); hasDatabasesInterface.addDatabase(databaseMeta); addUndoNew((UndoInterface) hasDatabasesInterface, new DatabaseMeta[] { (DatabaseMeta) databaseMeta.clone() }, new int[] { hasDatabasesInterface.indexOfDatabase(databaseMeta) }); saveConnection(databaseMeta); refreshTree(); } } public void saveConnection(DatabaseMeta db) { // Also add to repository? if (rep != null) { if (!rep.userinfo.isReadonly()) { try { rep.lockRepository(); rep.insertLogEntry("Saving database '" + db.getName() + "'"); db.saveRep(rep); log.logDetailed(toString(), Messages.getString("Spoon.Log.SavedDatabaseConnection", db.getDatabaseName()));//"Saved database connection ["+db+"] to the repository." // Put a commit behind it! rep.commit(); db.setChanged(false); } catch (KettleException ke) { rep.rollback(); // In case of failure: undo changes! new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorSavingConnection.Title"), Messages.getString("Spoon.Dialog.ErrorSavingConnection.Message", db.getDatabaseName()), ke);//"Can't save...","Error saving connection ["+db+"] to repository!" } finally { try { rep.unlockRepository(); } catch (KettleDatabaseException e) { new ErrorDialog(shell, "Error", "Unexpected error unlocking the repository database", e); } } } else { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.UnableSave.Title"), Messages.getString("Spoon.Dialog.ErrorSavingConnection.Message", db.getDatabaseName()), new KettleException(Messages.getString("Spoon.Dialog.Exception.ReadOnlyRepositoryUser")));//This repository user is read-only! } } } public void openRepository() { int perms[] = new int[] { PermissionMeta.TYPE_PERMISSION_TRANSFORMATION }; RepositoriesDialog rd = new RepositoriesDialog(disp, perms, APP_NAME); rd.getShell().setImage(GUIResource.getInstance().getImageSpoon()); if (rd.open()) { // Close previous repository... if (rep != null) { rep.disconnect(); } rep = new Repository(log, rd.getRepository(), rd.getUser()); try { rep.connect(APP_NAME); } catch (KettleException ke) { rep = null; new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorConnectingRepository.Title"), //$NON-NLS-1$ Messages.getString("Spoon.Dialog.ErrorConnectingRepository.Message", Const.CR), ke); //$NON-NLS-1$ } TransMeta transMetas[] = getLoadedTransformations(); for (int t = 0; t < transMetas.length; t++) { TransMeta transMeta = transMetas[t]; for (int i = 0; i < transMeta.nrDatabases(); i++) { transMeta.getDatabase(i).setID(-1L); } // Set for the existing transformation the ID at -1! transMeta.setID(-1L); // Keep track of the old databases for now. ArrayList oldDatabases = transMeta.getDatabases(); // In order to re-match the databases on name (not content), we need to load the databases from the new repository. // NOTE: for purposes such as DEVELOP - TEST - PRODUCTION sycles. // first clear the list of databases, partition schemas, slave servers, clusters transMeta.setDatabases(new ArrayList()); transMeta.setPartitionSchemas(new ArrayList()); transMeta.setSlaveServers(new ArrayList()); transMeta.setClusterSchemas(new ArrayList()); // Read them from the new repository. try { transMeta.readSharedObjects(rep); } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorReadingSharedObjects.Title"), Messages.getString("Spoon.Dialog.ErrorReadingSharedObjects.Message", makeTransGraphTabName(transMeta)), e); } // Then we need to re-match the databases at save time... for (int i = 0; i < oldDatabases.size(); i++) { DatabaseMeta oldDatabase = (DatabaseMeta) oldDatabases.get(i); DatabaseMeta newDatabase = DatabaseMeta.findDatabase(transMeta.getDatabases(), oldDatabase.getName()); // If it exists, change the settings... if (newDatabase != null) { // // A database connection with the same name exists in the new repository. // Change the old connections to reflect the settings in the new repository // oldDatabase.setDatabaseInterface(newDatabase.getDatabaseInterface()); } else { // // The old database is not present in the new repository: simply add it to the list. // When the transformation gets saved, it will be added to the repository. // transMeta.addDatabase(oldDatabase); } } // For the existing transformation, change the directory too: // Try to find the same directory in the new repository... RepositoryDirectory redi = rep.getDirectoryTree().findDirectory(transMeta.getDirectory().getPath()); if (redi != null) { transMeta.setDirectory(redi); } else { transMeta.setDirectory(rep.getDirectoryTree()); // the root is the default! } } refreshTree(); setShellText(); } else { // Not cancelled? --> Clear repository... if (!rd.isCancelled()) { closeRepository(); } } } public void exploreRepository() { if (rep != null) { RepositoryExplorerDialog erd = new RepositoryExplorerDialog(shell, SWT.NONE, rep, rep.getUserInfo()); String objname = erd.open(); if (objname != null) { String object_type = erd.getObjectType(); RepositoryDirectory repdir = erd.getObjectDirectory(); // Try to open the selected transformation. if (object_type.equals(RepositoryExplorerDialog.STRING_TRANSFORMATIONS)) { try { TransLoadProgressDialog progressDialog = new TransLoadProgressDialog(shell, rep, objname, repdir); TransMeta transMeta = progressDialog.open(); transMeta.clearChanged(); transMeta.setFilename(objname); addSpoonGraph(transMeta); refreshTree(); refreshGraph(); } catch (Exception e) { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR); mb.setMessage(Messages.getString("Spoon.Dialog.ErrorOpening.Message") + objname + Const.CR + e.getMessage());//"Error opening : " mb.setText(Messages.getString("Spoon.Dialog.ErrorOpening.Title")); mb.open(); } } else // Try to open the selected job. if (object_type.equals(RepositoryExplorerDialog.STRING_JOBS)) { try { JobLoadProgressDialog progressDialog = new JobLoadProgressDialog(shell, rep, objname, repdir); JobMeta jobMeta = progressDialog.open(); jobMeta.clearChanged(); jobMeta.setFilename(objname); addChefGraph(jobMeta); refreshTree(); refreshGraph(); } catch (Exception e) { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR); mb.setMessage(Messages.getString("Spoon.Dialog.ErrorOpening.Message") + objname + Const.CR + e.getMessage());//"Error opening : " mb.setText(Messages.getString("Spoon.Dialog.ErrorOpening.Title")); mb.open(); } } } } } public void editRepositoryUser() { if (rep != null) { UserInfo userinfo = rep.getUserInfo(); UserDialog ud = new UserDialog(shell, SWT.NONE, rep, userinfo); UserInfo ui = ud.open(); if (!userinfo.isReadonly()) { if (ui != null) { try { ui.saveRep(rep); } catch (KettleException e) { MessageBox mb = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK); mb.setMessage(Messages.getString("Spoon.Dialog.UnableChangeUser.Message") + Const.CR + e.getMessage());//Sorry, I was unable to change this user in the repository: mb.setText(Messages.getString("Spoon.Dialog.UnableChangeUser.Title"));//"Edit user" mb.open(); } } } else { MessageBox mb = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK); mb.setMessage(Messages.getString("Spoon.Dialog.NotAllowedChangeUser.Message"));//"Sorry, you are not allowed to change this user." mb.setText(Messages.getString("Spoon.Dialog.NotAllowedChangeUser.Title")); mb.open(); } } } public void closeRepository() { if (rep != null) rep.disconnect(); rep = null; setShellText(); } public void openFile(boolean importfile) { if (rep == null || importfile) // Load from XML { FileDialog dialog = new FileDialog(shell, SWT.OPEN); dialog.setFilterExtensions(Const.STRING_TRANS_AND_JOB_FILTER_EXT); dialog.setFilterNames(Const.getTransformationAndJobFilterNames()); String fname = dialog.open(); if (fname != null) { openFile(fname, importfile); } } else { SelectObjectDialog sod = new SelectObjectDialog(shell, rep); if (sod.open() != null) { String type = sod.getObjectType(); String name = sod.getObjectName(); RepositoryDirectory repdir = sod.getDirectory(); // Load a transformation if (RepositoryObject.STRING_OBJECT_TYPE_TRANSFORMATION.equals(type)) { TransLoadProgressDialog tlpd = new TransLoadProgressDialog(shell, rep, name, repdir); TransMeta transMeta = tlpd.open(); if (transMeta != null) { log.logDetailed(toString(), Messages.getString("Spoon.Log.LoadToTransformation", name, repdir.getDirectoryName()));//"Transformation ["+transname+"] in directory ["+repdir+"] loaded from the repository." props.addLastFile(LastUsedFile.FILE_TYPE_TRANSFORMATION, name, repdir.getPath(), true, rep.getName()); addMenuLast(); transMeta.clearChanged(); transMeta.setFilename(name); addSpoonGraph(transMeta); } refreshGraph(); refreshTree(); refreshHistory(); } else // Load a job if (RepositoryObject.STRING_OBJECT_TYPE_JOB.equals(type)) { JobLoadProgressDialog jlpd = new JobLoadProgressDialog(shell, rep, name, repdir); JobMeta jobMeta = jlpd.open(); if (jobMeta != null) { props.addLastFile(LastUsedFile.FILE_TYPE_JOB, name, repdir.getPath(), true, rep.getName()); saveSettings(); addMenuLast(); addChefGraph(jobMeta); } refreshGraph(); refreshTree(); } } } } private String lastFileOpened = ""; public void openFileVFSFile() { // "Open a file", "Specify the URL of the file to open:" EnterStringDialog enterStringDialog = new EnterStringDialog(shell, lastFileOpened, Messages.getString("Spoon.Dialog.OpenFileVFS.Title"), Messages.getString("Spoon.Dialog.OpenFileVFS.Message")); String fileName = enterStringDialog.open(); if (fileName != null) { lastFileOpened = fileName; openFile(fileName, false); } } public void openFile(String fname, boolean importfile) { // Open the XML and see what's in there. // We expect a single <transformation> or <job> root at this time... try { Document document = XMLHandler.loadXMLFile(fname); boolean loaded = false; // Check for a transformation... Node transNode = XMLHandler.getSubNode(document, TransMeta.XML_TAG); if (transNode != null) // yep, found a transformation { TransMeta transMeta = new TransMeta(); transMeta.loadXML(transNode, rep, true); props.addLastFile(LastUsedFile.FILE_TYPE_TRANSFORMATION, fname, null, false, null); addMenuLast(); if (!importfile) transMeta.clearChanged(); transMeta.setFilename(fname); addSpoonGraph(transMeta); refreshTree(); refreshHistory(); loaded = true; } // Check for a job... Node jobNode = XMLHandler.getSubNode(document, JobMeta.XML_TAG); if (jobNode != null) // Indeed, found a job { JobMeta jobMeta = new JobMeta(log); jobMeta.loadXML(jobNode, rep); props.addLastFile(LastUsedFile.FILE_TYPE_JOB, fname, null, false, null); addMenuLast(); if (!importfile) jobMeta.clearChanged(); jobMeta.setFilename(fname); addChefGraph(jobMeta); loaded = true; } if (!loaded) { // Give error back MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR); mb.setMessage(Messages.getString("Spoon.UnknownFileType.Message", fname)); mb.setText(Messages.getString("Spoon.UnknownFileType.Title")); mb.open(); } } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorOpening.Title"), Messages.getString("Spoon.Dialog.ErrorOpening.Message") + fname, e); } } public void newFile() { String[] choices = new String[] { STRING_TRANSFORMATION, STRING_JOB }; EnterSelectionDialog enterSelectionDialog = new EnterSelectionDialog(shell, choices, Messages.getString("Spoon.Dialog.NewFile.Title"), Messages.getString("Spoon.Dialog.NewFile.Message")); if (enterSelectionDialog.open() != null) { switch (enterSelectionDialog.getSelectionNr()) { case 0: newTransFile(); break; case 1: newJobFile(); break; } } } public void newTransFile() { TransMeta transMeta = new TransMeta(); try { transMeta.readSharedObjects(rep); transMeta.clearChanged(); } catch (Exception e) { new ErrorDialog(shell, Messages.getString("Spoon.Exception.ErrorReadingSharedObjects.Title"), Messages.getString("Spoon.Exception.ErrorReadingSharedObjects.Message"), e); } int nr = 1; transMeta.setName(STRING_TRANSFORMATION + " " + nr); // See if a transformation with the same name isn't already loaded... while (findTransformation(makeTransGraphTabName(transMeta)) != null) { nr++; transMeta.setName(STRING_TRANSFORMATION + " " + nr); // rename } addSpoonGraph(transMeta); refreshTree(); } public boolean isDefaultTransformationName(String name) { if (!name.startsWith(STRING_TRANSFORMATION)) return false; // see if there are only digits behind the transformation... // This will detect: // "Transformation" // "Transformation " // "Transformation 1" // "Transformation 2" // ... for (int i = STRING_TRANSFORMATION.length() + 1; i < name.length(); i++) { if (!Character.isDigit(name.charAt(i))) return false; } return true; } public void newJobFile() { try { JobMeta jobMeta = new JobMeta(log); try { jobMeta.readSharedObjects(rep); } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorReadingSharedObjects.Title"), Messages .getString("Spoon.Dialog.ErrorReadingSharedObjects.Message", makeJobGraphTabName(jobMeta)), e); } int nr = 1; jobMeta.setName(STRING_JOB + " " + nr); // See if a transformation with the same name isn't already loaded... while (findJob(makeJobGraphTabName(jobMeta)) != null) { nr++; jobMeta.setName(STRING_JOB + " " + nr); // rename } addChefGraph(jobMeta); refreshTree(); } catch (Exception e) { new ErrorDialog(shell, Messages.getString("Spoon.Exception.ErrorCreatingNewJob.Title"), Messages.getString("Spoon.Exception.ErrorCreatingNewJob.Message"), e); } } public boolean isDefaultJobnName(String name) { if (!name.startsWith(STRING_JOB)) return false; // see if there are only digits behind the job... // This will detect: // "Job" // "Job " // "Job 1" // "Job 2" // ... for (int i = STRING_JOB.length() + 1; i < name.length(); i++) { if (!Character.isDigit(name.charAt(i))) return false; } return true; } public void loadRepositoryObjects(TransMeta transMeta) { // Load common database info from active repository... if (rep != null) { try { transMeta.readSharedObjects(rep); } catch (Exception e) { new ErrorDialog(shell, Messages.getString("Spoon.Error.UnableToLoadSharedObjects.Title"), Messages.getString("Spoon.Error.UnableToLoadSharedObjects.Message"), e); } } } public boolean quitFile() { log.logDetailed(toString(), Messages.getString("Spoon.Log.QuitApplication"));//"Quit application." boolean exit = true; saveSettings(); if (props.showExitWarning()) { MessageDialogWithToggle md = new MessageDialogWithToggle(shell, Messages.getString("System.Warning"), //"Warning!" null, Messages.getString("Spoon.Message.Warning.PromptExit"), // Are you sure you want to exit? MessageDialog.WARNING, new String[] { Messages.getString("Spoon.Message.Warning.Yes"), Messages.getString("Spoon.Message.Warning.No") }, //"Yes", "No" 1, Messages.getString("Spoon.Message.Warning.NotShowWarning"), //"Please, don't show this warning anymore." !props.showExitWarning()); int idx = md.open(); props.setExitWarningShown(!md.getToggleState()); props.saveProps(); if ((idx & 0xFF) == 1) return false; // No selected: don't exit! } // Check all tabs to see if we can close them... List list = new ArrayList(); list.addAll(tabMap.values()); for (Iterator iter = list.iterator(); iter.hasNext() && exit;) { TabMapEntry mapEntry = (TabMapEntry) iter.next(); TabItemInterface itemInterface = mapEntry.getObject(); if (!itemInterface.canBeClosed()) { // Show the tab tabfolder.setSelection(mapEntry.getTabItem()); // Unsaved work that needs to changes to be applied? // int reply = itemInterface.showChangedWarning(); if (reply == SWT.YES) { exit = itemInterface.applyChanges(); } else { if (reply == SWT.CANCEL) { exit = false; } else // SWT.NO { exit = true; } } /* if (mapEntry.getObject() instanceof SpoonGraph) { TransMeta transMeta = (TransMeta) mapEntry.getObject().getManagedObject(); if (transMeta.hasChanged()) { // Show the transformation in question // tabfolder.setSelection( mapEntry.getTabItem() ); // Ask if we should save it before closing... MessageBox mb = new MessageBox(shell, SWT.YES | SWT.NO | SWT.CANCEL | SWT.ICON_WARNING ); mb.setMessage(Messages.getString("Spoon.Dialog.SaveChangedFile.Message", makeGraphTabName(transMeta)));//"File has changed! Do you want to save first?" mb.setText(Messages.getString("Spoon.Dialog.SaveChangedFile.Title"));//"Warning!" int answer = mb.open(); switch(answer) { case SWT.YES: exit=saveFile(transMeta); break; case SWT.NO: exit=true; break; case SWT.CANCEL: exit=false; break; } } } // A running transformation? // if (mapEntry.getObject() instanceof SpoonLog) { SpoonLog spoonLog = (SpoonLog) mapEntry.getObject(); if (spoonLog.isRunning()) { if (reply==SWT.NO) exit=false; // No selected: don't exit! } } */ } } if (exit) // we have asked about it all and we're still here. Now close all the tabs, stop the running transformations { for (Iterator iter = list.iterator(); iter.hasNext() && exit;) { TabMapEntry mapEntry = (TabMapEntry) iter.next(); if (!mapEntry.getObject().canBeClosed()) { // Unsaved transformation? // if (mapEntry.getObject() instanceof SpoonGraph) { TransMeta transMeta = (TransMeta) mapEntry.getObject().getManagedObject(); if (transMeta.hasChanged()) { mapEntry.getTabItem().dispose(); } } // A running transformation? // if (mapEntry.getObject() instanceof SpoonLog) { SpoonLog spoonLog = (SpoonLog) mapEntry.getObject(); if (spoonLog.isRunning()) { spoonLog.stop(); mapEntry.getTabItem().dispose(); } } } } } if (exit) dispose(); return exit; } public boolean saveFile() { TransMeta transMeta = getActiveTransformation(); if (transMeta != null) return saveTransFile(transMeta); JobMeta jobMeta = getActiveJob(); if (jobMeta != null) return saveJobFile(jobMeta); return false; } public boolean saveTransFile(TransMeta transMeta) { if (transMeta == null) return false; boolean saved = false; log.logDetailed(toString(), Messages.getString("Spoon.Log.SaveToFileOrRepository"));//"Save to file or repository..." if (rep != null) { saved = saveTransRepository(transMeta); } else { if (transMeta.getFilename() != null) { saved = save(transMeta, transMeta.getFilename()); } else { saved = saveTransFileAs(transMeta); } } if (saved) // all was OK { saved = saveTransSharedObjects(transMeta); } try { if (props.useDBCache()) transMeta.getDbCache().saveCache(log); } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorSavingDatabaseCache.Title"), Messages.getString("Spoon.Dialog.ErrorSavingDatabaseCache.Message"), e);//"An error occured saving the database cache to disk" } renameTabs(); // filename or name of transformation might have changed. refreshTree(); return saved; } public boolean saveTransRepository(TransMeta transMeta) { return saveTransRepository(transMeta, false); } public boolean saveTransRepository(TransMeta transMeta, boolean ask_name) { log.logDetailed(toString(), Messages.getString("Spoon.Log.SaveToRepository"));//"Save to repository..." if (rep != null) { boolean answer = true; boolean ask = ask_name; while (answer && (ask || Const.isEmpty(transMeta.getName()))) { if (!ask) { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_WARNING); mb.setMessage(Messages.getString("Spoon.Dialog.PromptTransformationName.Message"));//"Please give this transformation a name before saving it in the database." mb.setText(Messages.getString("Spoon.Dialog.PromptTransformationName.Title"));//"Transformation has no name." mb.open(); } ask = false; answer = editTransformationProperties(transMeta); } if (answer && !Const.isEmpty(transMeta.getName())) { if (!rep.getUserInfo().isReadonly()) { int response = SWT.YES; if (transMeta.showReplaceWarning(rep)) { MessageBox mb = new MessageBox(shell, SWT.YES | SWT.NO | SWT.ICON_QUESTION); mb.setMessage(Messages.getString("Spoon.Dialog.PromptOverwriteTransformation.Message", transMeta.getName(), Const.CR));//"There already is a transformation called ["+transMeta.getName()+"] in the repository."+Const.CR+"Do you want to overwrite the transformation?" mb.setText(Messages.getString("Spoon.Dialog.PromptOverwriteTransformation.Title"));//"Overwrite?" response = mb.open(); } boolean saved = false; if (response == SWT.YES) { shell.setCursor(cursor_hourglass); // Keep info on who & when this transformation was changed... transMeta.setModifiedDate(new Value("MODIFIED_DATE", Value.VALUE_TYPE_DATE)); transMeta.getModifiedDate().sysdate(); transMeta.setModifiedUser(rep.getUserInfo().getLogin()); TransSaveProgressDialog tspd = new TransSaveProgressDialog(shell, rep, transMeta); if (tspd.open()) { saved = true; if (!props.getSaveConfirmation()) { MessageDialogWithToggle md = new MessageDialogWithToggle(shell, Messages.getString("Spoon.Message.Warning.SaveOK"), //"Save OK!" null, Messages.getString("Spoon.Message.Warning.TransformationWasStored"), //"This transformation was stored in repository" MessageDialog.QUESTION, new String[] { Messages.getString("Spoon.Message.Warning.OK") }, //"OK!" 0, Messages.getString("Spoon.Message.Warning.NotShowThisMessage"), //"Don't show this message again." props.getSaveConfirmation()); md.open(); props.setSaveConfirmation(md.getToggleState()); } // Handle last opened files... props.addLastFile(LastUsedFile.FILE_TYPE_TRANSFORMATION, transMeta.getName(), transMeta.getDirectory().getPath(), true, getRepositoryName()); saveSettings(); addMenuLast(); setShellText(); } shell.setCursor(null); } return saved; } else { MessageBox mb = new MessageBox(shell, SWT.CLOSE | SWT.ICON_ERROR); mb.setMessage(Messages.getString("Spoon.Dialog.OnlyreadRepository.Message"));//"Sorry, the user you're logged on with, can only read from the repository" mb.setText(Messages.getString("Spoon.Dialog.OnlyreadRepository.Title"));//"Transformation not saved!" mb.open(); } } } else { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR); mb.setMessage(Messages.getString("Spoon.Dialog.NoRepositoryConnection.Message"));//"There is no repository connection available." mb.setText(Messages.getString("Spoon.Dialog.NoRepositoryConnection.Title"));//"No repository available." mb.open(); } return false; } public boolean saveFileAs() { TransMeta transMeta = getActiveTransformation(); if (transMeta != null) return saveTransFileAs(transMeta); JobMeta jobMeta = getActiveJob(); if (jobMeta != null) return saveJobFileAs(jobMeta); return false; } public boolean saveTransFileAs(TransMeta transMeta) { boolean saved = false; log.logBasic(toString(), Messages.getString("Spoon.Log.SaveAs"));//"Save as..." if (rep != null) { transMeta.setID(-1L); saved = saveTransRepository(transMeta, true); renameTabs(); } else { saved = saveTransXMLFile(transMeta); renameTabs(); } refreshTree(); return saved; } private void loadTransSharedObjects(TransMeta transMeta) { try { transMeta.readSharedObjects(rep); } catch (Exception e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorReadingSharedObjects.Title"), Messages .getString("Spoon.Dialog.ErrorReadingSharedObjects.Message", makeTransGraphTabName(transMeta)), e); } } private boolean saveTransSharedObjects(TransMeta transMeta) { try { transMeta.saveSharedObjects(); return true; } catch (Exception e) { log.logError(toString(), "Unable to save shared ojects: " + e.toString()); return false; } } private void loadJobSharedObjects(JobMeta jobMeta) { try { jobMeta.readSharedObjects(rep); } catch (Exception e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorReadingSharedObjects.Title"), Messages .getString("Spoon.Dialog.ErrorReadingSharedObjects.Message", makeJobGraphTabName(jobMeta)), e); } } private boolean saveJobSharedObjects(JobMeta jobMeta) { try { jobMeta.saveSharedObjects(); return true; } catch (Exception e) { log.logError(toString(), "Unable to save shared ojects: " + e.toString()); return false; } } private boolean saveXMLFile() { TransMeta transMeta = getActiveTransformation(); if (transMeta != null) return saveTransXMLFile(transMeta); JobMeta jobMeta = getActiveJob(); if (jobMeta != null) return saveJobXMLFile(jobMeta); return false; } private boolean saveTransXMLFile(TransMeta transMeta) { boolean saved = false; FileDialog dialog = new FileDialog(shell, SWT.SAVE); dialog.setFilterExtensions(Const.STRING_TRANS_FILTER_EXT); dialog.setFilterNames(Const.getTransformationFilterNames()); String fname = dialog.open(); if (fname != null) { // Is the filename ending on .ktr, .xml? boolean ending = false; for (int i = 0; i < Const.STRING_TRANS_FILTER_EXT.length - 1; i++) { if (fname.endsWith(Const.STRING_TRANS_FILTER_EXT[i].substring(1))) { ending = true; } } if (fname.endsWith(Const.STRING_TRANS_DEFAULT_EXT)) ending = true; if (!ending) { fname += Const.STRING_TRANS_DEFAULT_EXT; } // See if the file already exists... int id = SWT.YES; try { FileObject f = KettleVFS.getFileObject(fname); if (f.exists()) { MessageBox mb = new MessageBox(shell, SWT.NO | SWT.YES | SWT.ICON_WARNING); mb.setMessage(Messages.getString("Spoon.Dialog.PromptOverwriteFile.Message"));//"This file already exists. Do you want to overwrite it?" mb.setText(Messages.getString("Spoon.Dialog.PromptOverwriteFile.Title"));//"This file already exists!" id = mb.open(); } } catch (Exception e) { // TODO do we want to show an error dialog here? My first guess is not, but we might. } if (id == SWT.YES) { saved = save(transMeta, fname); transMeta.setFilename(fname); } } return saved; } private boolean save(TransMeta transMeta, String fname) { boolean saved = false; String xml = XMLHandler.getXMLHeader() + transMeta.getXML(); try { DataOutputStream dos = new DataOutputStream(KettleVFS.getOutputStream(fname, false)); dos.write(xml.getBytes(Const.XML_ENCODING)); dos.close(); saved = true; // Handle last opened files... props.addLastFile(LastUsedFile.FILE_TYPE_TRANSFORMATION, fname, null, false, null); saveSettings(); addMenuLast(); transMeta.clearChanged(); setShellText(); log.logDebug(toString(), Messages.getString("Spoon.Log.FileWritten") + " [" + fname + "]"); //"File written to } catch (Exception e) { log.logDebug(toString(), Messages.getString("Spoon.Log.ErrorOpeningFileForWriting") + e.toString());//"Error opening file for writing! --> " MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR); mb.setMessage(Messages.getString("Spoon.Dialog.ErrorSavingFile.Message") + Const.CR + e.toString());//"Error saving file:" mb.setText(Messages.getString("Spoon.Dialog.ErrorSavingFile.Title"));//"ERROR" mb.open(); } return saved; } public void helpAbout() { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION | SWT.CENTER); String mess = Messages.getString("System.ProductInfo") + Const.VERSION + Const.CR + Const.CR + Const.CR;//Kettle - Spoon version mess += Messages.getString("System.CompanyInfo") + Const.CR; mess += " " + Messages.getString("System.ProductWebsiteUrl") + Const.CR; //(c) 2001-2004 i-Bridge bvba www.kettle.be mess += Const.CR; mess += Const.CR; mess += Const.CR; mess += " Build version : " + BuildVersion.getInstance().getVersion() + Const.CR; mess += " Build date : " + BuildVersion.getInstance().getBuildDate() + Const.CR; mb.setMessage(mess); mb.setText(APP_NAME); mb.open(); } public void editUnselectAll(TransMeta transMeta) { transMeta.unselectAll(); // spoongraph.redraw(); } public void editSelectAll(TransMeta transMeta) { transMeta.selectAll(); // spoongraph.redraw(); } public void editOptions() { EnterOptionsDialog eod = new EnterOptionsDialog(shell); if (eod.open() != null) { props.saveProps(); loadSettings(); changeLooks(); MessageBox mb = new MessageBox(shell, SWT.ICON_INFORMATION); mb.setMessage(Messages.getString("Spoon.Dialog.PleaseRestartApplication.Message")); mb.setText(Messages.getString("Spoon.Dialog.PleaseRestartApplication.Title")); mb.open(); } } /** * Refresh the object selection tree (on the left of the screen) * @param complete true refreshes the complete tree, false tries to do a differential update to avoid flickering. */ public void refreshTree() { if (shell.isDisposed()) return; GUIResource guiResource = GUIResource.getInstance(); // get a list of transformations from the transformation map Collection transformations = transformationMap.values(); TransMeta[] transMetas = (TransMeta[]) transformations.toArray(new TransMeta[transformations.size()]); // get a list of jobs from the job map Collection jobs = jobMap.values(); JobMeta[] jobMetas = (JobMeta[]) jobs.toArray(new JobMeta[jobs.size()]); // Refresh the content of the tree for those transformations // // First remove the old ones. tiTrans.removeAll(); tiJobs.removeAll(); // Now add the data back // for (int t = 0; t < transMetas.length; t++) { TransMeta transMeta = transMetas[t]; // Add a tree item with the name of transformation // TreeItem tiTransName = new TreeItem(tiTrans, SWT.NONE); String name = makeTransGraphTabName(transMeta); if (Const.isEmpty(name)) name = STRING_TRANS_NO_NAME; tiTransName.setText(name); tiTransName.setImage(guiResource.getImageBol()); /////////////////////////////////////////////////////// // // Now add the database connections // TreeItem tiDbTitle = new TreeItem(tiTransName, SWT.NONE); tiDbTitle.setText(STRING_CONNECTIONS); tiDbTitle.setImage(guiResource.getImageConnection()); // Draw the connections themselves below it. for (int i = 0; i < transMeta.nrDatabases(); i++) { DatabaseMeta databaseMeta = transMeta.getDatabase(i); TreeItem tiDb = new TreeItem(tiDbTitle, SWT.NONE); tiDb.setText(databaseMeta.getName()); if (databaseMeta.isShared()) tiDb.setFont(guiResource.getFontBold()); tiDb.setImage(guiResource.getImageConnection()); } /////////////////////////////////////////////////////// // // The steps // TreeItem tiStepTitle = new TreeItem(tiTransName, SWT.NONE); tiStepTitle.setText(STRING_STEPS); tiStepTitle.setImage(guiResource.getImageBol()); // Put the steps below it. for (int i = 0; i < transMeta.nrSteps(); i++) { StepMeta stepMeta = transMeta.getStep(i); TreeItem tiStep = new TreeItem(tiStepTitle, SWT.NONE); tiStep.setText(stepMeta.getName()); if (stepMeta.isShared()) tiStep.setFont(guiResource.getFontBold()); if (!stepMeta.isDrawn()) tiStep.setForeground(guiResource.getColorGray()); tiStep.setImage(guiResource.getImageBol()); } /////////////////////////////////////////////////////// // // The hops // TreeItem tiHopTitle = new TreeItem(tiTransName, SWT.NONE); tiHopTitle.setText(STRING_HOPS); tiHopTitle.setImage(guiResource.getImageHop()); // Put the steps below it. for (int i = 0; i < transMeta.nrTransHops(); i++) { TransHopMeta hopMeta = transMeta.getTransHop(i); TreeItem tiHop = new TreeItem(tiHopTitle, SWT.NONE); tiHop.setText(hopMeta.toString()); tiHop.setImage(guiResource.getImageHop()); } /////////////////////////////////////////////////////// // // The partitions // TreeItem tiPartitionTitle = new TreeItem(tiTransName, SWT.NONE); tiPartitionTitle.setText(STRING_PARTITIONS); tiPartitionTitle.setImage(guiResource.getImageConnection()); // Put the steps below it. for (int i = 0; i < transMeta.getPartitionSchemas().size(); i++) { PartitionSchema partitionSchema = (PartitionSchema) transMeta.getPartitionSchemas().get(i); TreeItem tiPartition = new TreeItem(tiPartitionTitle, SWT.NONE); tiPartition.setText(partitionSchema.getName()); tiPartition.setImage(guiResource.getImageBol()); if (partitionSchema.isShared()) tiPartition.setFont(guiResource.getFontBold()); } /////////////////////////////////////////////////////// // // The slaves // TreeItem tiSlaveTitle = new TreeItem(tiTransName, SWT.NONE); tiSlaveTitle.setText(STRING_SLAVES); tiSlaveTitle.setImage(guiResource.getImageBol()); // Put the steps below it. for (int i = 0; i < transMeta.getSlaveServers().size(); i++) { SlaveServer slaveServer = (SlaveServer) transMeta.getSlaveServers().get(i); TreeItem tiSlave = new TreeItem(tiSlaveTitle, SWT.NONE); tiSlave.setText(slaveServer.getName()); tiSlave.setImage(guiResource.getImageBol()); if (slaveServer.isShared()) tiSlave.setFont(guiResource.getFontBold()); } /////////////////////////////////////////////////////// // // The clusters // TreeItem tiClusterTitle = new TreeItem(tiTransName, SWT.NONE); tiClusterTitle.setText(STRING_CLUSTERS); tiClusterTitle.setImage(guiResource.getImageBol()); // Put the steps below it. for (int i = 0; i < transMeta.getClusterSchemas().size(); i++) { ClusterSchema clusterSchema = (ClusterSchema) transMeta.getClusterSchemas().get(i); TreeItem tiCluster = new TreeItem(tiClusterTitle, SWT.NONE); tiCluster.setText(clusterSchema.toString()); tiCluster.setImage(guiResource.getImageBol()); if (clusterSchema.isShared()) tiCluster.setFont(guiResource.getFontBold()); } } // Now add the jobs // for (int t = 0; t < jobMetas.length; t++) { JobMeta jobMeta = jobMetas[t]; // Add a tree item with the name of job // TreeItem tiJobName = new TreeItem(tiJobs, SWT.NONE); String name = makeJobGraphTabName(jobMeta); if (Const.isEmpty(name)) name = STRING_JOB_NO_NAME; tiJobName.setText(name); tiJobName.setImage(guiResource.getImageBol()); /////////////////////////////////////////////////////// // // Now add the database connections // TreeItem tiDbTitle = new TreeItem(tiJobName, SWT.NONE); tiDbTitle.setText(STRING_CONNECTIONS); tiDbTitle.setImage(guiResource.getImageConnection()); // Draw the connections themselves below it. for (int i = 0; i < jobMeta.nrDatabases(); i++) { DatabaseMeta databaseMeta = jobMeta.getDatabase(i); TreeItem tiDb = new TreeItem(tiDbTitle, SWT.NONE); tiDb.setText(databaseMeta.getName()); if (databaseMeta.isShared()) tiDb.setFont(guiResource.getFontBold()); tiDb.setImage(guiResource.getImageConnection()); } /////////////////////////////////////////////////////// // // The job entries // TreeItem tiJobEntriesTitle = new TreeItem(tiJobName, SWT.NONE); tiJobEntriesTitle.setText(STRING_JOB_ENTRIES); tiJobEntriesTitle.setImage(guiResource.getImageBol()); // Put the steps below it. for (int i = 0; i < jobMeta.nrJobEntries(); i++) { JobEntryCopy jobEntry = jobMeta.getJobEntry(i); TreeItem tiJobEntry = Const.findTreeItem(tiJobEntriesTitle, jobEntry.getName()); if (tiJobEntry != null) continue; // only show it once tiJobEntry = new TreeItem(tiJobEntriesTitle, SWT.NONE); tiJobEntry.setText(jobEntry.getName()); // if (jobEntry.isShared()) tiStep.setFont(guiResource.getFontBold()); TODO: allow job entries to be shared as well... if (jobEntry.isStart()) { tiJobEntry.setImage(GUIResource.getInstance().getImageStart()); } else if (jobEntry.isDummy()) { tiJobEntry.setImage(GUIResource.getInstance().getImageDummy()); } else { Image image = (Image) GUIResource.getInstance().getImagesJobentriesSmall() .get(jobEntry.getTypeDesc()); tiJobEntry.setImage(image); } } } // Set the expanded state of the complete tree. TreeMemory.setExpandedFromMemory(selectionTree, STRING_SPOON_MAIN_TREE); selectionTree.setFocus(); setShellText(); } public String getActiveTabText() { if (tabfolder.getSelection() == null) return null; return tabfolder.getSelection().getText(); } public void refreshGraph() { if (shell.isDisposed()) return; String tabText = getActiveTabText(); if (tabText == null) return; TabMapEntry tabMapEntry = (TabMapEntry) tabMap.get(tabText); if (tabMapEntry.getObject() instanceof SpoonGraph) { SpoonGraph spoonGraph = (SpoonGraph) tabMapEntry.getObject(); spoonGraph.redraw(); } if (tabMapEntry.getObject() instanceof ChefGraph) { ChefGraph chefGraph = (ChefGraph) tabMapEntry.getObject(); chefGraph.redraw(); } setShellText(); } public void refreshHistory() { final SpoonHistory spoonHistory = getActiveSpoonHistory(); if (spoonHistory != null) { spoonHistory.markRefreshNeeded(); } } public StepMeta newStep(TransMeta transMeta) { return newStep(transMeta, true, true); } public StepMeta newStep(TransMeta transMeta, boolean openit, boolean rename) { if (transMeta == null) return null; TreeItem ti[] = selectionTree.getSelection(); StepMeta inf = null; if (ti.length == 1) { String steptype = ti[0].getText(); log.logDebug(toString(), Messages.getString("Spoon.Log.NewStep") + steptype);//"New step: " inf = newStep(transMeta, steptype, steptype, openit, rename); } return inf; } /** * Allocate new step, optionally open and rename it. * * @param name Name of the new step * @param description Description of the type of step * @param openit Open the dialog for this step? * @param rename Rename this step? * * @return The newly created StepMeta object. * */ public StepMeta newStep(TransMeta transMeta, String name, String description, boolean openit, boolean rename) { StepMeta inf = null; // See if we need to rename the step to avoid doubles! if (rename && transMeta.findStep(name) != null) { int i = 2; String newname = name + " " + i; while (transMeta.findStep(newname) != null) { i++; newname = name + " " + i; } name = newname; } StepLoader steploader = StepLoader.getInstance(); StepPlugin stepPlugin = null; String locale = LanguageChoice.getInstance().getDefaultLocale().toString().toLowerCase(); try { stepPlugin = steploader.findStepPluginWithDescription(description, locale); if (stepPlugin != null) { StepMetaInterface info = BaseStep.getStepInfo(stepPlugin, steploader); info.setDefault(); if (openit) { StepDialogInterface dialog = info.getDialog(shell, info, transMeta, name); name = dialog.open(); } inf = new StepMeta(stepPlugin.getID()[0], name, info); if (name != null) // OK pressed in the dialog: we have a step-name { String newname = name; StepMeta stepMeta = transMeta.findStep(newname); int nr = 2; while (stepMeta != null) { newname = name + " " + nr; stepMeta = transMeta.findStep(newname); nr++; } if (nr > 2) { inf.setName(newname); MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION); mb.setMessage(Messages.getString("Spoon.Dialog.ChangeStepname.Message", newname));//"This stepname already exists. Spoon changed the stepname to ["+newname+"]" mb.setText(Messages.getString("Spoon.Dialog.ChangeStepname.Title"));//"Info!" mb.open(); } inf.setLocation(20, 20); // default location at (20,20) transMeta.addStep(inf); // Save for later: // if openit is false: we drag&drop it onto the canvas! if (openit) { addUndoNew(transMeta, new StepMeta[] { inf }, new int[] { transMeta.indexOfStep(inf) }); } // Also store it in the pluginHistory list... props.addPluginHistory(stepPlugin.getID()[0]); refreshTree(); } else { return null; // Cancel pressed in dialog. } setShellText(); } } catch (KettleException e) { String filename = stepPlugin.getErrorHelpFile(); if (stepPlugin != null && !Const.isEmpty(filename)) { // OK, in stead of a normal error message, we give back the content of the error help file... (HTML) try { StringBuffer content = new StringBuffer(); FileInputStream fis = new FileInputStream(new File(filename)); int ch = fis.read(); while (ch >= 0) { content.append((char) ch); ch = fis.read(); } ShowBrowserDialog sbd = new ShowBrowserDialog(shell, Messages.getString("Spoon.Dialog.ErrorHelpText.Title"), content.toString());//"Error help text" sbd.open(); } catch (Exception ex) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorShowingHelpText.Title"), Messages.getString("Spoon.Dialog.ErrorShowingHelpText.Message"), ex);//"Error showing help text" } } else { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.UnableCreateNewStep.Title"), Messages.getString("Spoon.Dialog.UnableCreateNewStep.Message"), e);//"Error creating step" "I was unable to create a new step" } return null; } catch (Throwable e) { if (!shell.isDisposed()) new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorCreatingStep.Title"), Messages.getString("Spoon.Dialog.UnableCreateNewStep.Message"), new Exception(e));//"Error creating step" return null; } return inf; } private void setTreeImages() { tiTrans.setImage(GUIResource.getInstance().getImageBol()); tiJobs.setImage(GUIResource.getInstance().getImageBol()); TreeItem tiBaseCat[] = tiTransBase.getItems(); for (int x = 0; x < tiBaseCat.length; x++) { tiBaseCat[x].setImage(GUIResource.getInstance().getImageBol()); TreeItem ti[] = tiBaseCat[x].getItems(); for (int i = 0; i < ti.length; i++) { TreeItem stepitem = ti[i]; String description = stepitem.getText(); StepLoader steploader = StepLoader.getInstance(); StepPlugin sp = steploader.findStepPluginWithDescription(description); if (sp != null) { Image stepimg = (Image) GUIResource.getInstance().getImagesStepsSmall().get(sp.getID()[0]); if (stepimg != null) { stepitem.setImage(stepimg); } } } } } public void setShellText() { if (shell.isDisposed()) return; String fname = null; String name = null; long id = -1L; ChangedFlagInterface changed = null; TransMeta transMeta = getActiveTransformation(); if (transMeta != null) { changed = transMeta; fname = transMeta.getFilename(); name = transMeta.getName(); id = transMeta.getID(); } JobMeta jobMeta = getActiveJob(); if (jobMeta != null) { changed = jobMeta; fname = jobMeta.getFilename(); name = jobMeta.getName(); id = jobMeta.getID(); } String text = ""; if (rep != null) { text += APPL_TITLE + " - [" + getRepositoryName() + "] "; } else { text += APPL_TITLE + " - "; } if (rep != null && id > 0) { if (Const.isEmpty(name)) { text += Messages.getString("Spoon.Various.NoName");//"[no name]" } else { text += name; } } else { if (!Const.isEmpty(fname)) { text += fname; } } if (changed != null && changed.hasChanged()) { text += " " + Messages.getString("Spoon.Various.Changed"); } shell.setText(text); enableMenus(); markTabsChanged(); } public void enableMenus() { boolean enableTransMenu = getActiveTransformation() != null; boolean enableJobMenu = getActiveJob() != null; boolean enableRepositoryMenu = rep != null; // Only enable certain menu-items if we need to. miFileSave.setEnabled(enableTransMenu || enableJobMenu); miFileSaveAs.setEnabled(enableTransMenu || enableJobMenu); miFileClose.setEnabled(enableTransMenu || enableJobMenu); miFilePrint.setEnabled(enableTransMenu || enableJobMenu); miEditUndo.setEnabled(enableTransMenu || enableJobMenu); miEditRedo.setEnabled(enableTransMenu || enableJobMenu); miEditUnselectAll.setEnabled(enableTransMenu); miEditSelectAll.setEnabled(enableTransMenu); miEditCopy.setEnabled(enableTransMenu); miEditPaste.setEnabled(enableTransMenu); // Transformations miTransRun.setEnabled(enableTransMenu); miTransPreview.setEnabled(enableTransMenu); miTransCheck.setEnabled(enableTransMenu); miTransImpact.setEnabled(enableTransMenu); miTransSQL.setEnabled(enableTransMenu); miLastImpact.setEnabled(enableTransMenu); miLastCheck.setEnabled(enableTransMenu); miLastPreview.setEnabled(enableTransMenu); miTransCopy.setEnabled(enableTransMenu); // miTransPaste.setEnabled(enableTransMenu); miTransImage.setEnabled(enableTransMenu); miTransDetails.setEnabled(enableTransMenu); // Jobs miJobRun.setEnabled(enableJobMenu); miJobCopy.setEnabled(enableJobMenu); miJobInfo.setEnabled(enableJobMenu); miWizardNewConnection.setEnabled(enableTransMenu || enableJobMenu); miWizardCopyTable.setEnabled(enableTransMenu || enableJobMenu); miWizardRipDatabase.setEnabled(enableRepositoryMenu || enableTransMenu || enableJobMenu); miRepDisconnect.setEnabled(enableRepositoryMenu); miRepExplore.setEnabled(enableRepositoryMenu); miRepUser.setEnabled(enableRepositoryMenu); // Do the bar as well tiSQL.setEnabled(enableTransMenu || enableJobMenu); tiImpact.setEnabled(enableTransMenu); tiFileCheck.setEnabled(enableTransMenu); tiFileReplay.setEnabled(enableTransMenu); tiFilePreview.setEnabled(enableTransMenu); tiFileRun.setEnabled(enableTransMenu || enableJobMenu); tiFilePrint.setEnabled(enableTransMenu || enableJobMenu); tiFileSaveAs.setEnabled(enableTransMenu || enableJobMenu); tiFileSave.setEnabled(enableTransMenu || enableJobMenu); // What steps & plugins to show? refreshCoreObjectsTree(); } private void markTabsChanged() { Collection c = tabMap.values(); for (Iterator iter = c.iterator(); iter.hasNext();) { TabMapEntry entry = (TabMapEntry) iter.next(); if (entry.getTabItem().isDisposed()) continue; boolean changed = entry.getObject().hasContentChanged(); if (changed) { entry.getTabItem().setFont(GUIResource.getInstance().getFontBold()); } else { entry.getTabItem().setFont(GUIResource.getInstance().getFontGraph()); } } } private void printFile() { TransMeta transMeta = getActiveTransformation(); if (transMeta != null) { printTransFile(transMeta); } JobMeta jobMeta = getActiveJob(); if (jobMeta != null) { printJobFile(jobMeta); } } private void printTransFile(TransMeta transMeta) { SpoonGraph spoonGraph = getActiveSpoonGraph(); if (spoonGraph == null) return; PrintSpool ps = new PrintSpool(); Printer printer = ps.getPrinter(shell); // Create an image of the screen Point max = transMeta.getMaximum(); Image img = spoonGraph.getTransformationImage(printer, max.x, max.y); ps.printImage(shell, img); img.dispose(); ps.dispose(); } private void printJobFile(JobMeta jobMeta) { ChefGraph chefGraph = getActiveChefGraph(); if (chefGraph == null) return; PrintSpool ps = new PrintSpool(); Printer printer = ps.getPrinter(shell); // Create an image of the screen Point max = jobMeta.getMaximum(); PaletteData pal = ps.getPaletteData(); ImageData imd = new ImageData(max.x, max.y, printer.getDepth(), pal); Image img = new Image(printer, imd); GC img_gc = new GC(img); // Clear the background first, fill with background color... img_gc.setForeground(GUIResource.getInstance().getColorBackground()); img_gc.fillRectangle(0, 0, max.x, max.y); // Draw the transformation... chefGraph.drawJob(img_gc); ps.printImage(shell, img); img_gc.dispose(); img.dispose(); ps.dispose(); } private SpoonGraph getActiveSpoonGraph() { TabMapEntry mapEntry = (TabMapEntry) tabMap.get(tabfolder.getSelection().getText()); if (mapEntry.getObject() instanceof SpoonGraph) return (SpoonGraph) mapEntry.getObject(); return null; } private ChefGraph getActiveChefGraph() { TabMapEntry mapEntry = (TabMapEntry) tabMap.get(tabfolder.getSelection().getText()); if (mapEntry.getObject() instanceof ChefGraph) return (ChefGraph) mapEntry.getObject(); return null; } /** * @return the Log tab associated with the active transformation */ private SpoonLog getActiveSpoonLog() { TransMeta transMeta = getActiveTransformation(); if (transMeta == null) return null; // nothing to work with. return findSpoonLogOfTransformation(transMeta); } /** * @return the Log tab associated with the active job */ private ChefLog getActiveJobLog() { JobMeta jobMeta = getActiveJob(); if (jobMeta == null) return null; // nothing to work with. return findChefLogOfJob(jobMeta); } public SpoonGraph findSpoonGraphOfTransformation(TransMeta transMeta) { // Now loop over the entries in the tab-map Collection collection = tabMap.values(); for (Iterator iter = collection.iterator(); iter.hasNext();) { TabMapEntry mapEntry = (TabMapEntry) iter.next(); if (mapEntry.getObject() instanceof SpoonGraph) { SpoonGraph spoonGraph = (SpoonGraph) mapEntry.getObject(); if (spoonGraph.getTransMeta().equals(transMeta)) return spoonGraph; } } return null; } public ChefGraph findChefGraphOfJob(JobMeta jobMeta) { // Now loop over the entries in the tab-map Collection collection = tabMap.values(); for (Iterator iter = collection.iterator(); iter.hasNext();) { TabMapEntry mapEntry = (TabMapEntry) iter.next(); if (mapEntry.getObject() instanceof ChefGraph) { ChefGraph chefGraph = (ChefGraph) mapEntry.getObject(); if (chefGraph.getJobMeta().equals(jobMeta)) return chefGraph; } } return null; } public SpoonLog findSpoonLogOfTransformation(TransMeta transMeta) { // Now loop over the entries in the tab-map Collection collection = tabMap.values(); for (Iterator iter = collection.iterator(); iter.hasNext();) { TabMapEntry mapEntry = (TabMapEntry) iter.next(); if (mapEntry.getObject() instanceof SpoonLog) { SpoonLog spoonLog = (SpoonLog) mapEntry.getObject(); if (spoonLog.getTransMeta().equals(transMeta)) return spoonLog; } } return null; } public ChefLog findChefLogOfJob(JobMeta jobMeta) { // Now loop over the entries in the tab-map Collection collection = tabMap.values(); for (Iterator iter = collection.iterator(); iter.hasNext();) { TabMapEntry mapEntry = (TabMapEntry) iter.next(); if (mapEntry.getObject() instanceof ChefLog) { ChefLog chefLog = (ChefLog) mapEntry.getObject(); if (chefLog.getJobMeta().equals(jobMeta)) return chefLog; } } return null; } public SpoonHistory findSpoonHistoryOfTransformation(TransMeta transMeta) { if (transMeta == null) return null; // Now loop over the entries in the tab-map Collection collection = tabMap.values(); for (Iterator iter = collection.iterator(); iter.hasNext();) { TabMapEntry mapEntry = (TabMapEntry) iter.next(); if (mapEntry.getObject() instanceof SpoonHistory) { SpoonHistory spoonHistory = (SpoonHistory) mapEntry.getObject(); if (spoonHistory.getTransMeta() != null && spoonHistory.getTransMeta().equals(transMeta)) return spoonHistory; } } return null; } public ChefHistory findChefHistoryOfJob(JobMeta jobMeta) { if (jobMeta == null) return null; // Now loop over the entries in the tab-map Collection collection = tabMap.values(); for (Iterator iter = collection.iterator(); iter.hasNext();) { TabMapEntry mapEntry = (TabMapEntry) iter.next(); if (mapEntry.getObject() instanceof ChefHistory) { ChefHistory chefHistory = (ChefHistory) mapEntry.getObject(); if (chefHistory.getJobMeta() != null && chefHistory.getJobMeta().equals(jobMeta)) return chefHistory; } } return null; } /** * @return the history tab associated with the active transformation */ private SpoonHistory getActiveSpoonHistory() { TransMeta transMeta = getActiveTransformation(); if (transMeta == null) return null; // nothing to work with. return findSpoonHistoryOfTransformation(transMeta); } /** * @return The active TransMeta object by looking at the selected SpoonGraph, SpoonLog, SpoonHist * If nothing valueable is selected, we return null */ public TransMeta getActiveTransformation() { if (tabfolder == null) return null; CTabItem tabItem = tabfolder.getSelection(); if (tabItem == null) return null; // What transformation is in the active tab? // SpoonLog, SpoonGraph & SpoonHist contain the same transformation // TabMapEntry mapEntry = (TabMapEntry) tabMap.get(tabfolder.getSelection().getText()); TransMeta transMeta = null; if (mapEntry != null) { if (mapEntry.getObject() instanceof SpoonGraph) transMeta = ((SpoonGraph) mapEntry.getObject()).getTransMeta(); if (mapEntry.getObject() instanceof SpoonLog) transMeta = ((SpoonLog) mapEntry.getObject()).getTransMeta(); if (mapEntry.getObject() instanceof SpoonHistory) transMeta = ((SpoonHistory) mapEntry.getObject()).getTransMeta(); } return transMeta; } /** * @return The active JobMeta object by looking at the selected ChefGraph, ChefLog, ChefHist * If nothing valueable is selected, we return null */ public JobMeta getActiveJob() { if (tabfolder == null) return null; CTabItem tabItem = tabfolder.getSelection(); if (tabItem == null) return null; // What job is in the active tab? // ChefLog, ChefGraph & ChefHist contain the same job // TabMapEntry mapEntry = (TabMapEntry) tabMap.get(tabfolder.getSelection().getText()); JobMeta jobMeta = null; if (mapEntry != null) { if (mapEntry.getObject() instanceof ChefGraph) jobMeta = ((ChefGraph) mapEntry.getObject()).getJobMeta(); if (mapEntry.getObject() instanceof ChefLog) jobMeta = ((ChefLog) mapEntry.getObject()).getJobMeta(); if (mapEntry.getObject() instanceof ChefHistory) jobMeta = ((ChefHistory) mapEntry.getObject()).getJobMeta(); } return jobMeta; } public UndoInterface getActiveUndoInterface() { TransMeta transMeta = getActiveTransformation(); if (transMeta != null) return transMeta; return getActiveJob(); } public TransMeta findTransformation(String tabItemText) { return (TransMeta) transformationMap.get(tabItemText); } public JobMeta findJob(String tabItemText) { return (JobMeta) jobMap.get(tabItemText); } public TransMeta[] getLoadedTransformations() { List list = new ArrayList(transformationMap.values()); return (TransMeta[]) list.toArray(new TransMeta[list.size()]); } public JobMeta[] getLoadedJobs() { List list = new ArrayList(jobMap.values()); return (JobMeta[]) list.toArray(new JobMeta[list.size()]); } protected boolean editTransformationProperties(TransMeta transMeta) { if (transMeta == null) return false; TransDialog tid = new TransDialog(shell, SWT.NONE, transMeta, rep); TransMeta ti = tid.open(); // In this case, load shared objects // if (tid.isSharedObjectsFileChanged()) { loadTransSharedObjects(transMeta); } if (tid.isSharedObjectsFileChanged() || ti != null) { try { transMeta.readSharedObjects(rep); } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorReadingSharedObjects.Title"), Messages.getString("Spoon.Dialog.ErrorReadingSharedObjects.Message", makeTransGraphTabName(transMeta)), e); } refreshTree(); renameTabs(); // cheap operation, might as will do it anyway } setShellText(); return ti != null; } public void saveSettings() { WindowProperty winprop = new WindowProperty(shell); winprop.setName(APPL_TITLE); props.setScreen(winprop); props.setLogLevel(log.getLogLevelDesc()); props.setLogFilter(log.getFilter()); props.setSashWeights(sashform.getWeights()); props.saveProps(); } public void loadSettings() { log.setLogLevel(props.getLogLevel()); log.setFilter(props.getLogFilter()); // transMeta.setMaxUndo(props.getMaxUndo()); DBCache.getInstance().setActive(props.useDBCache()); } public void changeLooks() { props.setLook(selectionTree); props.setLook(tabfolder, Props.WIDGET_STYLE_TAB); GUIResource.getInstance().reload(); refreshTree(); refreshGraph(); } public void undoAction(UndoInterface undoInterface) { if (undoInterface == null) return; TransAction ta = undoInterface.previousUndo(); if (ta == null) return; setUndoMenu(undoInterface); // something changed: change the menu if (undoInterface instanceof TransMeta) undoTransformationAction((TransMeta) undoInterface, ta); if (undoInterface instanceof JobMeta) undoJobAction((JobMeta) undoInterface, ta); // Put what we undo in focus if (undoInterface instanceof TransMeta) { SpoonGraph spoonGraph = findSpoonGraphOfTransformation((TransMeta) undoInterface); spoonGraph.forceFocus(); } if (undoInterface instanceof JobMeta) { ChefGraph chefGraph = findChefGraphOfJob((JobMeta) undoInterface); chefGraph.forceFocus(); } } private void undoTransformationAction(TransMeta transMeta, TransAction transAction) { switch (transAction.getType()) { // // NEW // // We created a new step : undo this... case TransAction.TYPE_ACTION_NEW_STEP: // Delete the step at correct location: for (int i = transAction.getCurrent().length - 1; i >= 0; i--) { int idx = transAction.getCurrentIndex()[i]; transMeta.removeStep(idx); } refreshTree(); refreshGraph(); break; // We created a new connection : undo this... case TransAction.TYPE_ACTION_NEW_CONNECTION: // Delete the connection at correct location: for (int i = transAction.getCurrent().length - 1; i >= 0; i--) { int idx = transAction.getCurrentIndex()[i]; transMeta.removeDatabase(idx); } refreshTree(); refreshGraph(); break; // We created a new note : undo this... case TransAction.TYPE_ACTION_NEW_NOTE: // Delete the note at correct location: for (int i = transAction.getCurrent().length - 1; i >= 0; i--) { int idx = transAction.getCurrentIndex()[i]; transMeta.removeNote(idx); } refreshTree(); refreshGraph(); break; // We created a new hop : undo this... case TransAction.TYPE_ACTION_NEW_HOP: // Delete the hop at correct location: for (int i = transAction.getCurrent().length - 1; i >= 0; i--) { int idx = transAction.getCurrentIndex()[i]; transMeta.removeTransHop(idx); } refreshTree(); refreshGraph(); break; // We created a new slave : undo this... case TransAction.TYPE_ACTION_NEW_SLAVE: // Delete the slave at correct location: for (int i = transAction.getCurrent().length - 1; i >= 0; i--) { int idx = transAction.getCurrentIndex()[i]; transMeta.getSlaveServers().remove(idx); } refreshTree(); refreshGraph(); break; // We created a new slave : undo this... case TransAction.TYPE_ACTION_NEW_CLUSTER: // Delete the slave at correct location: for (int i = transAction.getCurrent().length - 1; i >= 0; i--) { int idx = transAction.getCurrentIndex()[i]; transMeta.getClusterSchemas().remove(idx); } refreshTree(); refreshGraph(); break; // // DELETE // // We delete a step : undo this... case TransAction.TYPE_ACTION_DELETE_STEP: // un-Delete the step at correct location: re-insert for (int i = 0; i < transAction.getCurrent().length; i++) { StepMeta stepMeta = (StepMeta) transAction.getCurrent()[i]; int idx = transAction.getCurrentIndex()[i]; transMeta.addStep(idx, stepMeta); } refreshTree(); refreshGraph(); break; // We deleted a connection : undo this... case TransAction.TYPE_ACTION_DELETE_CONNECTION: // re-insert the connection at correct location: for (int i = 0; i < transAction.getCurrent().length; i++) { DatabaseMeta ci = (DatabaseMeta) transAction.getCurrent()[i]; int idx = transAction.getCurrentIndex()[i]; transMeta.addDatabase(idx, ci); } refreshTree(); refreshGraph(); break; // We delete new note : undo this... case TransAction.TYPE_ACTION_DELETE_NOTE: // re-insert the note at correct location: for (int i = 0; i < transAction.getCurrent().length; i++) { NotePadMeta ni = (NotePadMeta) transAction.getCurrent()[i]; int idx = transAction.getCurrentIndex()[i]; transMeta.addNote(idx, ni); } refreshTree(); refreshGraph(); break; // We deleted a hop : undo this... case TransAction.TYPE_ACTION_DELETE_HOP: // re-insert the hop at correct location: for (int i = 0; i < transAction.getCurrent().length; i++) { TransHopMeta hi = (TransHopMeta) transAction.getCurrent()[i]; int idx = transAction.getCurrentIndex()[i]; // Build a new hop: StepMeta from = transMeta.findStep(hi.getFromStep().getName()); StepMeta to = transMeta.findStep(hi.getToStep().getName()); TransHopMeta hinew = new TransHopMeta(from, to); transMeta.addTransHop(idx, hinew); } refreshTree(); refreshGraph(); break; // // CHANGE // // We changed a step : undo this... case TransAction.TYPE_ACTION_CHANGE_STEP: // Delete the current step, insert previous version. for (int i = 0; i < transAction.getCurrent().length; i++) { StepMeta prev = (StepMeta) ((StepMeta) transAction.getPrevious()[i]).clone(); int idx = transAction.getCurrentIndex()[i]; transMeta.getStep(idx).replaceMeta(prev); } refreshTree(); refreshGraph(); break; // We changed a connection : undo this... case TransAction.TYPE_ACTION_CHANGE_CONNECTION: // Delete & re-insert for (int i = 0; i < transAction.getCurrent().length; i++) { DatabaseMeta prev = (DatabaseMeta) transAction.getPrevious()[i]; int idx = transAction.getCurrentIndex()[i]; transMeta.getDatabase(idx).replaceMeta((DatabaseMeta) prev.clone()); } refreshTree(); refreshGraph(); break; // We changed a note : undo this... case TransAction.TYPE_ACTION_CHANGE_NOTE: // Delete & re-insert for (int i = 0; i < transAction.getCurrent().length; i++) { int idx = transAction.getCurrentIndex()[i]; transMeta.removeNote(idx); NotePadMeta prev = (NotePadMeta) transAction.getPrevious()[i]; transMeta.addNote(idx, (NotePadMeta) prev.clone()); } refreshTree(); refreshGraph(); break; // We changed a hop : undo this... case TransAction.TYPE_ACTION_CHANGE_HOP: // Delete & re-insert for (int i = 0; i < transAction.getCurrent().length; i++) { TransHopMeta prev = (TransHopMeta) transAction.getPrevious()[i]; int idx = transAction.getCurrentIndex()[i]; transMeta.removeTransHop(idx); transMeta.addTransHop(idx, (TransHopMeta) prev.clone()); } refreshTree(); refreshGraph(); break; // // POSITION // // The position of a step has changed: undo this... case TransAction.TYPE_ACTION_POSITION_STEP: // Find the location of the step: for (int i = 0; i < transAction.getCurrentIndex().length; i++) { StepMeta stepMeta = transMeta.getStep(transAction.getCurrentIndex()[i]); stepMeta.setLocation(transAction.getPreviousLocation()[i]); } refreshGraph(); break; // The position of a note has changed: undo this... case TransAction.TYPE_ACTION_POSITION_NOTE: for (int i = 0; i < transAction.getCurrentIndex().length; i++) { int idx = transAction.getCurrentIndex()[i]; NotePadMeta npi = transMeta.getNote(idx); Point prev = transAction.getPreviousLocation()[i]; npi.setLocation(prev); } refreshGraph(); break; default: break; } // OK, now check if we need to do this again... if (transMeta.viewNextUndo() != null) { if (transMeta.viewNextUndo().getNextAlso()) undoAction(transMeta); } } private void undoJobAction(JobMeta jobMeta, TransAction transAction) { switch (transAction.getType()) { // // NEW // // We created a new entry : undo this... case TransAction.TYPE_ACTION_NEW_JOB_ENTRY: // Delete the entry at correct location: { int idx[] = transAction.getCurrentIndex(); for (int i = idx.length - 1; i >= 0; i--) jobMeta.removeJobEntry(idx[i]); refreshTree(); refreshGraph(); } break; // We created a new note : undo this... case TransAction.TYPE_ACTION_NEW_NOTE: // Delete the note at correct location: { int idx[] = transAction.getCurrentIndex(); for (int i = idx.length - 1; i >= 0; i--) jobMeta.removeNote(idx[i]); refreshTree(); refreshGraph(); } break; // We created a new hop : undo this... case TransAction.TYPE_ACTION_NEW_JOB_HOP: // Delete the hop at correct location: { int idx[] = transAction.getCurrentIndex(); for (int i = idx.length - 1; i >= 0; i--) jobMeta.removeJobHop(idx[i]); refreshTree(); refreshGraph(); } break; // // DELETE // // We delete an entry : undo this... case TransAction.TYPE_ACTION_DELETE_STEP: // un-Delete the entry at correct location: re-insert { JobEntryCopy ce[] = (JobEntryCopy[]) transAction.getCurrent(); int idx[] = transAction.getCurrentIndex(); for (int i = 0; i < ce.length; i++) jobMeta.addJobEntry(idx[i], ce[i]); refreshTree(); refreshGraph(); } break; // We delete new note : undo this... case TransAction.TYPE_ACTION_DELETE_NOTE: // re-insert the note at correct location: { NotePadMeta ni[] = (NotePadMeta[]) transAction.getCurrent(); int idx[] = transAction.getCurrentIndex(); for (int i = 0; i < idx.length; i++) jobMeta.addNote(idx[i], ni[i]); refreshTree(); refreshGraph(); } break; // We deleted a new hop : undo this... case TransAction.TYPE_ACTION_DELETE_JOB_HOP: // re-insert the hop at correct location: { JobHopMeta hi[] = (JobHopMeta[]) transAction.getCurrent(); int idx[] = transAction.getCurrentIndex(); for (int i = 0; i < hi.length; i++) { jobMeta.addJobHop(idx[i], hi[i]); } refreshTree(); refreshGraph(); } break; // // CHANGE // // We changed a job entry: undo this... case TransAction.TYPE_ACTION_CHANGE_JOB_ENTRY: // Delete the current job entry, insert previous version. { for (int i = 0; i < transAction.getPrevious().length; i++) { JobEntryCopy copy = (JobEntryCopy) ((JobEntryCopy) transAction.getPrevious()[i]).clone(); jobMeta.getJobEntry(transAction.getCurrentIndex()[i]).replaceMeta(copy); } refreshTree(); refreshGraph(); } break; // We changed a note : undo this... case TransAction.TYPE_ACTION_CHANGE_NOTE: // Delete & re-insert { NotePadMeta prev[] = (NotePadMeta[]) transAction.getPrevious(); int idx[] = transAction.getCurrentIndex(); for (int i = 0; i < idx.length; i++) { jobMeta.removeNote(idx[i]); jobMeta.addNote(idx[i], prev[i]); } refreshTree(); refreshGraph(); } break; // We changed a hop : undo this... case TransAction.TYPE_ACTION_CHANGE_JOB_HOP: // Delete & re-insert { JobHopMeta prev[] = (JobHopMeta[]) transAction.getPrevious(); int idx[] = transAction.getCurrentIndex(); for (int i = 0; i < idx.length; i++) { jobMeta.removeJobHop(idx[i]); jobMeta.addJobHop(idx[i], prev[i]); } refreshTree(); refreshGraph(); } break; // // POSITION // // The position of a step has changed: undo this... case TransAction.TYPE_ACTION_POSITION_JOB_ENTRY: // Find the location of the step: { int idx[] = transAction.getCurrentIndex(); Point p[] = transAction.getPreviousLocation(); for (int i = 0; i < p.length; i++) { JobEntryCopy entry = jobMeta.getJobEntry(idx[i]); entry.setLocation(p[i]); } refreshGraph(); } break; // The position of a note has changed: undo this... case TransAction.TYPE_ACTION_POSITION_NOTE: int idx[] = transAction.getCurrentIndex(); Point prev[] = transAction.getPreviousLocation(); for (int i = 0; i < idx.length; i++) { NotePadMeta npi = jobMeta.getNote(idx[i]); npi.setLocation(prev[i]); } refreshGraph(); break; default: break; } } public void redoAction(UndoInterface undoInterface) { if (undoInterface == null) return; TransAction ta = undoInterface.nextUndo(); if (ta == null) return; setUndoMenu(undoInterface); // something changed: change the menu if (undoInterface instanceof TransMeta) redoTransformationAction((TransMeta) undoInterface, ta); if (undoInterface instanceof JobMeta) redoJobAction((JobMeta) undoInterface, ta); // Put what we redo in focus if (undoInterface instanceof TransMeta) { SpoonGraph spoonGraph = findSpoonGraphOfTransformation((TransMeta) undoInterface); spoonGraph.forceFocus(); } if (undoInterface instanceof JobMeta) { ChefGraph chefGraph = findChefGraphOfJob((JobMeta) undoInterface); chefGraph.forceFocus(); } } private void redoTransformationAction(TransMeta transMeta, TransAction transAction) { switch (transAction.getType()) { // // NEW // case TransAction.TYPE_ACTION_NEW_STEP: // re-delete the step at correct location: for (int i = 0; i < transAction.getCurrent().length; i++) { StepMeta stepMeta = (StepMeta) transAction.getCurrent()[i]; int idx = transAction.getCurrentIndex()[i]; transMeta.addStep(idx, stepMeta); refreshTree(); refreshGraph(); } break; case TransAction.TYPE_ACTION_NEW_CONNECTION: // re-insert the connection at correct location: for (int i = 0; i < transAction.getCurrent().length; i++) { DatabaseMeta ci = (DatabaseMeta) transAction.getCurrent()[i]; int idx = transAction.getCurrentIndex()[i]; transMeta.addDatabase(idx, ci); refreshTree(); refreshGraph(); } break; case TransAction.TYPE_ACTION_NEW_NOTE: // re-insert the note at correct location: for (int i = 0; i < transAction.getCurrent().length; i++) { NotePadMeta ni = (NotePadMeta) transAction.getCurrent()[i]; int idx = transAction.getCurrentIndex()[i]; transMeta.addNote(idx, ni); refreshTree(); refreshGraph(); } break; case TransAction.TYPE_ACTION_NEW_HOP: // re-insert the hop at correct location: for (int i = 0; i < transAction.getCurrent().length; i++) { TransHopMeta hi = (TransHopMeta) transAction.getCurrent()[i]; int idx = transAction.getCurrentIndex()[i]; transMeta.addTransHop(idx, hi); refreshTree(); refreshGraph(); } break; // // DELETE // case TransAction.TYPE_ACTION_DELETE_STEP: // re-remove the step at correct location: for (int i = transAction.getCurrent().length - 1; i >= 0; i--) { int idx = transAction.getCurrentIndex()[i]; transMeta.removeStep(idx); } refreshTree(); refreshGraph(); break; case TransAction.TYPE_ACTION_DELETE_CONNECTION: // re-remove the connection at correct location: for (int i = transAction.getCurrent().length - 1; i >= 0; i--) { int idx = transAction.getCurrentIndex()[i]; transMeta.removeDatabase(idx); } refreshTree(); refreshGraph(); break; case TransAction.TYPE_ACTION_DELETE_NOTE: // re-remove the note at correct location: for (int i = transAction.getCurrent().length - 1; i >= 0; i--) { int idx = transAction.getCurrentIndex()[i]; transMeta.removeNote(idx); } refreshTree(); refreshGraph(); break; case TransAction.TYPE_ACTION_DELETE_HOP: // re-remove the hop at correct location: for (int i = transAction.getCurrent().length - 1; i >= 0; i--) { int idx = transAction.getCurrentIndex()[i]; transMeta.removeTransHop(idx); } refreshTree(); refreshGraph(); break; // // CHANGE // // We changed a step : undo this... case TransAction.TYPE_ACTION_CHANGE_STEP: // Delete the current step, insert previous version. for (int i = 0; i < transAction.getCurrent().length; i++) { StepMeta stepMeta = (StepMeta) ((StepMeta) transAction.getCurrent()[i]).clone(); transMeta.getStep(transAction.getCurrentIndex()[i]).replaceMeta(stepMeta); } refreshTree(); refreshGraph(); break; // We changed a connection : undo this... case TransAction.TYPE_ACTION_CHANGE_CONNECTION: // Delete & re-insert for (int i = 0; i < transAction.getCurrent().length; i++) { DatabaseMeta databaseMeta = (DatabaseMeta) transAction.getCurrent()[i]; int idx = transAction.getCurrentIndex()[i]; transMeta.getDatabase(idx).replaceMeta((DatabaseMeta) databaseMeta.clone()); } refreshTree(); refreshGraph(); break; // We changed a note : undo this... case TransAction.TYPE_ACTION_CHANGE_NOTE: // Delete & re-insert for (int i = 0; i < transAction.getCurrent().length; i++) { NotePadMeta ni = (NotePadMeta) transAction.getCurrent()[i]; int idx = transAction.getCurrentIndex()[i]; transMeta.removeNote(idx); transMeta.addNote(idx, (NotePadMeta) ni.clone()); } refreshTree(); refreshGraph(); break; // We changed a hop : undo this... case TransAction.TYPE_ACTION_CHANGE_HOP: // Delete & re-insert for (int i = 0; i < transAction.getCurrent().length; i++) { TransHopMeta hi = (TransHopMeta) transAction.getCurrent()[i]; int idx = transAction.getCurrentIndex()[i]; transMeta.removeTransHop(idx); transMeta.addTransHop(idx, (TransHopMeta) hi.clone()); } refreshTree(); refreshGraph(); break; // // CHANGE POSITION // case TransAction.TYPE_ACTION_POSITION_STEP: for (int i = 0; i < transAction.getCurrentIndex().length; i++) { // Find & change the location of the step: StepMeta stepMeta = transMeta.getStep(transAction.getCurrentIndex()[i]); stepMeta.setLocation(transAction.getCurrentLocation()[i]); } refreshGraph(); break; case TransAction.TYPE_ACTION_POSITION_NOTE: for (int i = 0; i < transAction.getCurrentIndex().length; i++) { int idx = transAction.getCurrentIndex()[i]; NotePadMeta npi = transMeta.getNote(idx); Point curr = transAction.getCurrentLocation()[i]; npi.setLocation(curr); } refreshGraph(); break; default: break; } // OK, now check if we need to do this again... if (transMeta.viewNextUndo() != null) { if (transMeta.viewNextUndo().getNextAlso()) redoAction(transMeta); } } private void redoJobAction(JobMeta jobMeta, TransAction transAction) { switch (transAction.getType()) { // // NEW // case TransAction.TYPE_ACTION_NEW_JOB_ENTRY: // re-delete the entry at correct location: { JobEntryCopy si[] = (JobEntryCopy[]) transAction.getCurrent(); int idx[] = transAction.getCurrentIndex(); for (int i = 0; i < idx.length; i++) jobMeta.addJobEntry(idx[i], si[i]); refreshTree(); refreshGraph(); } break; case TransAction.TYPE_ACTION_NEW_NOTE: // re-insert the note at correct location: { NotePadMeta ni[] = (NotePadMeta[]) transAction.getCurrent(); int idx[] = transAction.getCurrentIndex(); for (int i = 0; i < idx.length; i++) jobMeta.addNote(idx[i], ni[i]); refreshTree(); refreshGraph(); } break; case TransAction.TYPE_ACTION_NEW_JOB_HOP: // re-insert the hop at correct location: { JobHopMeta hi[] = (JobHopMeta[]) transAction.getCurrent(); int idx[] = transAction.getCurrentIndex(); for (int i = 0; i < idx.length; i++) jobMeta.addJobHop(idx[i], hi[i]); refreshTree(); refreshGraph(); } break; // // DELETE // case TransAction.TYPE_ACTION_DELETE_JOB_ENTRY: // re-remove the entry at correct location: { int idx[] = transAction.getCurrentIndex(); for (int i = idx.length - 1; i >= 0; i--) jobMeta.removeJobEntry(idx[i]); refreshTree(); refreshGraph(); } break; case TransAction.TYPE_ACTION_DELETE_NOTE: // re-remove the note at correct location: { int idx[] = transAction.getCurrentIndex(); for (int i = idx.length - 1; i >= 0; i--) jobMeta.removeNote(idx[i]); refreshTree(); refreshGraph(); } break; case TransAction.TYPE_ACTION_DELETE_JOB_HOP: // re-remove the hop at correct location: { int idx[] = transAction.getCurrentIndex(); for (int i = idx.length - 1; i >= 0; i--) jobMeta.removeJobHop(idx[i]); refreshTree(); refreshGraph(); } break; // // CHANGE // // We changed a step : undo this... case TransAction.TYPE_ACTION_CHANGE_JOB_ENTRY: // replace with "current" version. { for (int i = 0; i < transAction.getCurrent().length; i++) { JobEntryCopy copy = (JobEntryCopy) ((JobEntryCopy) (transAction.getCurrent()[i])).clone_deep(); jobMeta.getJobEntry(transAction.getCurrentIndex()[i]).replaceMeta(copy); } refreshTree(); refreshGraph(); } break; // We changed a note : undo this... case TransAction.TYPE_ACTION_CHANGE_NOTE: // Delete & re-insert { NotePadMeta ni[] = (NotePadMeta[]) transAction.getCurrent(); int idx[] = transAction.getCurrentIndex(); for (int i = 0; i < idx.length; i++) { jobMeta.removeNote(idx[i]); jobMeta.addNote(idx[i], ni[i]); } refreshTree(); refreshGraph(); } break; // We changed a hop : undo this... case TransAction.TYPE_ACTION_CHANGE_JOB_HOP: // Delete & re-insert { JobHopMeta hi[] = (JobHopMeta[]) transAction.getCurrent(); int idx[] = transAction.getCurrentIndex(); for (int i = 0; i < idx.length; i++) { jobMeta.removeJobHop(idx[i]); jobMeta.addJobHop(idx[i], hi[i]); } refreshTree(); refreshGraph(); } break; // // CHANGE POSITION // case TransAction.TYPE_ACTION_POSITION_JOB_ENTRY: { // Find the location of the step: int idx[] = transAction.getCurrentIndex(); Point p[] = transAction.getCurrentLocation(); for (int i = 0; i < p.length; i++) { JobEntryCopy entry = jobMeta.getJobEntry(idx[i]); entry.setLocation(p[i]); } refreshGraph(); } break; case TransAction.TYPE_ACTION_POSITION_NOTE: { int idx[] = transAction.getCurrentIndex(); Point curr[] = transAction.getCurrentLocation(); for (int i = 0; i < idx.length; i++) { NotePadMeta npi = jobMeta.getNote(idx[i]); npi.setLocation(curr[i]); } refreshGraph(); } break; default: break; } } public void setUndoMenu(UndoInterface undoInterface) { if (shell.isDisposed()) return; TransAction prev = undoInterface != null ? undoInterface.viewThisUndo() : null; TransAction next = undoInterface != null ? undoInterface.viewNextUndo() : null; if (prev != null) { miEditUndo.setEnabled(true); miEditUndo.setText(Messages.getString("Spoon.Menu.Undo.Available", prev.toString()));//"Undo : "+prev.toString()+" \tCTRL-Z" } else { miEditUndo.setEnabled(false); miEditUndo.setText(Messages.getString("Spoon.Menu.Undo.NotAvailable"));//"Undo : not available \tCTRL-Z" } if (next != null) { miEditRedo.setEnabled(true); miEditRedo.setText(Messages.getString("Spoon.Menu.Redo.Available", next.toString()));//"Redo : "+next.toString()+" \tCTRL-Y" } else { miEditRedo.setEnabled(false); miEditRedo.setText(Messages.getString("Spoon.Menu.Redo.NotAvailable"));//"Redo : not available \tCTRL-Y" } } public void addUndoNew(UndoInterface undoInterface, Object obj[], int position[]) { addUndoNew(undoInterface, obj, position, false); } public void addUndoNew(UndoInterface undoInterface, Object obj[], int position[], boolean nextAlso) { undoInterface.addUndo(obj, null, position, null, null, TransMeta.TYPE_UNDO_NEW, nextAlso); setUndoMenu(undoInterface); } // Undo delete object public void addUndoDelete(UndoInterface undoInterface, Object obj[], int position[]) { addUndoDelete(undoInterface, obj, position, false); } // Undo delete object public void addUndoDelete(UndoInterface undoInterface, Object obj[], int position[], boolean nextAlso) { undoInterface.addUndo(obj, null, position, null, null, TransMeta.TYPE_UNDO_DELETE, nextAlso); setUndoMenu(undoInterface); } // Change of step, connection, hop or note... public void addUndoPosition(UndoInterface undoInterface, Object obj[], int pos[], Point prev[], Point curr[]) { // It's better to store the indexes of the objects, not the objects itself! undoInterface.addUndo(obj, null, pos, prev, curr, JobMeta.TYPE_UNDO_POSITION, false); setUndoMenu(undoInterface); } // Change of step, connection, hop or note... public void addUndoChange(UndoInterface undoInterface, Object from[], Object to[], int[] pos) { addUndoChange(undoInterface, from, to, pos, false); } // Change of step, connection, hop or note... public void addUndoChange(UndoInterface undoInterface, Object from[], Object to[], int[] pos, boolean nextAlso) { undoInterface.addUndo(from, to, pos, null, null, JobMeta.TYPE_UNDO_CHANGE, nextAlso); setUndoMenu(undoInterface); } /** * Checks *all* the steps in the transformation, puts the result in remarks list */ public void checkTrans(TransMeta transMeta) { checkTrans(transMeta, false); } /** * Check the steps in a transformation * * @param only_selected True: Check only the selected steps... */ public void checkTrans(TransMeta transMeta, boolean only_selected) { if (transMeta == null) return; SpoonGraph spoonGraph = findSpoonGraphOfTransformation(transMeta); if (spoonGraph == null) return; CheckTransProgressDialog ctpd = new CheckTransProgressDialog(shell, transMeta, spoonGraph.getRemarks(), only_selected); ctpd.open(); // manages the remarks arraylist... showLastTransCheck(); } /** * Show the remarks of the last transformation check that was run. * @see #checkTrans() */ public void showLastTransCheck() { TransMeta transMeta = getActiveTransformation(); if (transMeta == null) return; SpoonGraph spoonGraph = findSpoonGraphOfTransformation(transMeta); if (spoonGraph == null) return; CheckResultDialog crd = new CheckResultDialog(shell, SWT.NONE, spoonGraph.getRemarks()); String stepname = crd.open(); if (stepname != null) { // Go to the indicated step! StepMeta stepMeta = transMeta.findStep(stepname); if (stepMeta != null) { editStep(transMeta, stepMeta); } } } public void clearDBCache() { clearDBCache(null); } public void clearDBCache(DatabaseMeta databaseMeta) { if (databaseMeta != null) { DBCache.getInstance().clear(databaseMeta.getName()); } else { DBCache.getInstance().clear(null); } } public void exploreDB(DatabaseMeta databaseMeta) { List databases = null; HasDatabasesInterface activeHasDatabasesInterface = getActiveHasDatabasesInterface(); if (activeHasDatabasesInterface != null) databases = activeHasDatabasesInterface.getDatabases(); DatabaseExplorerDialog std = new DatabaseExplorerDialog(shell, SWT.NONE, databaseMeta, databases, true); std.open(); } public void analyseImpact(TransMeta transMeta) { if (transMeta == null) return; SpoonGraph spoonGraph = findSpoonGraphOfTransformation(transMeta); if (spoonGraph == null) return; AnalyseImpactProgressDialog aipd = new AnalyseImpactProgressDialog(shell, transMeta, spoonGraph.getImpact()); spoonGraph.setImpactFinished(aipd.open()); if (spoonGraph.isImpactFinished()) showLastImpactAnalyses(transMeta); } public void showLastImpactAnalyses(TransMeta transMeta) { if (transMeta == null) return; SpoonGraph spoonGraph = findSpoonGraphOfTransformation(transMeta); if (spoonGraph == null) return; ArrayList rows = new ArrayList(); for (int i = 0; i < spoonGraph.getImpact().size(); i++) { DatabaseImpact ii = (DatabaseImpact) spoonGraph.getImpact().get(i); rows.add(ii.getRow()); } if (rows.size() > 0) { // Display all the rows... PreviewRowsDialog prd = new PreviewRowsDialog(shell, SWT.NONE, "-", rows); prd.setTitleMessage(Messages.getString("Spoon.Dialog.ImpactAnalyses.Title"), Messages.getString("Spoon.Dialog.ImpactAnalyses.Message"));//"Impact analyses" "Result of analyses:" prd.open(); } else { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION); if (spoonGraph.isImpactFinished()) { mb.setMessage(Messages.getString("Spoon.Dialog.TransformationNoImpactOnDatabase.Message"));//"As far as I can tell, this transformation has no impact on any database." } else { mb.setMessage(Messages.getString("Spoon.Dialog.RunImpactAnalysesFirst.Message"));//"Please run the impact analyses first on this transformation." } mb.setText(Messages.getString("Spoon.Dialog.ImpactAnalyses.Title"));//Impact mb.open(); } } public void getSQL() { TransMeta transMeta = getActiveTransformation(); if (transMeta != null) getTransSQL(transMeta); JobMeta jobMeta = getActiveJob(); if (jobMeta != null) getJobSQL(jobMeta); } /** * Get & show the SQL required to run the loaded transformation... * */ public void getTransSQL(TransMeta transMeta) { GetSQLProgressDialog pspd = new GetSQLProgressDialog(shell, transMeta); ArrayList stats = pspd.open(); if (stats != null) // null means error, but we already displayed the error { if (stats.size() > 0) { SQLStatementsDialog ssd = new SQLStatementsDialog(shell, SWT.NONE, stats); ssd.open(); } else { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION); mb.setMessage(Messages.getString("Spoon.Dialog.NoSQLNeedEexecuted.Message"));//As far as I can tell, no SQL statements need to be executed before this transformation can run. mb.setText(Messages.getString("Spoon.Dialog.NoSQLNeedEexecuted.Title"));//"SQL" mb.open(); } } } /** * Get & show the SQL required to run the loaded job entry... * */ public void getJobSQL(JobMeta jobMeta) { GetJobSQLProgressDialog pspd = new GetJobSQLProgressDialog(shell, jobMeta, rep); ArrayList stats = pspd.open(); if (stats != null) // null means error, but we already displayed the error { if (stats.size() > 0) { SQLStatementsDialog ssd = new SQLStatementsDialog(shell, SWT.NONE, stats); ssd.open(); } else { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION); mb.setMessage(Messages.getString("Spoon.Dialog.JobNoSQLNeedEexecuted.Message")); //$NON-NLS-1$ mb.setText(Messages.getString("Spoon.Dialog.JobNoSQLNeedEexecuted.Title")); //$NON-NLS-1$ mb.open(); } } } public void toClipboard(String cliptext) { GUIResource.getInstance().toClipboard(cliptext); } public String fromClipboard() { return GUIResource.getInstance().fromClipboard(); } /** * Paste transformation from the clipboard... * */ public void pasteTransformation() { log.logDetailed(toString(), Messages.getString("Spoon.Log.PasteTransformationFromClipboard"));//"Paste transformation from the clipboard!" String xml = fromClipboard(); try { Document doc = XMLHandler.loadXMLString(xml); TransMeta transMeta = new TransMeta(XMLHandler.getSubNode(doc, TransMeta.XML_TAG)); addSpoonGraph(transMeta); // create a new tab refreshGraph(); refreshTree(); } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorPastingTransformation.Title"), Messages.getString("Spoon.Dialog.ErrorPastingTransformation.Message"), e);//Error pasting transformation "An error occurred pasting a transformation from the clipboard" } } /** * Paste job from the clipboard... * */ public void pasteJob() { String xml = fromClipboard(); try { Document doc = XMLHandler.loadXMLString(xml); JobMeta jobMeta = new JobMeta(log, XMLHandler.getSubNode(doc, JobMeta.XML_TAG), rep); addChefGraph(jobMeta); // create a new tab refreshGraph(); refreshTree(); } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorPastingJob.Title"), Messages.getString("Spoon.Dialog.ErrorPastingJob.Message"), e);//Error pasting transformation "An error occurred pasting a transformation from the clipboard" } } public void copyTransformation(TransMeta transMeta) { if (transMeta == null) return; toClipboard(XMLHandler.getXMLHeader() + transMeta.getXML()); } public void copyJob(JobMeta jobMeta) { if (jobMeta == null) return; toClipboard(XMLHandler.getXMLHeader() + jobMeta.getXML()); } public void copyTransformationImage(TransMeta transMeta) { SpoonGraph spoonGraph = findSpoonGraphOfTransformation(transMeta); if (spoonGraph == null) return; Clipboard clipboard = GUIResource.getInstance().getNewClipboard(); Point area = transMeta.getMaximum(); Image image = spoonGraph.getTransformationImage(Display.getCurrent(), area.x, area.y); clipboard.setContents(new Object[] { image.getImageData() }, new Transfer[] { ImageDataTransfer.getInstance() }); } /** * @return Either a TransMeta or JobMeta object */ public HasDatabasesInterface getActiveHasDatabasesInterface() { TransMeta transMeta = getActiveTransformation(); if (transMeta != null) return transMeta; return getActiveJob(); } /** * Shows a wizard that creates a new database connection... * */ private void createDatabaseWizard() { HasDatabasesInterface hasDatabasesInterface = getActiveHasDatabasesInterface(); if (hasDatabasesInterface == null) return; // nowhere to put the new database CreateDatabaseWizard cdw = new CreateDatabaseWizard(); DatabaseMeta newDBInfo = cdw.createAndRunDatabaseWizard(shell, props, hasDatabasesInterface.getDatabases()); if (newDBInfo != null) { //finished hasDatabasesInterface.addDatabase(newDBInfo); refreshTree(); refreshGraph(); } } public ArrayList getActiveDatabases() { Map map = new Hashtable(); HasDatabasesInterface hasDatabasesInterface = getActiveHasDatabasesInterface(); if (hasDatabasesInterface != null) { for (int i = 0; i < hasDatabasesInterface.nrDatabases(); i++) { map.put(hasDatabasesInterface.getDatabase(i).getName(), hasDatabasesInterface.getDatabase(i)); } } if (rep != null) { try { List repDBs = rep.getDatabases(); for (int i = 0; i < repDBs.size(); i++) { DatabaseMeta databaseMeta = (DatabaseMeta) repDBs.get(i); map.put(databaseMeta.getName(), databaseMeta); } } catch (Exception e) { log.logError(toString(), "Unexpected error reading databases from the repository: " + e.toString()); log.logError(toString(), Const.getStackTracker(e)); } } ArrayList databases = new ArrayList(); databases.addAll(map.values()); return databases; } /** * Create a transformation that extracts tables & data from a database.<p><p> * * 0) Select the database to rip<p> * 1) Select the table in the database to copy<p> * 2) Select the database to dump to<p> * 3) Select the repository directory in which it will end up<p> * 4) Select a name for the new transformation<p> * 6) Create 1 transformation for the selected table<p> */ private void copyTableWizard() { ArrayList databases = getActiveDatabases(); if (databases.size() == 0) return; // Nothing to do here final CopyTableWizardPage1 page1 = new CopyTableWizardPage1("1", databases); page1.createControl(shell); final CopyTableWizardPage2 page2 = new CopyTableWizardPage2("2"); page2.createControl(shell); Wizard wizard = new Wizard() { public boolean performFinish() { return copyTable(page1.getSourceDatabase(), page1.getTargetDatabase(), page2.getSelection()); } /** * @see org.eclipse.jface.wizard.Wizard#canFinish() */ public boolean canFinish() { return page2.canFinish(); } }; wizard.addPage(page1); wizard.addPage(page2); WizardDialog wd = new WizardDialog(shell, wizard); wd.setMinimumPageSize(700, 400); wd.open(); } public boolean copyTable(DatabaseMeta sourceDBInfo, DatabaseMeta targetDBInfo, String tablename) { try { // // Create a new transformation... // TransMeta meta = new TransMeta(); meta.addDatabase(sourceDBInfo); meta.addDatabase(targetDBInfo); // // Add a note // String note = Messages.getString("Spoon.Message.Note.ReadInformationFromTableOnDB", tablename, sourceDBInfo.getDatabaseName()) + Const.CR;//"Reads information from table ["+tablename+"] on database ["+sourceDBInfo+"]" note += Messages.getString("Spoon.Message.Note.WriteInformationToTableOnDB", tablename, targetDBInfo.getDatabaseName());//"After that, it writes the information to table ["+tablename+"] on database ["+targetDBInfo+"]" NotePadMeta ni = new NotePadMeta(note, 150, 10, -1, -1); meta.addNote(ni); // // create the source step... // String fromstepname = Messages.getString("Spoon.Message.Note.ReadFromTable", tablename); //"read from ["+tablename+"]"; TableInputMeta tii = new TableInputMeta(); tii.setDatabaseMeta(sourceDBInfo); tii.setSQL("SELECT * FROM " + tablename); StepLoader steploader = StepLoader.getInstance(); String fromstepid = steploader.getStepPluginID(tii); StepMeta fromstep = new StepMeta(fromstepid, fromstepname, tii); fromstep.setLocation(150, 100); fromstep.setDraw(true); fromstep.setDescription(Messages.getString("Spoon.Message.Note.ReadInformationFromTableOnDB", tablename, sourceDBInfo.getDatabaseName())); meta.addStep(fromstep); // // add logic to rename fields in case any of the field names contain reserved words... // Use metadata logic in SelectValues, use SelectValueInfo... // Database sourceDB = new Database(sourceDBInfo); sourceDB.connect(); // Get the fields for the input table... Row fields = sourceDB.getTableFields(tablename); // See if we need to deal with reserved words... int nrReserved = targetDBInfo.getNrReservedWords(fields); if (nrReserved > 0) { SelectValuesMeta svi = new SelectValuesMeta(); svi.allocate(0, 0, nrReserved); int nr = 0; for (int i = 0; i < fields.size(); i++) { Value v = fields.getValue(i); if (targetDBInfo.isReservedWord(v.getName())) { svi.getMetaName()[nr] = v.getName(); svi.getMetaRename()[nr] = targetDBInfo.quoteField(v.getName()); nr++; } } String selstepname = Messages.getString("Spoon.Message.Note.HandleReservedWords"); //"Handle reserved words"; String selstepid = steploader.getStepPluginID(svi); StepMeta selstep = new StepMeta(selstepid, selstepname, svi); selstep.setLocation(350, 100); selstep.setDraw(true); selstep.setDescription(Messages.getString("Spoon.Message.Note.RenamesReservedWords", targetDBInfo.getDatabaseTypeDesc()));//"Renames reserved words for "+targetDBInfo.getDatabaseTypeDesc() meta.addStep(selstep); TransHopMeta shi = new TransHopMeta(fromstep, selstep); meta.addTransHop(shi); fromstep = selstep; } // // Create the target step... // // // Add the TableOutputMeta step... // String tostepname = Messages.getString("Spoon.Message.Note.WriteToTable", tablename); // "write to ["+tablename+"]"; TableOutputMeta toi = new TableOutputMeta(); toi.setDatabaseMeta(targetDBInfo); toi.setTablename(tablename); toi.setCommitSize(200); toi.setTruncateTable(true); String tostepid = steploader.getStepPluginID(toi); StepMeta tostep = new StepMeta(tostepid, tostepname, toi); tostep.setLocation(550, 100); tostep.setDraw(true); tostep.setDescription(Messages.getString("Spoon.Message.Note.WriteInformationToTableOnDB2", tablename, targetDBInfo.getDatabaseName()));//"Write information to table ["+tablename+"] on database ["+targetDBInfo+"]" meta.addStep(tostep); // // Add a hop between the two steps... // TransHopMeta hi = new TransHopMeta(fromstep, tostep); meta.addTransHop(hi); // OK, if we're still here: overwrite the current transformation... // Set a name on this generated transformation // String name = "Copy table from [" + sourceDBInfo.getName() + "] to [" + targetDBInfo.getName() + "]"; String transName = name; int nr = 1; if (findTransformation(transName) != null) { nr++; transName = name + " " + nr; } meta.setName(transName); addSpoonGraph(meta); refreshGraph(); refreshTree(); } catch (Exception e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.UnexpectedError.Title"), Messages.getString("Spoon.Dialog.UnexpectedError.Message"), new KettleException(e.getMessage(), e));//"Unexpected error" "An unexpected error occurred creating the new transformation" return false; } return true; } public String toString() { return APP_NAME; } /** * This is the main procedure for Spoon. * * @param a Arguments are available in the "Get System Info" step. */ public static void main(String[] a) throws KettleException { EnvUtil.environmentInit(); ArrayList args = new ArrayList(); for (int i = 0; i < a.length; i++) args.add(a[i]); Display display = new Display(); Splash splash = new Splash(display); StringBuffer optionRepname, optionUsername, optionPassword, optionJobname, optionTransname, optionFilename, optionDirname, optionLogfile, optionLoglevel; CommandLineOption options[] = new CommandLineOption[] { new CommandLineOption("rep", "Repository name", optionRepname = new StringBuffer()), new CommandLineOption("user", "Repository username", optionUsername = new StringBuffer()), new CommandLineOption("pass", "Repository password", optionPassword = new StringBuffer()), new CommandLineOption("job", "The name of the job to launch", optionJobname = new StringBuffer()), new CommandLineOption("trans", "The name of the transformation to launch", optionTransname = new StringBuffer()), new CommandLineOption("dir", "The directory (don't forget the leading /)", optionDirname = new StringBuffer()), new CommandLineOption("file", "The filename (Transformation in XML) to launch", optionFilename = new StringBuffer()), new CommandLineOption("level", "The logging level (Basic, Detailed, Debug, Rowlevel, Error, Nothing)", optionLoglevel = new StringBuffer()), new CommandLineOption("logfile", "The logging file to write to", optionLogfile = new StringBuffer()), new CommandLineOption("log", "The logging file to write to (deprecated)", optionLogfile = new StringBuffer(), false, true), }; // Parse the options... CommandLineOption.parseArguments(args, options); String kettleRepname = Const.getEnvironmentVariable("KETTLE_REPOSITORY", null); String kettleUsername = Const.getEnvironmentVariable("KETTLE_USER", null); String kettlePassword = Const.getEnvironmentVariable("KETTLE_PASSWORD", null); if (!Const.isEmpty(kettleRepname)) optionRepname = new StringBuffer(kettleRepname); if (!Const.isEmpty(kettleUsername)) optionUsername = new StringBuffer(kettleUsername); if (!Const.isEmpty(kettlePassword)) optionPassword = new StringBuffer(kettlePassword); // Before anything else, check the runtime version!!! String version = Const.JAVA_VERSION; if ("1.4".compareToIgnoreCase(version) > 0) { System.out.println("The System is running on Java version " + version); System.out.println("Unfortunately, it needs version 1.4 or higher to run."); return; } // Set default Locale: Locale.setDefault(Const.DEFAULT_LOCALE); LogWriter log; LogWriter.setConsoleAppenderDebug(); if (Const.isEmpty(optionLogfile)) { log = LogWriter.getInstance(Const.SPOON_LOG_FILE, false, LogWriter.LOG_LEVEL_BASIC); } else { log = LogWriter.getInstance(optionLogfile.toString(), true, LogWriter.LOG_LEVEL_BASIC); } if (log.getRealFilename() != null) log.logBasic(APP_NAME, Messages.getString("Spoon.Log.LoggingToFile") + log.getRealFilename());//"Logging goes to " if (!Const.isEmpty(optionLoglevel)) { log.setLogLevel(optionLoglevel.toString()); log.logBasic(APP_NAME, Messages.getString("Spoon.Log.LoggingAtLevel") + log.getLogLevelDesc());//"Logging is at level : " } /* Load the plugins etc.*/ StepLoader stloader = StepLoader.getInstance(); if (!stloader.read()) { log.logError(APP_NAME, Messages.getString("Spoon.Log.ErrorLoadingAndHaltSystem"));//Error loading steps & plugins... halting Spoon! return; } /* Load the plugins etc. we need to load jobentry*/ JobEntryLoader jeloader = JobEntryLoader.getInstance(); if (!jeloader.read()) { log.logError("Spoon", "Error loading job entries & plugins... halting Kitchen!"); return; } final Spoon spoon = new Spoon(log, display, null); staticSpoon = spoon; spoon.setDestroy(true); spoon.setArguments((String[]) args.toArray(new String[args.size()])); log.logBasic(APP_NAME, Messages.getString("Spoon.Log.MainWindowCreated"));//Main window is created. RepositoryMeta repositoryMeta = null; UserInfo userinfo = null; if (Const.isEmpty(optionRepname) && Const.isEmpty(optionFilename) && spoon.props.showRepositoriesDialogAtStartup()) { log.logBasic(APP_NAME, Messages.getString("Spoon.Log.AskingForRepository"));//"Asking for repository" int perms[] = new int[] { PermissionMeta.TYPE_PERMISSION_TRANSFORMATION, PermissionMeta.TYPE_PERMISSION_JOB }; splash.hide(); RepositoriesDialog rd = new RepositoriesDialog(spoon.disp, perms, Messages.getString("Spoon.Application.Name"));//"Spoon" if (rd.open()) { repositoryMeta = rd.getRepository(); userinfo = rd.getUser(); if (!userinfo.useTransformations()) { MessageBox mb = new MessageBox(spoon.shell, SWT.OK | SWT.ICON_ERROR); mb.setMessage(Messages.getString("Spoon.Dialog.RepositoryUserCannotWork.Message"));//"Sorry, this repository user can't work with transformations from the repository." mb.setText(Messages.getString("Spoon.Dialog.RepositoryUserCannotWork.Title"));//"Error!" mb.open(); userinfo = null; repositoryMeta = null; } } else { // Exit point: user pressed CANCEL! if (rd.isCancelled()) { splash.dispose(); spoon.quitFile(); return; } } } try { // Read kettle transformation specified on command-line? if (!Const.isEmpty(optionRepname) || !Const.isEmpty(optionFilename)) { if (!Const.isEmpty(optionRepname)) { RepositoriesMeta repsinfo = new RepositoriesMeta(log); if (repsinfo.readData()) { repositoryMeta = repsinfo.findRepository(optionRepname.toString()); if (repositoryMeta != null) { // Define and connect to the repository... spoon.rep = new Repository(log, repositoryMeta, userinfo); if (spoon.rep.connect(Messages.getString("Spoon.Application.Name")))//"Spoon" { if (Const.isEmpty(optionDirname)) optionDirname = new StringBuffer(RepositoryDirectory.DIRECTORY_SEPARATOR); // Check username, password spoon.rep.userinfo = new UserInfo(spoon.rep, optionUsername.toString(), optionPassword.toString()); if (spoon.rep.userinfo.getID() > 0) { // Options /file, /job and /trans are mutually exclusive int t = (Const.isEmpty(optionFilename) ? 0 : 1) + (Const.isEmpty(optionJobname) ? 0 : 1) + (Const.isEmpty(optionTransname) ? 0 : 1); if (t > 1) { log.logError(APP_NAME, Messages.getString("Spoon.Log.MutuallyExcusive")); // "More then one mutually exclusive options /file, /job and /trans are specified." } else if (t == 1) { if (!Const.isEmpty(optionFilename)) { spoon.openFile(optionFilename.toString(), false); } else { // OK, if we have a specified job or transformation, try to load it... // If not, keep the repository logged in. RepositoryDirectory repdir = spoon.rep.getDirectoryTree() .findDirectory(optionDirname.toString()); if (repdir == null) { log.logError(APP_NAME, Messages.getString( "Spoon.Log.UnableFindDirectory", optionDirname.toString())); //"Can't find directory ["+dirname+"] in the repository." } else { if (!Const.isEmpty(optionTransname)) { TransMeta transMeta = new TransMeta(spoon.rep, optionTransname.toString(), repdir); transMeta.setFilename(optionRepname.toString()); transMeta.clearChanged(); spoon.addSpoonGraph(transMeta); } else { // Try to load a specified job if any JobMeta jobMeta = new JobMeta(log, spoon.rep, optionJobname.toString(), repdir); jobMeta.setFilename(optionRepname.toString()); jobMeta.clearChanged(); spoon.addChefGraph(jobMeta); } } } } } else { log.logError(APP_NAME, Messages.getString("Spoon.Log.UnableVerifyUser"));//"Can't verify username and password." spoon.rep.disconnect(); spoon.rep = null; } } else { log.logError(APP_NAME, Messages.getString("Spoon.Log.UnableConnectToRepository"));//"Can't connect to the repository." } } else { log.logError(APP_NAME, Messages.getString("Spoon.Log.NoRepositoryRrovided"));//"No repository provided, can't load transformation." } } else { log.logError(APP_NAME, Messages.getString("Spoon.Log.NoRepositoriesDefined"));//"No repositories defined on this system." } } else if (!Const.isEmpty(optionFilename)) { spoon.openFile(optionFilename.toString(), false); } } else // Normal operations, nothing on the commandline... { // Can we connect to the repository? if (repositoryMeta != null && userinfo != null) { spoon.rep = new Repository(log, repositoryMeta, userinfo); if (!spoon.rep.connect(Messages.getString("Spoon.Application.Name"))) //"Spoon" { spoon.rep = null; } } if (spoon.props.openLastFile()) { log.logDetailed(APP_NAME, Messages.getString("Spoon.Log.TryingOpenLastUsedFile"));//"Trying to open the last file used." List lastUsedFiles = spoon.props.getLastUsedFiles(); if (lastUsedFiles.size() > 0) { LastUsedFile lastUsedFile = (LastUsedFile) lastUsedFiles.get(0); spoon.loadLastUsedFile(lastUsedFile, repositoryMeta); } } } } catch (KettleException ke) { log.logError(APP_NAME, Messages.getString("Spoon.Log.ErrorOccurred") + Const.CR + ke.getMessage());//"An error occurred: " spoon.rep = null; // ke.printStackTrace(); } spoon.open(); splash.dispose(); try { while (!spoon.isDisposed()) { if (!spoon.readAndDispatch()) spoon.sleep(); } } catch (Throwable e) { log.logError(APP_NAME, Messages.getString("Spoon.Log.UnexpectedErrorOccurred") + Const.CR + e.getMessage());//"An unexpected error occurred in Spoon: probable cause: please close all windows before stopping Spoon! " e.printStackTrace(); } spoon.dispose(); log.logBasic(APP_NAME, APP_NAME + " " + Messages.getString("Spoon.Log.AppHasEnded"));//" has ended." // Close the logfile log.close(); // Kill all remaining things in this VM! System.exit(0); } private void loadLastUsedFile(LastUsedFile lastUsedFile, RepositoryMeta repositoryMeta) throws KettleException { boolean useRepository = repositoryMeta != null; // Perhaps we need to connect to the repository? if (lastUsedFile.isSourceRepository()) { if (!Const.isEmpty(lastUsedFile.getRepositoryName())) { if (useRepository && !lastUsedFile.getRepositoryName().equalsIgnoreCase(repositoryMeta.getName())) { // We just asked... useRepository = false; } } } if (useRepository && lastUsedFile.isSourceRepository()) { if (rep != null) // load from this repository... { if (rep.getName().equalsIgnoreCase(lastUsedFile.getRepositoryName())) { RepositoryDirectory repdir = rep.getDirectoryTree().findDirectory(lastUsedFile.getDirectory()); if (repdir != null) { // Are we loading a transformation or a job? if (lastUsedFile.isTransformation()) { log.logDetailed(APP_NAME, Messages.getString("Spoon.Log.AutoLoadingTransformation", lastUsedFile.getFilename(), lastUsedFile.getDirectory()));//"Auto loading transformation ["+lastfiles[0]+"] from repository directory ["+lastdirs[0]+"]" TransLoadProgressDialog tlpd = new TransLoadProgressDialog(shell, rep, lastUsedFile.getFilename(), repdir); TransMeta transMeta = tlpd.open(); // = new TransInfo(log, win.rep, lastfiles[0], repdir); if (transMeta != null) { props.addLastFile(LastUsedFile.FILE_TYPE_TRANSFORMATION, lastUsedFile.getFilename(), repdir.getPath(), true, rep.getName()); transMeta.setFilename(lastUsedFile.getFilename()); transMeta.clearChanged(); addSpoonGraph(transMeta); refreshTree(); } } else if (lastUsedFile.isJob()) { JobLoadProgressDialog progressDialog = new JobLoadProgressDialog(shell, rep, lastUsedFile.getFilename(), repdir); JobMeta jobMeta = progressDialog.open(); props.addLastFile(LastUsedFile.FILE_TYPE_JOB, lastUsedFile.getFilename(), repdir.getPath(), true, rep.getName()); jobMeta.clearChanged(); addChefGraph(jobMeta); } refreshTree(); } } } } if (!lastUsedFile.isSourceRepository() && !Const.isEmpty(lastUsedFile.getFilename())) { if (lastUsedFile.isTransformation()) { TransMeta transMeta = new TransMeta(lastUsedFile.getFilename()); transMeta.setFilename(lastUsedFile.getFilename()); transMeta.clearChanged(); props.addLastFile(LastUsedFile.FILE_TYPE_TRANSFORMATION, lastUsedFile.getFilename(), null, false, null); addSpoonGraph(transMeta); } if (lastUsedFile.isJob()) { JobMeta jobMeta = new JobMeta(log, lastUsedFile.getFilename(), rep); jobMeta.setFilename(lastUsedFile.getFilename()); jobMeta.clearChanged(); props.addLastFile(LastUsedFile.FILE_TYPE_JOB, lastUsedFile.getFilename(), null, false, null); addChefGraph(jobMeta); } refreshTree(); } } /** * Create a new SelectValues step in between this step and the previous. * If the previous fields are not there, no mapping can be made, same with the required fields. * @param stepMeta The target step to map against. */ public void generateMapping(TransMeta transMeta, StepMeta stepMeta) { try { if (stepMeta != null) { StepMetaInterface smi = stepMeta.getStepMetaInterface(); Row targetFields = smi.getRequiredFields(); Row sourceFields = transMeta.getPrevStepFields(stepMeta); // Build the mapping: let the user decide!! String[] source = sourceFields.getFieldNames(); for (int i = 0; i < source.length; i++) { Value v = sourceFields.getValue(i); source[i] += EnterMappingDialog.STRING_ORIGIN_SEPARATOR + v.getOrigin() + ")"; } String[] target = targetFields.getFieldNames(); EnterMappingDialog dialog = new EnterMappingDialog(shell, source, target); ArrayList mappings = dialog.open(); if (mappings != null) { // OK, so we now know which field maps where. // This allows us to generate the mapping using a SelectValues Step... SelectValuesMeta svm = new SelectValuesMeta(); svm.allocate(mappings.size(), 0, 0); for (int i = 0; i < mappings.size(); i++) { SourceToTargetMapping mapping = (SourceToTargetMapping) mappings.get(i); svm.getSelectName()[i] = sourceFields.getValue(mapping.getSourcePosition()).getName(); svm.getSelectRename()[i] = target[mapping.getTargetPosition()]; svm.getSelectLength()[i] = -1; svm.getSelectPrecision()[i] = -1; } // Now that we have the meta-data, create a new step info object String stepName = stepMeta.getName() + " Mapping"; stepName = transMeta.getAlternativeStepname(stepName); // if it's already there, rename it. StepMeta newStep = new StepMeta("SelectValues", stepName, svm); newStep.setLocation(stepMeta.getLocation().x + 20, stepMeta.getLocation().y + 20); newStep.setDraw(true); transMeta.addStep(newStep); addUndoNew(transMeta, new StepMeta[] { newStep }, new int[] { transMeta.indexOfStep(newStep) }); // Redraw stuff... refreshTree(); refreshGraph(); } } else { System.out.println("No target to do mapping against!"); } } catch (KettleException e) { new ErrorDialog(shell, "Error creating mapping", "There was an error when Kettle tried to generate a mapping against the target step", e); } } public void editPartitioning(TransMeta transMeta, StepMeta stepMeta) { StepPartitioningMeta stepPartitioningMeta = stepMeta.getStepPartitioningMeta(); if (stepPartitioningMeta == null) stepPartitioningMeta = new StepPartitioningMeta(); String[] options = StepPartitioningMeta.methodDescriptions; EnterSelectionDialog dialog = new EnterSelectionDialog(shell, options, "Partioning method", "Select the partitioning method"); String methodDescription = dialog.open(stepPartitioningMeta.getMethod()); if (methodDescription != null) { int method = StepPartitioningMeta.getMethod(methodDescription); stepPartitioningMeta.setMethod(method); switch (method) { case StepPartitioningMeta.PARTITIONING_METHOD_NONE: break; case StepPartitioningMeta.PARTITIONING_METHOD_MOD: // ask for a fieldname EnterStringDialog stringDialog = new EnterStringDialog(shell, Const.NVL(stepPartitioningMeta.getFieldName(), ""), "Fieldname", "Enter a field name to partition on"); String fieldName = stringDialog.open(); stepPartitioningMeta.setFieldName(fieldName); // Ask for a Partitioning Schema String schemaNames[] = transMeta.getPartitionSchemasNames(); if (schemaNames.length == 0) { MessageBox box = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK); box.setText("Create a partition schema"); box.setMessage( "You first need to create one or more partition schemas in the transformation settings dialog before you can select one!"); box.open(); } else { // Set the partitioning schema too. PartitionSchema partitionSchema = stepPartitioningMeta.getPartitionSchema(); int idx = -1; if (partitionSchema != null) { idx = Const.indexOfString(partitionSchema.getName(), schemaNames); } EnterSelectionDialog askSchema = new EnterSelectionDialog(shell, schemaNames, "Select a partition schema", "Select the partition schema to use:"); String schemaName = askSchema.open(idx); if (schemaName != null) { idx = Const.indexOfString(schemaName, schemaNames); stepPartitioningMeta .setPartitionSchema((PartitionSchema) transMeta.getPartitionSchemas().get(idx)); } } break; } refreshGraph(); } } /** * Select a clustering schema for this step. * * @param stepMeta The step to set the clustering schema for. */ public void editClustering(TransMeta transMeta, StepMeta stepMeta) { int idx = -1; if (stepMeta.getClusterSchema() != null) { idx = transMeta.getClusterSchemas().indexOf(stepMeta.getClusterSchema()); } String[] clusterSchemaNames = transMeta.getClusterSchemaNames(); EnterSelectionDialog dialog = new EnterSelectionDialog(shell, clusterSchemaNames, "Cluster schema", "Select the cluster schema to use (cancel=clear)"); String schemaName = dialog.open(idx); if (schemaName == null) { stepMeta.setClusterSchema(null); } else { ClusterSchema clusterSchema = transMeta.findClusterSchema(schemaName); stepMeta.setClusterSchema(clusterSchema); } refreshTree(); refreshGraph(); } public void createKettleArchive(TransMeta transMeta) { if (transMeta == null) return; JarfileGenerator.generateJarFile(transMeta); } /** * This creates a new database partitioning schema, edits it and adds it to the transformation metadata * */ public void newDatabasePartitioningSchema(TransMeta transMeta) { PartitionSchema partitionSchema = new PartitionSchema(); PartitionSchemaDialog dialog = new PartitionSchemaDialog(shell, partitionSchema, transMeta.getDatabases()); if (dialog.open()) { transMeta.getPartitionSchemas().add(partitionSchema); refreshTree(); } } private void editPartitionSchema(HasDatabasesInterface hasDatabasesInterface, PartitionSchema partitionSchema) { PartitionSchemaDialog dialog = new PartitionSchemaDialog(shell, partitionSchema, hasDatabasesInterface.getDatabases()); if (dialog.open()) { refreshTree(); } } private void delPartitionSchema(TransMeta transMeta, PartitionSchema partitionSchema) { try { if (rep != null && partitionSchema.getId() > 0) { // remove the partition schema from the repository too... rep.delPartitionSchema(partitionSchema.getId()); } int idx = transMeta.getPartitionSchemas().indexOf(partitionSchema); transMeta.getPartitionSchemas().remove(idx); refreshTree(); } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorDeletingClusterSchema.Title"), //$NON-NLS-1$ Messages.getString("Spoon.Dialog.ErrorDeletingClusterSchema.Message"), e); //$NON-NLS-1$ } } /** * This creates a new clustering schema, edits it and adds it to the transformation metadata * */ public void newClusteringSchema(TransMeta transMeta) { ClusterSchema clusterSchema = new ClusterSchema(); ClusterSchemaDialog dialog = new ClusterSchemaDialog(shell, clusterSchema, transMeta.getSlaveServers()); if (dialog.open()) { transMeta.getClusterSchemas().add(clusterSchema); refreshTree(); } } private void editClusterSchema(TransMeta transMeta, ClusterSchema clusterSchema) { ClusterSchemaDialog dialog = new ClusterSchemaDialog(shell, clusterSchema, transMeta.getSlaveServers()); if (dialog.open()) { refreshTree(); } } private void delClusterSchema(TransMeta transMeta, ClusterSchema clusterSchema) { try { if (rep != null && clusterSchema.getId() > 0) { // remove the partition schema from the repository too... rep.delClusterSchema(clusterSchema.getId()); } int idx = transMeta.getClusterSchemas().indexOf(clusterSchema); transMeta.getClusterSchemas().remove(idx); refreshTree(); } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorDeletingPartitionSchema.Title"), //$NON-NLS-1$ Messages.getString("Spoon.Dialog.ErrorDeletingPartitionSchema.Message"), e); //$NON-NLS-1$ } } /** * This creates a slave server, edits it and adds it to the transformation metadata * */ public void newSlaveServer(TransMeta transMeta) { SlaveServer slaveServer = new SlaveServer(); SlaveServerDialog dialog = new SlaveServerDialog(shell, slaveServer); if (dialog.open()) { transMeta.getSlaveServers().add(slaveServer); refreshTree(); } } public void delSlaveServer(TransMeta transMeta, SlaveServer slaveServer) { try { if (rep != null && slaveServer.getId() > 0) { // remove the slave server from the repository too... rep.delSlave(slaveServer.getId()); } int idx = transMeta.getSlaveServers().indexOf(slaveServer); transMeta.getSlaveServers().remove(idx); refreshTree(); } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.Dialog.ErrorDeletingSlave.Title"), //$NON-NLS-1$ Messages.getString("Spoon.Dialog.ErrorDeletingSlave.Message"), e); //$NON-NLS-1$ } } /** * Sends transformation to slave server * @param executionConfiguration */ public void sendXMLToSlaveServer(TransMeta transMeta, TransExecutionConfiguration executionConfiguration) { SlaveServer slaveServer = executionConfiguration.getRemoteServer(); try { if (slaveServer == null) throw new KettleException("No slave server specified"); if (Const.isEmpty(transMeta.getName())) throw new KettleException( "The transformation needs a name to uniquely identify it by on the remote server."); String xml = new TransConfiguration(transMeta, executionConfiguration).getXML(); String reply = slaveServer.sendXML(xml, AddTransServlet.CONTEXT_PATH + "/?xml=Y"); WebResult webResult = WebResult.fromXMLString(reply); if (!webResult.getResult().equalsIgnoreCase(WebResult.STRING_OK)) { throw new KettleException("There was an error posting the transformation on the remote server: " + Const.CR + webResult.getMessage()); } reply = slaveServer.getContentFromServer( PrepareExecutionTransServlet.CONTEXT_PATH + "/?name=" + transMeta.getName() + "&xml=Y"); webResult = WebResult.fromXMLString(reply); if (!webResult.getResult().equalsIgnoreCase(WebResult.STRING_OK)) { throw new KettleException( "There was an error preparing the transformation for excution on the remote server: " + Const.CR + webResult.getMessage()); } reply = slaveServer.getContentFromServer( StartExecutionTransServlet.CONTEXT_PATH + "/?name=" + transMeta.getName() + "&xml=Y"); webResult = WebResult.fromXMLString(reply); if (!webResult.getResult().equalsIgnoreCase(WebResult.STRING_OK)) { throw new KettleException("There was an error starting the transformation on the remote server: " + Const.CR + webResult.getMessage()); } } catch (Exception e) { new ErrorDialog(shell, "Error", "Error sending transformation to server", e); } } private void splitTrans(TransMeta transMeta, boolean show, boolean post, boolean prepare, boolean start) { try { if (Const.isEmpty(transMeta.getName())) throw new KettleException( "The transformation needs a name to uniquely identify it by on the remote server."); TransSplitter transSplitter = new TransSplitter(transMeta); transSplitter.splitOriginalTransformation(); // Send the transformations to the servers... // // First the master... // TransMeta master = transSplitter.getMaster(); SlaveServer masterServer = null; List masterSteps = master.getTransHopSteps(false); if (masterSteps.size() > 0) // If there is something that needs to be done on the master... { masterServer = transSplitter.getMasterServer(); if (show) addSpoonGraph(master); if (post) { String masterReply = masterServer.sendXML( new TransConfiguration(master, executionConfiguration).getXML(), AddTransServlet.CONTEXT_PATH + "/?xml=Y"); WebResult webResult = WebResult.fromXMLString(masterReply); if (!webResult.getResult().equalsIgnoreCase(WebResult.STRING_OK)) { throw new KettleException( "An error occurred sending the master transformation: " + webResult.getMessage()); } } } // Then the slaves... // SlaveServer slaves[] = transSplitter.getSlaveTargets(); for (int i = 0; i < slaves.length; i++) { TransMeta slaveTrans = (TransMeta) transSplitter.getSlaveTransMap().get(slaves[i]); if (show) addSpoonGraph(slaveTrans); if (post) { String slaveReply = slaves[i].sendXML( new TransConfiguration(slaveTrans, executionConfiguration).getXML(), AddTransServlet.CONTEXT_PATH + "/?xml=Y"); WebResult webResult = WebResult.fromXMLString(slaveReply); if (!webResult.getResult().equalsIgnoreCase(WebResult.STRING_OK)) { throw new KettleException( "An error occurred sending a slave transformation: " + webResult.getMessage()); } } } if (post) { if (prepare) { // Prepare the master... if (masterSteps.size() > 0) // If there is something that needs to be done on the master... { String masterReply = masterServer .getContentFromServer(PrepareExecutionTransServlet.CONTEXT_PATH + "/?name=" + master.getName() + "&xml=Y"); WebResult webResult = WebResult.fromXMLString(masterReply); if (!webResult.getResult().equalsIgnoreCase(WebResult.STRING_OK)) { throw new KettleException( "An error occurred while preparing the execution of the master transformation: " + webResult.getMessage()); } } // Prepare the slaves for (int i = 0; i < slaves.length; i++) { TransMeta slaveTrans = (TransMeta) transSplitter.getSlaveTransMap().get(slaves[i]); String slaveReply = slaves[i].getContentFromServer(PrepareExecutionTransServlet.CONTEXT_PATH + "/?name=" + slaveTrans.getName() + "&xml=Y"); WebResult webResult = WebResult.fromXMLString(slaveReply); if (!webResult.getResult().equalsIgnoreCase(WebResult.STRING_OK)) { throw new KettleException( "An error occurred while preparing the execution of a slave transformation: " + webResult.getMessage()); } } } if (start) { // Start the master... if (masterSteps.size() > 0) // If there is something that needs to be done on the master... { String masterReply = masterServer.getContentFromServer( StartExecutionTransServlet.CONTEXT_PATH + "/?name=" + master.getName() + "&xml=Y"); WebResult webResult = WebResult.fromXMLString(masterReply); if (!webResult.getResult().equalsIgnoreCase(WebResult.STRING_OK)) { throw new KettleException( "An error occurred while starting the execution of the master transformation: " + webResult.getMessage()); } } // Start the slaves for (int i = 0; i < slaves.length; i++) { TransMeta slaveTrans = (TransMeta) transSplitter.getSlaveTransMap().get(slaves[i]); String slaveReply = slaves[i].getContentFromServer(StartExecutionTransServlet.CONTEXT_PATH + "/?name=" + slaveTrans.getName() + "&xml=Y"); WebResult webResult = WebResult.fromXMLString(slaveReply); if (!webResult.getResult().equalsIgnoreCase(WebResult.STRING_OK)) { throw new KettleException( "An error occurred while starting the execution of a slave transformation: " + webResult.getMessage()); } } } // Now add monitors for the master and all the slave servers addSpoonSlave(masterServer); for (int i = 0; i < slaves.length; i++) { addSpoonSlave(slaves[i]); } } } catch (Exception e) { new ErrorDialog(shell, "Split transformation", "There was an error during transformation split", e); } } public void executeFile(boolean local, boolean remote, boolean cluster, boolean preview, Date replayDate) { TransMeta transMeta = getActiveTransformation(); if (transMeta != null) executeTransformation(transMeta, local, remote, cluster, preview, replayDate); JobMeta jobMeta = getActiveJob(); if (jobMeta != null) executeJob(jobMeta, local, remote, cluster, preview, replayDate); } public void executeTransformation(TransMeta transMeta, boolean local, boolean remote, boolean cluster, boolean preview, Date replayDate) { if (transMeta == null) return; executionConfiguration.setExecutingLocally(local); executionConfiguration.setExecutingRemotely(remote); executionConfiguration.setExecutingClustered(cluster); executionConfiguration.getUsedVariables(transMeta); executionConfiguration.getUsedArguments(transMeta, arguments); executionConfiguration.setReplayDate(replayDate); executionConfiguration.setLocalPreviewing(preview); executionConfiguration.setLogLevel(log.getLogLevel()); // executionConfiguration.setSafeModeEnabled( spoonLog!=null && spoonLog.isSafeModeChecked() ); TransExecutionConfigurationDialog dialog = new TransExecutionConfigurationDialog(shell, executionConfiguration, transMeta); if (dialog.open()) { addSpoonLog(transMeta, !executionConfiguration.isLocalPreviewing()); SpoonLog spoonLog = getActiveSpoonLog(); if (executionConfiguration.isExecutingLocally()) { if (executionConfiguration.isLocalPreviewing()) { spoonLog.preview(executionConfiguration); } else { spoonLog.start(executionConfiguration); } } else if (executionConfiguration.isExecutingRemotely()) { if (executionConfiguration.getRemoteServer() != null) { sendXMLToSlaveServer(transMeta, executionConfiguration); addSpoonSlave(executionConfiguration.getRemoteServer()); } else { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION); mb.setMessage(Messages.getString("Spoon.Dialog.NoRemoteServerSpecified.Message")); mb.setText(Messages.getString("Spoon.Dialog.NoRemoteServerSpecified.Title")); mb.open(); } } else if (executionConfiguration.isExecutingClustered()) { splitTrans(transMeta, executionConfiguration.isClusterShowingTransformation(), executionConfiguration.isClusterPosting(), executionConfiguration.isClusterPreparing(), executionConfiguration.isClusterStarting()); } } } public void executeJob(JobMeta jobMeta, boolean local, boolean remote, boolean cluster, boolean preview, Date replayDate) { addChefLog(jobMeta); ChefLog chefLog = getActiveJobLog(); chefLog.startJob(replayDate); } public CTabItem findCTabItem(String tabItemText, int objectType) { for (Iterator iter = tabMap.values().iterator(); iter.hasNext();) { TabMapEntry entry = (TabMapEntry) iter.next(); if (entry.getTabItem().isDisposed()) continue; if (objectType == entry.getObjectType() && entry.getTabItem().getText().equalsIgnoreCase(tabItemText)) { return entry.getTabItem(); } } return null; } private void addSpoonSlave(SlaveServer slaveServer) { // See if there is a SpoonSlave for this slaveServer... String tabName = makeSlaveTabName(slaveServer); CTabItem tabItem = findCTabItem(tabName, TabMapEntry.OBJECT_TYPE_SLAVE_SERVER); if (tabItem == null) { SpoonSlave spoonSlave = new SpoonSlave(tabfolder, SWT.NONE, this, slaveServer); tabItem = new CTabItem(tabfolder, SWT.CLOSE); tabItem.setText(tabName); tabItem.setToolTipText( "Status of slave server : " + slaveServer.getName() + " : " + slaveServer.getServerAndPort()); tabItem.setControl(spoonSlave); tabMap.put(tabName, new TabMapEntry(tabItem, tabName, spoonSlave, TabMapEntry.OBJECT_TYPE_SLAVE_SERVER)); } int idx = tabfolder.indexOf(tabItem); tabfolder.setSelection(idx); } public void addSpoonGraph(TransMeta transMeta) { String key = addTransformation(transMeta); if (key != null) { // See if there already is a tab for this graph // If no, add it // If yes, select that tab // String tabName = makeTransGraphTabName(transMeta); CTabItem tabItem = findCTabItem(tabName, TabMapEntry.OBJECT_TYPE_TRANSFORMATION_GRAPH); if (tabItem == null) { SpoonGraph spoonGraph = new SpoonGraph(tabfolder, this, transMeta); tabItem = new CTabItem(tabfolder, SWT.CLOSE); tabItem.setText(tabName); tabItem.setToolTipText( Messages.getString("Spoon.TabTrans.Tooltip", makeTransGraphTabName(transMeta))); tabItem.setImage(GUIResource.getInstance().getImageSpoonGraph()); tabItem.setControl(spoonGraph); tabMap.put(tabName, new TabMapEntry(tabItem, tabName, spoonGraph, TabMapEntry.OBJECT_TYPE_TRANSFORMATION_GRAPH)); } int idx = tabfolder.indexOf(tabItem); // OK, also see if we need to open a new history window. if (transMeta.getLogConnection() != null && !Const.isEmpty(transMeta.getLogTable())) { addSpoonHistory(transMeta, false); } // keep the focus on the graph tabfolder.setSelection(idx); setUndoMenu(transMeta); enableMenus(); } } public void addChefGraph(JobMeta jobMeta) { String key = addJob(jobMeta); if (key != null) { // See if there already is a tab for this graph // If no, add it // If yes, select that tab // String tabName = makeJobGraphTabName(jobMeta); CTabItem tabItem = findCTabItem(tabName, TabMapEntry.OBJECT_TYPE_JOB_GRAPH); if (tabItem == null) { ChefGraph chefGraph = new ChefGraph(tabfolder, this, jobMeta); tabItem = new CTabItem(tabfolder, SWT.CLOSE); tabItem.setText(tabName); tabItem.setToolTipText(Messages.getString("Spoon.TabJob.Tooltip", makeJobGraphTabName(jobMeta))); tabItem.setImage(GUIResource.getInstance().getImageChefGraph()); tabItem.setControl(chefGraph); tabMap.put(tabName, new TabMapEntry(tabItem, tabName, chefGraph, TabMapEntry.OBJECT_TYPE_JOB_GRAPH)); } int idx = tabfolder.indexOf(tabItem); // OK, also see if we need to open a new history window. if (jobMeta.getLogConnection() != null && !Const.isEmpty(jobMeta.getLogTable())) { addChefHistory(jobMeta, false); } // keep the focus on the graph tabfolder.setSelection(idx); setUndoMenu(jobMeta); enableMenus(); } } public boolean addSpoonBrowser(String name, String urlString) { try { // OK, now we have the HTML, create a new browset tab. // See if there already is a tab for this browser // If no, add it // If yes, select that tab // CTabItem tabItem = findCTabItem(name, TabMapEntry.OBJECT_TYPE_BROWSER); if (tabItem == null) { SpoonBrowser browser = new SpoonBrowser(tabfolder, this, urlString); tabItem = new CTabItem(tabfolder, SWT.CLOSE); tabItem.setText(name); tabItem.setControl(browser.getComposite()); tabMap.put(name, new TabMapEntry(tabItem, name, browser, TabMapEntry.OBJECT_TYPE_BROWSER)); } int idx = tabfolder.indexOf(tabItem); // keep the focus on the graph tabfolder.setSelection(idx); return true; } catch (Throwable e) { return false; } } public String makeLogTabName(TransMeta transMeta) { return Messages.getString("Spoon.Title.LogTransView", makeTransGraphTabName(transMeta)); } public String makeJobLogTabName(JobMeta jobMeta) { return Messages.getString("Spoon.Title.LogJobView", makeJobGraphTabName(jobMeta)); } public String makeTransGraphTabName(TransMeta transMeta) { if (Const.isEmpty(transMeta.getName()) && Const.isEmpty(transMeta.getFilename())) return STRING_TRANS_NO_NAME; if (Const.isEmpty(transMeta.getName()) || isDefaultTransformationName(transMeta.getName())) { transMeta.nameFromFilename(); } return transMeta.getName(); } public String makeJobGraphTabName(JobMeta jobMeta) { if (Const.isEmpty(jobMeta.getName()) && Const.isEmpty(jobMeta.getFilename())) return STRING_JOB_NO_NAME; if (Const.isEmpty(jobMeta.getName()) || isDefaultJobnName(jobMeta.getName())) { jobMeta.nameFromFilename(); } return jobMeta.getName(); } public String makeHistoryTabName(TransMeta transMeta) { return Messages.getString("Spoon.Title.LogTransHistoryView", makeTransGraphTabName(transMeta)); } public String makeJobHistoryTabName(JobMeta jobMeta) { return Messages.getString("Spoon.Title.LogJobHistoryView", makeJobGraphTabName(jobMeta)); } public String makeSlaveTabName(SlaveServer slaveServer) { return "Slave server: " + slaveServer.getName(); } public void addSpoonLog(TransMeta transMeta) { addSpoonLog(transMeta, true); } public void addSpoonLog(TransMeta transMeta, boolean setActive) { // See if there already is a tab for this log // If no, add it // If yes, select that tab // if setActive is true // String tabName = makeLogTabName(transMeta); CTabItem tabItem = findCTabItem(tabName, TabMapEntry.OBJECT_TYPE_TRANSFORMATION_LOG); if (tabItem == null) { SpoonLog spoonLog = new SpoonLog(tabfolder, this, transMeta); tabItem = new CTabItem(tabfolder, SWT.CLOSE); tabItem.setText(tabName); tabItem.setToolTipText( Messages.getString("Spoon.Title.ExecLogTransView.Tooltip", makeTransGraphTabName(transMeta))); tabItem.setControl(spoonLog); // If there is an associated history window, we want to keep that one up-to-date as well. // SpoonHistory spoonHistory = findSpoonHistoryOfTransformation(transMeta); CTabItem historyItem = findCTabItem(makeHistoryTabName(transMeta), TabMapEntry.OBJECT_TYPE_TRANSFORMATION_HISTORY); if (spoonHistory != null && historyItem != null) { SpoonHistoryRefresher spoonHistoryRefresher = new SpoonHistoryRefresher(historyItem, spoonHistory); tabfolder.addSelectionListener(spoonHistoryRefresher); spoonLog.setSpoonHistoryRefresher(spoonHistoryRefresher); } tabMap.put(tabName, new TabMapEntry(tabItem, tabName, spoonLog, TabMapEntry.OBJECT_TYPE_TRANSFORMATION_LOG)); } if (setActive) { int idx = tabfolder.indexOf(tabItem); tabfolder.setSelection(idx); } } public void addChefLog(JobMeta jobMeta) { // See if there already is a tab for this log // If no, add it // If yes, select that tab // String tabName = makeJobLogTabName(jobMeta); CTabItem tabItem = findCTabItem(tabName, TabMapEntry.OBJECT_TYPE_JOB_LOG); if (tabItem == null) { ChefLog chefLog = new ChefLog(tabfolder, this, jobMeta); tabItem = new CTabItem(tabfolder, SWT.CLOSE); tabItem.setText(tabName); tabItem.setToolTipText( Messages.getString("Spoon.Title.ExecLogJobView.Tooltip", makeJobGraphTabName(jobMeta))); tabItem.setControl(chefLog); // If there is an associated history window, we want to keep that one up-to-date as well. // ChefHistory chefHistory = findChefHistoryOfJob(jobMeta); CTabItem historyItem = findCTabItem(makeJobHistoryTabName(jobMeta), TabMapEntry.OBJECT_TYPE_JOB_HISTORY); if (chefHistory != null && historyItem != null) { ChefHistoryRefresher chefHistoryRefresher = new ChefHistoryRefresher(historyItem, chefHistory); tabfolder.addSelectionListener(chefHistoryRefresher); chefLog.setChefHistoryRefresher(chefHistoryRefresher); } tabMap.put(tabName, new TabMapEntry(tabItem, tabName, chefLog, TabMapEntry.OBJECT_TYPE_JOB_LOG)); } int idx = tabfolder.indexOf(tabItem); tabfolder.setSelection(idx); } public void addSpoonHistory(TransMeta transMeta, boolean select) { // See if there already is a tab for this history view // If no, add it // If yes, select that tab // String tabName = makeHistoryTabName(transMeta); CTabItem tabItem = findCTabItem(tabName, TabMapEntry.OBJECT_TYPE_TRANSFORMATION_HISTORY); if (tabItem == null) { SpoonHistory spoonHistory = new SpoonHistory(tabfolder, this, transMeta); tabItem = new CTabItem(tabfolder, SWT.CLOSE); tabItem.setText(tabName); tabItem.setToolTipText(Messages.getString("Spoon.Title.ExecHistoryTransView.Tooltip", makeTransGraphTabName(transMeta))); tabItem.setControl(spoonHistory); // If there is an associated log window that's open, find it and add a refresher SpoonLog spoonLog = findSpoonLogOfTransformation(transMeta); if (spoonLog != null) { SpoonHistoryRefresher spoonHistoryRefresher = new SpoonHistoryRefresher(tabItem, spoonHistory); tabfolder.addSelectionListener(spoonHistoryRefresher); spoonLog.setSpoonHistoryRefresher(spoonHistoryRefresher); } spoonHistory.markRefreshNeeded(); // will refresh when first selected tabMap.put(tabName, new TabMapEntry(tabItem, tabName, spoonHistory, TabMapEntry.OBJECT_TYPE_TRANSFORMATION_HISTORY)); } if (select) { int idx = tabfolder.indexOf(tabItem); tabfolder.setSelection(idx); } } public void addChefHistory(JobMeta jobMeta, boolean select) { // See if there already is a tab for this history view // If no, add it // If yes, select that tab // String tabName = makeJobHistoryTabName(jobMeta); CTabItem tabItem = findCTabItem(tabName, TabMapEntry.OBJECT_TYPE_JOB_HISTORY); if (tabItem == null) { ChefHistory chefHistory = new ChefHistory(tabfolder, this, jobMeta); tabItem = new CTabItem(tabfolder, SWT.CLOSE); tabItem.setText(tabName); tabItem.setToolTipText( Messages.getString("Spoon.Title.ExecHistoryJobView.Tooltip", makeJobGraphTabName(jobMeta))); tabItem.setControl(chefHistory); // If there is an associated log window that's open, find it and add a refresher ChefLog chefLog = findChefLogOfJob(jobMeta); if (chefLog != null) { ChefHistoryRefresher chefHistoryRefresher = new ChefHistoryRefresher(tabItem, chefHistory); tabfolder.addSelectionListener(chefHistoryRefresher); chefLog.setChefHistoryRefresher(chefHistoryRefresher); } chefHistory.markRefreshNeeded(); // will refresh when first selected tabMap.put(tabName, new TabMapEntry(tabItem, tabName, chefHistory, TabMapEntry.OBJECT_TYPE_JOB_HISTORY)); } if (select) { int idx = tabfolder.indexOf(tabItem); tabfolder.setSelection(idx); } } /** * Rename the tabs */ public void renameTabs() { Collection collection = tabMap.values(); List list = new ArrayList(); list.addAll(collection); for (Iterator iter = list.iterator(); iter.hasNext();) { TabMapEntry entry = (TabMapEntry) iter.next(); if (entry.getTabItem().isDisposed()) { // this should not be in the map, get rid of it. tabMap.remove(entry.getObjectName()); continue; } String before = entry.getTabItem().getText(); Object managedObject = entry.getObject().getManagedObject(); if (managedObject != null) { if (entry.getObject() instanceof SpoonGraph) { entry.getTabItem().setText(makeTransGraphTabName((TransMeta) managedObject)); entry.getTabItem().setToolTipText(Messages.getString("Spoon.TabTrans.Tooltip", makeTransGraphTabName((TransMeta) managedObject))); } else if (entry.getObject() instanceof SpoonLog) entry.getTabItem().setText(makeLogTabName((TransMeta) managedObject)); else if (entry.getObject() instanceof SpoonHistory) entry.getTabItem().setText(makeHistoryTabName((TransMeta) managedObject)); else if (entry.getObject() instanceof ChefGraph) { entry.getTabItem().setText(makeJobGraphTabName((JobMeta) managedObject)); entry.getTabItem().setToolTipText(Messages.getString("Spoon.TabJob.Tooltip", makeJobGraphTabName((JobMeta) managedObject))); } else if (entry.getObject() instanceof ChefLog) entry.getTabItem().setText(makeJobLogTabName((JobMeta) managedObject)); else if (entry.getObject() instanceof ChefHistory) entry.getTabItem().setText(makeJobHistoryTabName((JobMeta) managedObject)); } String after = entry.getTabItem().getText(); if (!before.equals(after)) { entry.setObjectName(after); tabMap.remove(before); tabMap.put(after, entry); // Also change the transformation map if (entry.getObject() instanceof SpoonGraph) { transformationMap.remove(before); transformationMap.put(after, entry.getObject().getManagedObject()); } // Also change the job map if (entry.getObject() instanceof ChefGraph) { jobMap.remove(before); jobMap.put(after, entry.getObject().getManagedObject()); } } } setShellText(); } /** * This contains a map between the name of a transformation and the TransMeta object. * If the transformation has no name it will be mapped under a number [1], [2] etc. * @return the transformation map */ public Map getTransformationMap() { return transformationMap; } /** * @param transformationMap the transformation map to set */ public void setTransformationMap(Map transformationMap) { this.transformationMap = transformationMap; } /** * @return the tabMap */ public Map getTabMap() { return tabMap; } /** * @param tabMap the tabMap to set */ public void setTabMap(Map tabMap) { this.tabMap = tabMap; } public void pasteSteps() { // Is there an active SpoonGraph? SpoonGraph spoonGraph = getActiveSpoonGraph(); if (spoonGraph == null) return; TransMeta transMeta = spoonGraph.getTransMeta(); String clipcontent = fromClipboard(); if (clipcontent != null) { Point lastMove = spoonGraph.getLastMove(); if (lastMove != null) { pasteXML(transMeta, clipcontent, lastMove); } } } ////////////////////////////////////////////////////////////////////////////////////////////////// // // // // Job manipulation steps... // // // ////////////////////////////////////////////////////////////////////////////////////////////////// public JobEntryCopy newJobEntry(JobMeta jobMeta, String type_desc, boolean openit) { JobEntryLoader jobLoader = JobEntryLoader.getInstance(); JobPlugin jobPlugin = null; try { jobPlugin = jobLoader.findJobEntriesWithDescription(type_desc); if (jobPlugin == null) { // Check if it's not START or DUMMY if (JobMeta.STRING_SPECIAL_START.equals(type_desc) || JobMeta.STRING_SPECIAL_DUMMY.equals(type_desc)) { jobPlugin = jobLoader.findJobEntriesWithID(JobMeta.STRING_SPECIAL); } } if (jobPlugin != null) { // Determine name & number for this entry. String basename = type_desc; int nr = jobMeta.generateJobEntryNameNr(basename); String entry_name = basename + " " + nr; //$NON-NLS-1$ // Generate the appropriate class... JobEntryInterface jei = jobLoader.getJobEntryClass(jobPlugin); jei.setName(entry_name); if (jei.isSpecial()) { if (JobMeta.STRING_SPECIAL_START.equals(type_desc)) { // Check if start is already on the canvas... if (jobMeta.findStart() != null) { ChefGraph.showOnlyStartOnceMessage(shell); return null; } ((JobEntrySpecial) jei).setStart(true); jei.setName("Start"); } if (JobMeta.STRING_SPECIAL_DUMMY.equals(type_desc)) { ((JobEntrySpecial) jei).setDummy(true); jei.setName("Dummy"); } } if (openit) { JobEntryDialogInterface d = jei.getDialog(shell, jei, jobMeta, entry_name, rep); if (d.open() != null) { JobEntryCopy jge = new JobEntryCopy(); jge.setEntry(jei); jge.setLocation(50, 50); jge.setNr(0); jobMeta.addJobEntry(jge); addUndoNew(jobMeta, new JobEntryCopy[] { jge }, new int[] { jobMeta.indexOfJobEntry(jge) }); refreshGraph(); refreshTree(); return jge; } else { return null; } } else { JobEntryCopy jge = new JobEntryCopy(); jge.setEntry(jei); jge.setLocation(50, 50); jge.setNr(0); jobMeta.addJobEntry(jge); addUndoNew(jobMeta, new JobEntryCopy[] { jge }, new int[] { jobMeta.indexOfJobEntry(jge) }); refreshGraph(); refreshTree(); return jge; } } else { return null; } } catch (Throwable e) { new ErrorDialog(shell, Messages.getString("Spoon.ErrorDialog.UnexpectedErrorCreatingNewChefGraphEntry.Title"), //$NON-NLS-1$ Messages.getString("Spoon.ErrorDialog.UnexpectedErrorCreatingNewChefGraphEntry.Message"), //$NON-NLS-1$ new Exception(e)); return null; } } public boolean saveJobFile(JobMeta jobMeta) { log.logDetailed(toString(), "Save file..."); //$NON-NLS-1$ boolean saved = false; if (rep != null) { saved = saveJobRepository(jobMeta); } else { if (jobMeta.getFilename() != null) { saved = saveJob(jobMeta, jobMeta.getFilename()); } else { saved = saveJobFileAs(jobMeta); } } if (saved) // all was OK { saved = saveJobSharedObjects(jobMeta); } return saved; } private boolean saveJobXMLFile(JobMeta jobMeta) { boolean saved = false; FileDialog dialog = new FileDialog(shell, SWT.SAVE); dialog.setFilterExtensions(Const.STRING_JOB_FILTER_EXT); dialog.setFilterNames(Const.getJobFilterNames()); String fname = dialog.open(); if (fname != null) { // Is the filename ending on .ktr, .xml? boolean ending = false; for (int i = 0; i < Const.STRING_JOB_FILTER_EXT.length - 1; i++) { if (fname.endsWith(Const.STRING_JOB_FILTER_EXT[i].substring(1))) { ending = true; } } if (fname.endsWith(Const.STRING_JOB_DEFAULT_EXT)) ending = true; if (!ending) { fname += Const.STRING_JOB_DEFAULT_EXT; } // See if the file already exists... File f = new File(fname); int id = SWT.YES; if (f.exists()) { MessageBox mb = new MessageBox(shell, SWT.NO | SWT.YES | SWT.ICON_WARNING); mb.setMessage(Messages.getString("Spoon.Dialog.PromptOverwriteFile.Message"));//"This file already exists. Do you want to overwrite it?" mb.setText(Messages.getString("Spoon.Dialog.PromptOverwriteFile.Title"));//"This file already exists!" id = mb.open(); } if (id == SWT.YES) { saved = saveJob(jobMeta, fname); jobMeta.setFilename(fname); } } return saved; } public boolean saveJobRepository(JobMeta jobMeta) { return saveJobRepository(jobMeta, false); } public boolean saveJobRepository(JobMeta jobMeta, boolean ask_name) { log.logDetailed(toString(), "Save to repository..."); //$NON-NLS-1$ if (rep != null) { boolean answer = true; boolean ask = ask_name; while (answer && (ask || jobMeta.getName() == null || jobMeta.getName().length() == 0)) { if (!ask) { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_WARNING); mb.setMessage(Messages.getString("Spoon.Dialog.GiveJobANameBeforeSaving.Message")); //$NON-NLS-1$ mb.setText(Messages.getString("Spoon.Dialog.GiveJobANameBeforeSaving.Title")); //$NON-NLS-1$ mb.open(); } ask = false; answer = editJobProperties(jobMeta); } if (answer && jobMeta.getName() != null && jobMeta.getName().length() > 0) { if (!rep.getUserInfo().isReadonly()) { boolean saved = false; int response = SWT.YES; if (jobMeta.showReplaceWarning(rep)) { MessageBox mb = new MessageBox(shell, SWT.YES | SWT.NO | SWT.ICON_QUESTION); mb.setMessage("'" + jobMeta.getName() + "'" + Const.CR + Const.CR //$NON-NLS-1$//$NON-NLS-2$ + Messages.getString("Spoon.Dialog.FileExistsOverWrite.Message")); //$NON-NLS-1$ mb.setText(Messages.getString("Spoon.Dialog.FileExistsOverWrite.Title")); //$NON-NLS-1$ response = mb.open(); } if (response == SWT.YES) { // Keep info on who & when this transformation was changed... jobMeta.modifiedDate = new Value("MODIFIED_DATE", Value.VALUE_TYPE_DATE); //$NON-NLS-1$ jobMeta.modifiedDate.sysdate(); jobMeta.modifiedUser = rep.getUserInfo().getLogin(); JobSaveProgressDialog jspd = new JobSaveProgressDialog(shell, rep, jobMeta); if (jspd.open()) { if (!props.getSaveConfirmation()) { MessageDialogWithToggle md = new MessageDialogWithToggle(shell, Messages.getString("Spoon.Dialog.JobWasStoredInTheRepository.Title"), //$NON-NLS-1$ null, Messages.getString("Spoon.Dialog.JobWasStoredInTheRepository.Message"), //$NON-NLS-1$ MessageDialog.QUESTION, new String[] { Messages.getString("System.Button.OK") }, //$NON-NLS-1$ 0, Messages.getString("Spoon.Dialog.JobWasStoredInTheRepository.Toggle"), //$NON-NLS-1$ props.getSaveConfirmation()); md.open(); props.setSaveConfirmation(md.getToggleState()); } // Handle last opened files... props.addLastFile(LastUsedFile.FILE_TYPE_JOB, jobMeta.getName(), jobMeta.getDirectory().getPath(), true, rep.getName()); saveSettings(); addMenuLast(); setShellText(); saved = true; } } return saved; } else { MessageBox mb = new MessageBox(shell, SWT.CLOSE | SWT.ICON_ERROR); mb.setMessage( Messages.getString("Spoon.Dialog.UserCanOnlyReadFromTheRepositoryJobNotSaved.Message")); //$NON-NLS-1$ mb.setText( Messages.getString("Spoon.Dialog.UserCanOnlyReadFromTheRepositoryJobNotSaved.Title")); //$NON-NLS-1$ mb.open(); } } } else { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR); mb.setMessage(Messages.getString("Spoon.Dialog.NoRepositoryConnectionAvailable.Message")); //$NON-NLS-1$ mb.setText(Messages.getString("Spoon.Dialog.NoRepositoryConnectionAvailable.Title")); //$NON-NLS-1$ mb.open(); } return false; } public boolean saveJobFileAs(JobMeta jobMeta) { boolean saved = false; if (rep != null) { jobMeta.setID(-1L); saved = saveJobRepository(jobMeta, true); renameTabs(); } else { saved = saveJobXMLFile(jobMeta); renameTabs(); } return saved; } public void saveJobFileAsXML(JobMeta jobMeta) { log.logBasic(toString(), "Save file as..."); //$NON-NLS-1$ FileDialog dialog = new FileDialog(shell, SWT.SAVE); //dialog.setFilterPath("C:\\Projects\\kettle\\source\\"); dialog.setFilterExtensions(Const.STRING_JOB_FILTER_EXT); dialog.setFilterNames(Const.getJobFilterNames()); String fname = dialog.open(); if (fname != null) { // Is the filename ending on .ktr, .xml? boolean ending = false; for (int i = 0; i < Const.STRING_JOB_FILTER_EXT.length - 1; i++) { if (fname.endsWith(Const.STRING_JOB_FILTER_EXT[i].substring(1))) ending = true; } if (fname.endsWith(Const.STRING_JOB_DEFAULT_EXT)) ending = true; if (!ending) { fname += Const.STRING_JOB_DEFAULT_EXT; } // See if the file already exists... File f = new File(fname); int id = SWT.YES; if (f.exists()) { MessageBox mb = new MessageBox(shell, SWT.NO | SWT.YES | SWT.ICON_WARNING); mb.setMessage(Messages.getString("Spoon.Dialog.FileExistsOverWrite.Message")); //$NON-NLS-1$ mb.setText(Messages.getString("Spoon.Dialog.FileExistsOverWrite.Title")); //$NON-NLS-1$ id = mb.open(); } if (id == SWT.YES) { saveJob(jobMeta, fname); } } } private boolean saveJob(JobMeta jobMeta, String fname) { boolean saved = false; String xml = XMLHandler.getXMLHeader() + jobMeta.getXML(); try { DataOutputStream dos = new DataOutputStream(KettleVFS.getOutputStream(fname, false)); dos.write(xml.getBytes(Const.XML_ENCODING)); dos.close(); saved = true; // Handle last opened files... props.addLastFile(LastUsedFile.FILE_TYPE_JOB, fname, RepositoryDirectory.DIRECTORY_SEPARATOR, false, ""); //$NON-NLS-1$ saveSettings(); addMenuLast(); log.logDebug(toString(), "File written to [" + fname + "]"); //$NON-NLS-1$ //$NON-NLS-2$ jobMeta.setFilename(fname); jobMeta.clearChanged(); setShellText(); } catch (Exception e) { log.logDebug(toString(), "Error opening file for writing! --> " + e.toString()); //$NON-NLS-1$ MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR); mb.setMessage(Messages.getString("Spoon.Dialog.ErrorSavingFile.Message") + Const.CR + e.toString()); //$NON-NLS-1$ mb.setText(Messages.getString("Spoon.Dialog.ErrorSavingFile.Title")); //$NON-NLS-1$ mb.open(); } return saved; } public boolean editJobProperties(JobMeta jobMeta) { if (jobMeta == null) return false; JobDialog jd = new JobDialog(shell, SWT.NONE, jobMeta, rep); JobMeta ji = jd.open(); // In this case, load shared objects // if (jd.isSharedObjectsFileChanged()) { loadJobSharedObjects(jobMeta); } if (jd.isSharedObjectsFileChanged() || ji != null) { refreshTree(); renameTabs(); // cheap operation, might as will do it anyway } setShellText(); return ji != null; } public void editJobEntry(JobMeta jobMeta, JobEntryCopy je) { try { log.logBasic(toString(), "edit job graph entry: " + je.getName()); //$NON-NLS-1$ JobEntryCopy before = (JobEntryCopy) je.clone_deep(); boolean entry_changed = false; JobEntryInterface jei = je.getEntry(); if (jei.isSpecial()) { JobEntrySpecial special = (JobEntrySpecial) jei; if (special.isDummy()) return; } JobEntryDialogInterface d = jei.getDialog(shell, jei, jobMeta, je.getName(), rep); if (d != null) { if (d.open() != null) { entry_changed = true; } if (entry_changed) { JobEntryCopy after = (JobEntryCopy) je.clone(); addUndoChange(jobMeta, new JobEntryCopy[] { before }, new JobEntryCopy[] { after }, new int[] { jobMeta.indexOfJobEntry(je) }); refreshGraph(); refreshTree(); } } else { MessageBox mb = new MessageBox(shell, SWT.OK | SWT.ICON_INFORMATION); mb.setMessage(Messages.getString("Spoon.Dialog.JobEntryCanNotBeChanged.Message")); //$NON-NLS-1$ mb.setText(Messages.getString("Spoon.Dialog.JobEntryCanNotBeChanged.Title")); //$NON-NLS-1$ mb.open(); } } catch (Exception e) { if (!shell.isDisposed()) new ErrorDialog(shell, Messages.getString("Spoon.ErrorDialog.ErrorEditingJobEntry.Title"), //$NON-NLS-1$ Messages.getString("Spoon.ErrorDialog.ErrorEditingJobEntry.Message"), e); //$NON-NLS-1$ } } public JobEntryTrans newJobEntry(JobMeta jobMeta, int type) { JobEntryTrans je = new JobEntryTrans(); je.setType(type); String basename = JobEntryInterface.typeDesc[type]; int nr = jobMeta.generateJobEntryNameNr(basename); je.setName(basename + " " + nr); //$NON-NLS-1$ setShellText(); return je; } public void deleteJobEntryCopies(JobMeta jobMeta, JobEntryCopy jobEntry) { String name = jobEntry.getName(); // TODO Show warning "Are you sure? This operation can't be undone." + clear undo buffer. // First delete all the hops using entry with name: JobHopMeta hi[] = jobMeta.getAllJobHopsUsing(name); if (hi.length > 0) { int hix[] = new int[hi.length]; for (int i = 0; i < hi.length; i++) hix[i] = jobMeta.indexOfJobHop(hi[i]); addUndoDelete(jobMeta, hi, hix); for (int i = hix.length - 1; i >= 0; i--) jobMeta.removeJobHop(hix[i]); } // Then delete all the entries with name: JobEntryCopy je[] = jobMeta.getAllChefGraphEntries(name); int jex[] = new int[je.length]; for (int i = 0; i < je.length; i++) jex[i] = jobMeta.indexOfJobEntry(je[i]); if (je.length > 0) addUndoDelete(jobMeta, je, jex); for (int i = jex.length - 1; i >= 0; i--) jobMeta.removeJobEntry(jex[i]); jobMeta.clearUndo(); setUndoMenu(jobMeta); refreshGraph(); refreshTree(); } public void dupeJobEntry(JobMeta jobMeta, JobEntryCopy jobEntry) { if (jobEntry != null && !jobEntry.isStart()) { JobEntryCopy dupejge = (JobEntryCopy) jobEntry.clone(); dupejge.setNr(jobMeta.findUnusedNr(dupejge.getName())); if (dupejge.isDrawn()) { Point p = jobEntry.getLocation(); dupejge.setLocation(p.x + 10, p.y + 10); } jobMeta.addJobEntry(dupejge); refreshGraph(); refreshTree(); setShellText(); } } public void copyJobEntries(JobMeta jobMeta, JobEntryCopy jec[]) { if (jec == null || jec.length == 0) return; String xml = XMLHandler.getXMLHeader(); xml += "<jobentries>" + Const.CR; //$NON-NLS-1$ for (int i = 0; i < jec.length; i++) { xml += jec[i].getXML(); } xml += " </jobentries>" + Const.CR; //$NON-NLS-1$ toClipboard(xml); } public void pasteXML(JobMeta jobMeta, String clipcontent, Point loc) { try { Document doc = XMLHandler.loadXMLString(clipcontent); // De-select all, re-select pasted steps... jobMeta.unselectAll(); Node entriesnode = XMLHandler.getSubNode(doc, "jobentries"); //$NON-NLS-1$ int nr = XMLHandler.countNodes(entriesnode, "entry"); //$NON-NLS-1$ log.logDebug(toString(), "I found " + nr + " job entries to paste on location: " + loc); //$NON-NLS-1$ //$NON-NLS-2$ JobEntryCopy entries[] = new JobEntryCopy[nr]; //Point min = new Point(loc.x, loc.y); Point min = new Point(99999999, 99999999); for (int i = 0; i < nr; i++) { Node entrynode = XMLHandler.getSubNodeByNr(entriesnode, "entry", i); //$NON-NLS-1$ entries[i] = new JobEntryCopy(entrynode, jobMeta.getDatabases(), rep); String name = jobMeta.getAlternativeJobentryName(entries[i].getName()); entries[i].setName(name); if (loc != null) { Point p = entries[i].getLocation(); if (min.x > p.x) min.x = p.x; if (min.y > p.y) min.y = p.y; } } // What's the difference between loc and min? // This is the offset: Point offset = new Point(loc.x - min.x, loc.y - min.y); // Undo/redo object positions... int position[] = new int[entries.length]; for (int i = 0; i < entries.length; i++) { Point p = entries[i].getLocation(); String name = entries[i].getName(); entries[i].setLocation(p.x + offset.x, p.y + offset.y); // Check the name, find alternative... entries[i].setName(jobMeta.getAlternativeJobentryName(name)); jobMeta.addJobEntry(entries[i]); position[i] = jobMeta.indexOfJobEntry(entries[i]); } // Save undo information too... addUndoNew(jobMeta, entries, position); if (jobMeta.hasChanged()) { refreshTree(); refreshGraph(); } } catch (KettleException e) { new ErrorDialog(shell, Messages.getString("Spoon.ErrorDialog.ErrorPasingJobEntries.Title"), //$NON-NLS-1$ Messages.getString("Spoon.ErrorDialog.ErrorPasingJobEntries.Message"), e); //$NON-NLS-1$ } } public void newJobHop(JobMeta jobMeta, JobEntryCopy fr, JobEntryCopy to) { JobHopMeta hi = new JobHopMeta(fr, to); jobMeta.addJobHop(hi); addUndoNew(jobMeta, new JobHopMeta[] { hi }, new int[] { jobMeta.indexOfJobHop(hi) }); refreshGraph(); refreshTree(); } /** * Create a job that extracts tables & data from a database.<p><p> * * 0) Select the database to rip<p> * 1) Select the tables in the database to rip<p> * 2) Select the database to dump to<p> * 3) Select the repository directory in which it will end up<p> * 4) Select a name for the new job<p> * 5) Create an empty job with the selected name.<p> * 6) Create 1 transformation for every selected table<p> * 7) add every created transformation to the job & evaluate<p> * */ private void ripDBWizard() { final ArrayList databases = getActiveDatabases(); if (databases.size() == 0) return; // Nothing to do here final RipDatabaseWizardPage1 page1 = new RipDatabaseWizardPage1("1", databases); //$NON-NLS-1$ page1.createControl(shell); final RipDatabaseWizardPage2 page2 = new RipDatabaseWizardPage2("2"); //$NON-NLS-1$ page2.createControl(shell); final RipDatabaseWizardPage3 page3 = new RipDatabaseWizardPage3("3", rep); //$NON-NLS-1$ page3.createControl(shell); Wizard wizard = new Wizard() { public boolean performFinish() { JobMeta jobMeta = ripDB(databases, page3.getJobname(), page3.getRepositoryDirectory(), page3.getDirectory(), page1.getSourceDatabase(), page1.getTargetDatabase(), page2.getSelection()); if (jobMeta == null) return false; if (page3.getRepositoryDirectory() != null) { saveJobRepository(jobMeta); } else { saveJobFile(jobMeta); } addChefGraph(jobMeta); return true; } /** * @see org.eclipse.jface.wizard.Wizard#canFinish() */ public boolean canFinish() { return page3.canFinish(); } }; wizard.addPage(page1); wizard.addPage(page2); wizard.addPage(page3); WizardDialog wd = new WizardDialog(shell, wizard); wd.setMinimumPageSize(700, 400); wd.open(); } public JobMeta ripDB(final ArrayList databases, final String jobname, final RepositoryDirectory repdir, final String directory, final DatabaseMeta sourceDbInfo, final DatabaseMeta targetDbInfo, final String[] tables) { // // Create a new job... // final JobMeta jobMeta = new JobMeta(log); jobMeta.setDatabases(databases); jobMeta.setFilename(null); jobMeta.setName(jobname); if (rep != null) { jobMeta.setDirectory(repdir); } else { jobMeta.setFilename(Const.createFilename(directory, jobname, Const.STRING_JOB_DEFAULT_EXT)); } refreshTree(); refreshGraph(); final Point location = new Point(50, 50); // The start entry... final JobEntryCopy start = JobMeta.createStartEntry(); start.setLocation(new Point(location.x, location.y)); start.setDrawn(); jobMeta.addJobEntry(start); // final Thread parentThread = Thread.currentThread(); // Create a dialog with a progress indicator! IRunnableWithProgress op = new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { // This is running in a new process: copy some KettleVariables info // LocalVariables.getInstance().createKettleVariables(Thread.currentThread().getName(), // parentThread.getName(), true); monitor.beginTask(Messages.getString("Spoon.RipDB.Monitor.BuildingNewJob"), tables.length); //$NON-NLS-1$ monitor.worked(0); JobEntryCopy previous = start; // Loop over the table-names... for (int i = 0; i < tables.length && !monitor.isCanceled(); i++) { monitor.setTaskName( Messages.getString("Spoon.RipDB.Monitor.ProcessingTable") + tables[i] + "]..."); //$NON-NLS-1$ //$NON-NLS-2$ // // Create the new transformation... // String transname = Messages.getString("Spoon.RipDB.Monitor.Transname1") + sourceDbInfo + "].[" //$NON-NLS-1$//$NON-NLS-2$ + tables[i] + Messages.getString("Spoon.RipDB.Monitor.Transname2") + targetDbInfo + "]"; //$NON-NLS-1$ //$NON-NLS-2$ TransMeta transMeta = new TransMeta((String) null, transname, null); if (repdir != null) { transMeta.setDirectory(repdir); } else { transMeta.setFilename( Const.createFilename(directory, transname, Const.STRING_TRANS_DEFAULT_EXT)); } // // Add a note // String note = Messages.getString("Spoon.RipDB.Monitor.Note1") + tables[i] //$NON-NLS-1$ + Messages.getString("Spoon.RipDB.Monitor.Note2") + sourceDbInfo + "]" + Const.CR; //$NON-NLS-1$ //$NON-NLS-2$ note += Messages.getString("Spoon.RipDB.Monitor.Note3") + tables[i] //$NON-NLS-1$ + Messages.getString("Spoon.RipDB.Monitor.Note4") + targetDbInfo + "]"; //$NON-NLS-1$ //$NON-NLS-2$ NotePadMeta ni = new NotePadMeta(note, 150, 10, -1, -1); transMeta.addNote(ni); // // Add the TableInputMeta step... // String fromstepname = Messages.getString("Spoon.RipDB.Monitor.FromStep.Name") + tables[i] + "]"; //$NON-NLS-1$ //$NON-NLS-2$ TableInputMeta tii = new TableInputMeta(); tii.setDatabaseMeta(sourceDbInfo); tii.setSQL("SELECT * FROM " + sourceDbInfo.quoteField(tables[i])); //$NON-NLS-1$ String fromstepid = StepLoader.getInstance().getStepPluginID(tii); StepMeta fromstep = new StepMeta(fromstepid, fromstepname, tii); fromstep.setLocation(150, 100); fromstep.setDraw(true); fromstep.setDescription(Messages.getString("Spoon.RipDB.Monitor.FromStep.Description") //$NON-NLS-1$ + tables[i] + Messages.getString("Spoon.RipDB.Monitor.FromStep.Description2") //$NON-NLS-1$ + sourceDbInfo + "]"); //$NON-NLS-1$ transMeta.addStep(fromstep); // // Add the TableOutputMeta step... // String tostepname = Messages.getString("Spoon.RipDB.Monitor.ToStep.Name") + tables[i] + "]"; //$NON-NLS-1$ //$NON-NLS-2$ TableOutputMeta toi = new TableOutputMeta(); toi.setDatabaseMeta(targetDbInfo); toi.setTablename(tables[i]); toi.setCommitSize(100); toi.setTruncateTable(true); String tostepid = StepLoader.getInstance().getStepPluginID(toi); StepMeta tostep = new StepMeta(tostepid, tostepname, toi); tostep.setLocation(500, 100); tostep.setDraw(true); tostep.setDescription(Messages.getString("Spoon.RipDB.Monitor.ToStep.Description1") + tables[i] //$NON-NLS-1$ + Messages.getString("Spoon.RipDB.Monitor.ToStep.Description2") + targetDbInfo + "]"); //$NON-NLS-1$ //$NON-NLS-2$ transMeta.addStep(tostep); // // Add a hop between the two steps... // TransHopMeta hi = new TransHopMeta(fromstep, tostep); transMeta.addTransHop(hi); // // Now we generate the SQL needed to run for this transformation. // // First set the limit to 1 to speed things up! String tmpSql = tii.getSQL(); tii.setSQL(tii.getSQL() + sourceDbInfo.getLimitClause(1)); String sql = ""; //$NON-NLS-1$ try { sql = transMeta.getSQLStatementsString(); } catch (KettleStepException kse) { throw new InvocationTargetException(kse, Messages.getString("Spoon.RipDB.Exception.ErrorGettingSQLFromTransformation") //$NON-NLS-1$ + transMeta + "] : " + kse.getMessage()); //$NON-NLS-1$ } // remove the limit tii.setSQL(tmpSql); // // Now, save the transformation... // boolean ok; if (rep != null) { ok = saveTransRepository(transMeta); } else { ok = saveTransFile(transMeta); } if (!ok) { throw new InvocationTargetException( new Exception(Messages .getString("Spoon.RipDB.Exception.UnableToSaveTransformationToRepository")), //$NON-NLS-1$ Messages.getString("Spoon.RipDB.Exception.UnableToSaveTransformationToRepository")); } // We can now continue with the population of the job... // ////////////////////////////////////////////////////////////////////// location.x = 250; if (i > 0) location.y += 100; // // We can continue defining the job. // // First the SQL, but only if needed! // If the table exists & has the correct format, nothing is done // if (!Const.isEmpty(sql)) { String jesqlname = Messages.getString("Spoon.RipDB.JobEntrySQL.Name") + tables[i] + "]"; //$NON-NLS-1$ //$NON-NLS-2$ JobEntrySQL jesql = new JobEntrySQL(jesqlname); jesql.setDatabase(targetDbInfo); jesql.setSQL(sql); jesql.setDescription(Messages.getString("Spoon.RipDB.JobEntrySQL.Description") //$NON-NLS-1$ + targetDbInfo + "].[" + tables[i] + "]"); //$NON-NLS-1$ //$NON-NLS-2$ JobEntryCopy jecsql = new JobEntryCopy(); jecsql.setEntry(jesql); jecsql.setLocation(new Point(location.x, location.y)); jecsql.setDrawn(); jobMeta.addJobEntry(jecsql); // Add the hop too... JobHopMeta jhi = new JobHopMeta(previous, jecsql); jobMeta.addJobHop(jhi); previous = jecsql; } // // Add the jobentry for the transformation too... // String jetransname = Messages.getString("Spoon.RipDB.JobEntryTrans.Name") + tables[i] + "]"; //$NON-NLS-1$ //$NON-NLS-2$ JobEntryTrans jetrans = new JobEntryTrans(jetransname); jetrans.setTransname(transMeta.getName()); if (rep != null) { jetrans.setDirectory(transMeta.getDirectory()); } else { jetrans.setFileName( Const.createFilename("${" + Const.INTERNAL_VARIABLE_JOB_FILENAME_DIRECTORY + "}", transMeta.getName(), Const.STRING_TRANS_DEFAULT_EXT)); } JobEntryCopy jectrans = new JobEntryCopy(log, jetrans); jectrans.setDescription(Messages.getString("Spoon.RipDB.JobEntryTrans.Description1") + Const.CR //$NON-NLS-1$ + Messages.getString("Spoon.RipDB.JobEntryTrans.Description2") + sourceDbInfo + "].[" //$NON-NLS-1$//$NON-NLS-2$ + tables[i] + "]" + Const.CR //$NON-NLS-1$ + Messages.getString("Spoon.RipDB.JobEntryTrans.Description3") + targetDbInfo + "].[" //$NON-NLS-1$//$NON-NLS-2$ + tables[i] + "]"); //$NON-NLS-1$ jectrans.setDrawn(); location.x += 400; jectrans.setLocation(new Point(location.x, location.y)); jobMeta.addJobEntry(jectrans); // Add a hop between the last 2 job entries. JobHopMeta jhi2 = new JobHopMeta(previous, jectrans); jobMeta.addJobHop(jhi2); previous = jectrans; monitor.worked(1); } monitor.worked(100); monitor.done(); } }; try { ProgressMonitorDialog pmd = new ProgressMonitorDialog(shell); pmd.run(false, true, op); } catch (InvocationTargetException e) { new ErrorDialog(shell, Messages.getString("Spoon.ErrorDialog.RipDB.ErrorRippingTheDatabase.Title"), //$NON-NLS-1$ Messages.getString("Spoon.ErrorDialog.RipDB.ErrorRippingTheDatabase.Message"), e); //$NON-NLS-1$ return null; } catch (InterruptedException e) { new ErrorDialog(shell, Messages.getString("Spoon.ErrorDialog.RipDB.ErrorRippingTheDatabase.Title"), //$NON-NLS-1$ Messages.getString("Spoon.ErrorDialog.RipDB.ErrorRippingTheDatabase.Message"), e); //$NON-NLS-1$ return null; } finally { refreshGraph(); refreshTree(); } return jobMeta; } /** * Set the core object state. * * @param state */ public void setCoreObjectsState(int state) { coreObjectsState = state; } /** * Get the core object state. * * @return state. */ public int getCoreObjectsState() { return coreObjectsState; } }