/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2017 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
package org.pentaho.di.ui.spoon.delegates;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.MessageBox;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.util.Utils;
import org.pentaho.di.core.DBCache;
import org.pentaho.di.core.NotePadMeta;
import org.pentaho.di.core.SQLStatement;
import org.pentaho.di.core.database.Database;
import org.pentaho.di.core.database.DatabaseMeta;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.gui.UndoInterface;
import org.pentaho.di.core.plugins.PluginRegistry;
import org.pentaho.di.core.plugins.StepPluginType;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.core.variables.VariableSpace;
import org.pentaho.di.core.variables.Variables;
import org.pentaho.di.core.xml.XMLHandler;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.job.JobMeta;
import org.pentaho.di.repository.Repository;
import org.pentaho.di.trans.HasDatabasesInterface;
import org.pentaho.di.trans.TransHopMeta;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.steps.selectvalues.SelectMetadataChange;
import org.pentaho.di.trans.steps.selectvalues.SelectValuesMeta;
import org.pentaho.di.trans.steps.tableinput.TableInputMeta;
import org.pentaho.di.trans.steps.tableoutput.TableOutputMeta;
import org.pentaho.di.ui.core.database.dialog.DatabaseDialog;
import org.pentaho.di.ui.core.database.dialog.DatabaseExplorerDialog;
import org.pentaho.di.ui.core.database.dialog.SQLEditor;
import org.pentaho.di.ui.core.dialog.ErrorDialog;
import org.pentaho.di.ui.core.dialog.SQLStatementsDialog;
import org.pentaho.di.ui.core.gui.GUIResource;
import org.pentaho.di.ui.spoon.SharedObjectSyncUtil;
import org.pentaho.di.ui.spoon.Spoon;
import org.pentaho.di.ui.spoon.dialog.GetJobSQLProgressDialog;
import org.pentaho.di.ui.spoon.dialog.GetSQLProgressDialog;
import org.pentaho.di.ui.util.DialogUtils;
public class SpoonDBDelegate extends SpoonDelegate {
private static Class<?> PKG = Spoon.class; // for i18n purposes, needed by Translator2!!
private DatabaseDialog databaseDialog;
private SharedObjectSyncUtil sharedObjectSyncUtil;
public SpoonDBDelegate( Spoon spoon ) {
super( spoon );
}
public void setSharedObjectSyncUtil( SharedObjectSyncUtil sharedObjectSyncUtil ) {
this.sharedObjectSyncUtil = sharedObjectSyncUtil;
}
public void sqlConnection( DatabaseMeta databaseMeta ) {
SQLEditor sql =
new SQLEditor( databaseMeta, spoon.getShell(), SWT.NONE, databaseMeta, DBCache.getInstance(), "" );
sql.open();
}
public void editConnection( DatabaseMeta databaseMeta ) {
HasDatabasesInterface hasDatabasesInterface = spoon.getActiveHasDatabasesInterface();
if ( hasDatabasesInterface == null ) {
return; // program error, exit just to make sure.
}
String originalName = databaseMeta.getName();
getDatabaseDialog().setDatabaseMeta( databaseMeta );
getDatabaseDialog().setDatabases( hasDatabasesInterface.getDatabases() );
String newname = getDatabaseDialog().open();
if ( !Utils.isEmpty( newname ) ) { // null: CANCEL
databaseMeta = getDatabaseDialog().getDatabaseMeta();
if ( !newname.equals( originalName ) && DialogUtils.objectWithTheSameNameExists( databaseMeta,
hasDatabasesInterface.getDatabases() ) ) {
DatabaseDialog.showDatabaseExistsDialog( spoon.getShell(), databaseMeta );
return;
}
saveConnection( databaseMeta, Const.VERSION_COMMENT_EDIT_VERSION );
if ( databaseMeta.isShared() ) {
sharedObjectSyncUtil.synchronizeConnections( databaseMeta, originalName );
}
spoon.refreshTree();
}
spoon.setShellText();
}
private DatabaseDialog getDatabaseDialog() {
if ( databaseDialog != null ) {
return databaseDialog;
}
databaseDialog = new DatabaseDialog( spoon.getShell() );
return databaseDialog;
}
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 = BaseMessages.getString( PKG, "Spoon.Various.DupeName" ) + name;
databaseMetaCopy.setName( dupename );
getDatabaseDialog().setDatabaseMeta( databaseMetaCopy );
String newname = getDatabaseDialog().open();
if ( newname != null ) { // null: CANCEL
databaseMetaCopy.verifyAndModifyDatabaseName( hasDatabasesInterface.getDatabases(), name );
hasDatabasesInterface.addDatabase( pos + 1, databaseMetaCopy );
spoon.addUndoNew(
(UndoInterface) hasDatabasesInterface, new DatabaseMeta[] { (DatabaseMeta) databaseMetaCopy.clone() },
new int[] { pos + 1 } );
saveConnection( databaseMetaCopy, Const.VERSION_COMMENT_EDIT_VERSION );
spoon.refreshTree();
}
}
}
public void clipConnection( DatabaseMeta databaseMeta ) {
String xml = XMLHandler.getXMLHeader() + databaseMeta.getXML();
GUIResource.getInstance().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?
Repository rep = spoon.getRepository();
if ( rep != null ) {
if ( !rep.getSecurityProvider().isReadOnly() ) {
try {
rep.deleteDatabaseMeta( db.getName() );
worked = true;
} catch ( KettleException dbe ) {
new ErrorDialog( spoon.getShell(),
BaseMessages.getString( PKG, "Spoon.Dialog.ErrorDeletingConnection.Title" ),
BaseMessages.getString( PKG, "Spoon.Dialog.ErrorDeletingConnection.Message", db.getName() ), dbe );
}
} else {
new ErrorDialog( spoon.getShell(),
BaseMessages.getString( PKG, "Spoon.Dialog.ErrorDeletingConnection.Title" ),
BaseMessages.getString( PKG, "Spoon.Dialog.ErrorDeletingConnection.Message", db.getName() ),
new KettleException( BaseMessages.getString( PKG, "Spoon.Dialog.Exception.ReadOnlyUser" ) ) );
}
}
if ( spoon.getRepository() == null || worked ) {
spoon.addUndoDelete(
(UndoInterface) hasDatabasesInterface, new DatabaseMeta[] { (DatabaseMeta) db.clone() },
new int[] { pos } );
hasDatabasesInterface.removeDatabase( pos );
DBCache.getInstance().clear( db.getName() ); // remove this from the cache as well.
}
spoon.refreshTree();
spoon.setShellText();
}
/**
* return a schema, table combination from the explorer
*
* @param databaseMeta
* @param aLook
* @return schema [0] and table [1]
*/
public String[] exploreDB( DatabaseMeta databaseMeta, boolean aLook ) {
List<DatabaseMeta> databases = null;
HasDatabasesInterface activeHasDatabasesInterface = spoon.getActiveHasDatabasesInterface();
if ( activeHasDatabasesInterface != null ) {
databases = activeHasDatabasesInterface.getDatabases();
}
DatabaseExplorerDialog std =
new DatabaseExplorerDialog( spoon.getShell(), SWT.NONE, databaseMeta, databases, aLook );
std.open();
return new String[] { std.getSchemaName(), std.getTableName() };
}
public void clearDBCache( DatabaseMeta databaseMeta ) {
if ( databaseMeta != null ) {
DBCache.getInstance().clear( databaseMeta.getName() );
} else {
DBCache.getInstance().clear( null );
}
}
public void getSQL() {
TransMeta transMeta = spoon.getActiveTransformation();
if ( transMeta != null ) {
getTransSQL( transMeta );
}
JobMeta jobMeta = spoon.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( spoon.getShell(), transMeta );
List<SQLStatement> stats = pspd.open();
if ( stats != null ) {
// null means error, but we already displayed the error
if ( stats.size() > 0 ) {
SQLStatementsDialog ssd =
new SQLStatementsDialog( spoon.getShell(), Variables.getADefaultVariableSpace(), SWT.NONE, stats );
String sn = ssd.open();
if ( sn != null ) {
StepMeta esi = transMeta.findStep( sn );
if ( esi != null ) {
spoon.delegates.steps.editStep( transMeta, esi );
}
}
} else {
MessageBox mb = new MessageBox( spoon.getShell(), SWT.OK | SWT.ICON_INFORMATION );
mb.setMessage( BaseMessages.getString( PKG, "Spoon.Dialog.NoSQLNeedEexecuted.Message" ) );
mb.setText( BaseMessages.getString( PKG, "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( spoon.getShell(), jobMeta, spoon.getRepository() );
List<SQLStatement> stats = pspd.open();
if ( stats != null ) {
// null means error, but we already displayed the error
if ( stats.size() > 0 ) {
SQLStatementsDialog ssd = new SQLStatementsDialog( spoon.getShell(), jobMeta, SWT.NONE, stats );
ssd.open();
} else {
MessageBox mb = new MessageBox( spoon.getShell(), SWT.OK | SWT.ICON_INFORMATION );
mb.setMessage( BaseMessages.getString( PKG, "Spoon.Dialog.JobNoSQLNeedEexecuted.Message" ) );
mb.setText( BaseMessages.getString( PKG, "Spoon.Dialog.JobNoSQLNeedEexecuted.Title" ) );
mb.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 =
BaseMessages.getString( PKG, "Spoon.Message.Note.ReadInformationFromTableOnDB", tablename, sourceDBInfo
.getDatabaseName() )
+ Const.CR; // "Reads information from table ["+tablename+"]
// on database ["+sourceDBInfo+"]"
note +=
BaseMessages.getString( PKG, "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 = BaseMessages.getString( PKG, "Spoon.Message.Note.ReadFromTable", tablename ); // "read
// from
// ["+tablename+"]";
TableInputMeta tii = new TableInputMeta();
tii.setDatabaseMeta( sourceDBInfo );
tii.setSQL( "SELECT * FROM " + tablename );
PluginRegistry registry = PluginRegistry.getInstance();
String fromstepid = registry.getPluginId( StepPluginType.class, tii );
StepMeta fromstep = new StepMeta( fromstepid, fromstepname, tii );
fromstep.setLocation( 150, 100 );
fromstep.setDraw( true );
fromstep.setDescription( BaseMessages.getString(
PKG, "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( loggingObject, sourceDBInfo );
sourceDB.shareVariablesWith( meta );
sourceDB.connect();
try {
// Get the fields for the input table...
RowMetaInterface 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;
//CHECKSTYLE:Indentation:OFF
for ( int i = 0; i < fields.size(); i++ ) {
ValueMetaInterface v = fields.getValueMeta( i );
if ( targetDBInfo.isReservedWord( v.getName() ) ) {
if ( svi.getMeta()[nr] == null ) {
svi.getMeta()[nr] = new SelectMetadataChange( svi );
}
svi.getMeta()[nr].setName( v.getName() );
svi.getMeta()[nr].setRename( targetDBInfo.quoteField( v.getName() ) );
nr++;
}
}
String selstepname = BaseMessages.getString( PKG, "Spoon.Message.Note.HandleReservedWords" );
String selstepid = registry.getPluginId( StepPluginType.class, svi );
StepMeta selstep = new StepMeta( selstepid, selstepname, svi );
selstep.setLocation( 350, 100 );
selstep.setDraw( true );
selstep.setDescription( BaseMessages.getString(
PKG, "Spoon.Message.Note.RenamesReservedWords", targetDBInfo.getPluginId() ) ); //
meta.addStep( selstep );
TransHopMeta shi = new TransHopMeta( fromstep, selstep );
meta.addTransHop( shi );
fromstep = selstep;
}
//
// Create the target step...
//
//
// Add the TableOutputMeta step...
//
String tostepname = BaseMessages.getString( PKG, "Spoon.Message.Note.WriteToTable", tablename );
TableOutputMeta toi = new TableOutputMeta();
toi.setDatabaseMeta( targetDBInfo );
toi.setTableName( tablename );
toi.setCommitSize( 200 );
toi.setTruncateTable( true );
String tostepid = registry.getPluginId( StepPluginType.class, toi );
StepMeta tostep = new StepMeta( tostepid, tostepname, toi );
tostep.setLocation( 550, 100 );
tostep.setDraw( true );
tostep.setDescription( BaseMessages.getString(
PKG, "Spoon.Message.Note.WriteInformationToTableOnDB2", tablename, targetDBInfo.getDatabaseName() ) );
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 ( spoon.delegates.trans.getTransformation( transName ) != null ) {
nr++;
transName = name + " " + nr;
}
meta.setName( transName );
spoon.delegates.trans.addTransGraph( meta );
spoon.refreshGraph();
spoon.refreshTree();
} finally {
sourceDB.disconnect();
}
} catch ( Exception e ) {
new ErrorDialog(
spoon.getShell(), BaseMessages.getString( PKG, "Spoon.Dialog.UnexpectedError.Title" ), BaseMessages
.getString( PKG, "Spoon.Dialog.UnexpectedError.Message" ), new KettleException( e.getMessage(), e ) );
return false;
}
return true;
}
public void saveConnection( DatabaseMeta db, String versionComment ) {
// Also add to repository?
Repository rep = spoon.getRepository();
if ( rep != null ) {
if ( !rep.getSecurityProvider().isReadOnly() ) {
try {
if ( Utils.isEmpty( versionComment ) ) {
rep.insertLogEntry( "Saving database '" + db.getName() + "'" );
} else {
rep.insertLogEntry( "Save database : " + versionComment );
}
rep.save( db, versionComment, null );
spoon.getLog().logDetailed(
BaseMessages.getString( PKG, "Spoon.Log.SavedDatabaseConnection", db.getDatabaseName() ) );
db.setChanged( false );
} catch ( KettleException ke ) {
new ErrorDialog( spoon.getShell(),
BaseMessages.getString( PKG, "Spoon.Dialog.ErrorSavingConnection.Title" ),
BaseMessages.getString( PKG, "Spoon.Dialog.ErrorSavingConnection.Message", db.getDatabaseName() ), ke );
}
} else {
// This repository user is read-only!
//
new ErrorDialog(
spoon.getShell(), BaseMessages.getString( PKG, "Spoon.Dialog.UnableSave.Title" ), BaseMessages
.getString( PKG, "Spoon.Dialog.ErrorSavingConnection.Message", db.getDatabaseName() ),
new KettleException( BaseMessages.getString( PKG, "Spoon.Dialog.Exception.ReadOnlyRepositoryUser" ) ) );
}
}
}
public void newConnection() {
HasDatabasesInterface hasDatabasesInterface = spoon.getActiveHasDatabasesInterface();
if ( hasDatabasesInterface == null && spoon.rep == null ) {
return;
}
newConnection( hasDatabasesInterface );
}
public void newConnection( HasDatabasesInterface hasDatabasesInterface ) {
DatabaseMeta databaseMeta = new DatabaseMeta();
if ( hasDatabasesInterface instanceof VariableSpace ) {
databaseMeta.shareVariablesWith( (VariableSpace) hasDatabasesInterface );
} else {
databaseMeta.initializeVariablesFrom( null );
}
getDatabaseDialog().setDatabaseMeta( databaseMeta );
String con_name = getDatabaseDialog().open();
if ( !Utils.isEmpty( con_name ) ) {
databaseMeta = getDatabaseDialog().getDatabaseMeta();
if ( !DialogUtils.objectWithTheSameNameExists( databaseMeta,
hasDatabasesInterface.getDatabases() ) ) {
hasDatabasesInterface.addDatabase( databaseMeta );
spoon.addUndoNew( (UndoInterface) hasDatabasesInterface, new DatabaseMeta[]{(DatabaseMeta) databaseMeta
.clone()}, new int[]{hasDatabasesInterface.indexOfDatabase( databaseMeta )} );
if ( spoon.rep != null ) {
try {
if ( !spoon.rep.getSecurityProvider().isReadOnly() ) {
// spoon.rep.getDatabaseID( )
spoon.rep.save( databaseMeta, Const.VERSION_COMMENT_INITIAL_VERSION, null );
} else {
throw new KettleException( BaseMessages.getString(
PKG, "Spoon.Dialog.Exception.ReadOnlyRepositoryUser" ) );
}
} catch ( KettleException e ) {
new ErrorDialog( spoon.getShell(),
BaseMessages.getString( PKG, "Spoon.Dialog.ErrorSavingConnection.Title" ),
BaseMessages.getString( PKG, "Spoon.Dialog.ErrorSavingConnection.Message", databaseMeta.getName() ), e );
}
}
spoon.refreshTree();
} else {
DatabaseDialog.showDatabaseExistsDialog( spoon.getShell(), databaseMeta );
}
}
}
}