/*! ****************************************************************************** * * 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.partition.dialog; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Dialog; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.pentaho.di.core.Const; import org.pentaho.di.core.database.DatabaseMeta; import org.pentaho.di.core.database.PartitionDatabaseMeta; import org.pentaho.di.core.variables.VariableSpace; import org.pentaho.di.core.variables.Variables; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.partition.PartitionSchema; import org.pentaho.di.ui.core.PropsUI; import org.pentaho.di.ui.core.dialog.EnterSelectionDialog; import org.pentaho.di.ui.core.gui.GUIResource; import org.pentaho.di.ui.core.gui.WindowProperty; import org.pentaho.di.ui.core.widget.ColumnInfo; import org.pentaho.di.ui.core.widget.TableView; import org.pentaho.di.ui.core.widget.TextVar; import org.pentaho.di.ui.trans.step.BaseStepDialog; import org.pentaho.di.ui.util.DialogUtils; /** * * Dialog that allows you to edit the settings of the partition schema * * @see PartitionSchema * @author Matt * @since 17-11-2006 * */ public class PartitionSchemaDialog extends Dialog { private static Class<?> PKG = PartitionSchemaDialog.class; // for i18n purposes, needed by Translator2!! private PartitionSchema partitionSchema; private Collection<PartitionSchema> existingSchemas; private Shell shell; // Name private Text wName; // Dynamic definition? private Button wDynamic; private TextVar wNumber; // Partitions private TableView wPartitions; private Button wOK, wGet, wCancel; private ModifyListener lsMod; private PropsUI props; private int middle; private int margin; private PartitionSchema originalSchema; private boolean ok; private List<DatabaseMeta> databases; private VariableSpace variableSpace; public PartitionSchemaDialog( Shell par, PartitionSchema partitionSchema, Collection<PartitionSchema> existingSchemas, List<DatabaseMeta> databases, VariableSpace variableSpace ) { super( par, SWT.NONE ); this.partitionSchema = (PartitionSchema) partitionSchema.clone(); this.originalSchema = partitionSchema; this.existingSchemas = existingSchemas; this.databases = databases; this.variableSpace = variableSpace; props = PropsUI.getInstance(); ok = false; } public PartitionSchemaDialog( Shell par, PartitionSchema partitionSchema, List<DatabaseMeta> databases, VariableSpace variableSpace ) { this( par, partitionSchema, Collections.<PartitionSchema>emptyList(), databases, variableSpace ); } public boolean open() { Shell parent = getParent(); shell = new Shell( parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN ); props.setLook( shell ); shell.setImage( GUIResource.getInstance().getImageSpoon() ); lsMod = new ModifyListener() { public void modifyText( ModifyEvent e ) { partitionSchema.setChanged(); } }; middle = props.getMiddlePct(); margin = Const.MARGIN; FormLayout formLayout = new FormLayout(); formLayout.marginWidth = Const.FORM_MARGIN; formLayout.marginHeight = Const.FORM_MARGIN; shell.setText( BaseMessages.getString( PKG, "PartitionSchemaDialog.Shell.Title" ) ); shell.setLayout( formLayout ); // First, add the buttons... // Buttons wOK = new Button( shell, SWT.PUSH ); wOK.setText( " &OK " ); wGet = new Button( shell, SWT.PUSH ); wGet.setText( BaseMessages.getString( PKG, "PartitionSchema.ImportPartitions" ) ); wCancel = new Button( shell, SWT.PUSH ); wCancel.setText( " &Cancel " ); Button[] buttons = new Button[] { wOK, wGet, wCancel }; BaseStepDialog.positionBottomButtons( shell, buttons, margin, null ); // The rest stays above the buttons, so we added those first... // What's the schema name?? // Label wlName = new Label( shell, SWT.RIGHT ); props.setLook( wlName ); wlName.setText( BaseMessages.getString( PKG, "PartitionSchemaDialog.PartitionName.Label" ) ); FormData fdlName = new FormData(); fdlName.top = new FormAttachment( 0, 0 ); fdlName.left = new FormAttachment( 0, 0 ); // First one in the left top corner fdlName.right = new FormAttachment( middle, 0 ); wlName.setLayoutData( fdlName ); wName = new Text( shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER ); props.setLook( wName ); wName.addModifyListener( lsMod ); FormData fdName = new FormData(); fdName.top = new FormAttachment( 0, 0 ); fdName.left = new FormAttachment( middle, margin ); // To the right of the label fdName.right = new FormAttachment( 95, 0 ); wName.setLayoutData( fdName ); // is the schema defined dynamically using the number of slave servers in the used cluster. // Label wlDynamic = new Label( shell, SWT.RIGHT ); props.setLook( wlDynamic ); wlDynamic.setText( BaseMessages.getString( PKG, "PartitionSchemaDialog.Dynamic.Label" ) ); FormData fdlDynamic = new FormData(); fdlDynamic.top = new FormAttachment( wName, margin ); fdlDynamic.left = new FormAttachment( 0, 0 ); // First one in the left top corner fdlDynamic.right = new FormAttachment( middle, 0 ); wlDynamic.setLayoutData( fdlDynamic ); wDynamic = new Button( shell, SWT.CHECK ); props.setLook( wDynamic ); wDynamic.setToolTipText( BaseMessages.getString( PKG, "PartitionSchemaDialog.Dynamic.Tooltip" ) ); FormData fdDynamic = new FormData(); fdDynamic.top = new FormAttachment( wName, margin ); fdDynamic.left = new FormAttachment( middle, margin ); // To the right of the label fdDynamic.right = new FormAttachment( 95, 0 ); wDynamic.setLayoutData( fdDynamic ); // The number of partitions per cluster schema // Label wlNumber = new Label( shell, SWT.RIGHT ); props.setLook( wlNumber ); wlNumber.setText( BaseMessages.getString( PKG, "PartitionSchemaDialog.Number.Label" ) ); FormData fdlNumber = new FormData(); fdlNumber.top = new FormAttachment( wDynamic, margin ); fdlNumber.left = new FormAttachment( 0, 0 ); // First one in the left top corner fdlNumber.right = new FormAttachment( middle, 0 ); wlNumber.setLayoutData( fdlNumber ); wNumber = new TextVar( variableSpace, shell, SWT.LEFT | SWT.BORDER | SWT.SINGLE, BaseMessages.getString( PKG, "PartitionSchemaDialog.Number.Tooltip" ) ); props.setLook( wNumber ); FormData fdNumber = new FormData(); fdNumber.top = new FormAttachment( wDynamic, margin ); fdNumber.left = new FormAttachment( middle, margin ); // To the right of the label fdNumber.right = new FormAttachment( 95, 0 ); wNumber.setLayoutData( fdNumber ); // Schema list: Label wlPartitions = new Label( shell, SWT.RIGHT ); wlPartitions.setText( BaseMessages.getString( PKG, "PartitionSchemaDialog.Partitions.Label" ) ); props.setLook( wlPartitions ); FormData fdlPartitions = new FormData(); fdlPartitions.left = new FormAttachment( 0, 0 ); fdlPartitions.right = new FormAttachment( middle, 0 ); fdlPartitions.top = new FormAttachment( wNumber, margin ); wlPartitions.setLayoutData( fdlPartitions ); ColumnInfo[] partitionColumns = new ColumnInfo[] { new ColumnInfo( BaseMessages.getString( PKG, "PartitionSchemaDialog.PartitionID.Label" ), ColumnInfo.COLUMN_TYPE_TEXT, false, false ), }; wPartitions = new TableView( Variables.getADefaultVariableSpace(), // probably better push this up. TODO shell, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI, partitionColumns, 1, lsMod, props ); props.setLook( wPartitions ); FormData fdPartitions = new FormData(); fdPartitions.left = new FormAttachment( middle, margin ); fdPartitions.right = new FormAttachment( 100, 0 ); fdPartitions.top = new FormAttachment( wNumber, margin ); fdPartitions.bottom = new FormAttachment( wOK, -margin * 2 ); wPartitions.setLayoutData( fdPartitions ); // Add listeners wOK.addListener( SWT.Selection, new Listener() { public void handleEvent( Event e ) { ok(); } } ); wGet.addListener( SWT.Selection, new Listener() { public void handleEvent( Event e ) { importPartitions(); } } ); wCancel.addListener( SWT.Selection, new Listener() { public void handleEvent( Event e ) { cancel(); } } ); SelectionAdapter selAdapter = new SelectionAdapter() { public void widgetDefaultSelected( SelectionEvent e ) { ok(); } }; wName.addSelectionListener( selAdapter ); // Detect X or ALT-F4 or something that kills this window... shell.addShellListener( new ShellAdapter() { public void shellClosed( ShellEvent e ) { cancel(); } } ); getData(); BaseStepDialog.setSize( shell ); shell.open(); Display display = parent.getDisplay(); while ( !shell.isDisposed() ) { if ( !display.readAndDispatch() ) { display.sleep(); } } return ok; } public void dispose() { props.setScreen( new WindowProperty( shell ) ); shell.dispose(); } public void getData() { wName.setText( Const.NVL( partitionSchema.getName(), "" ) ); refreshPartitions(); wDynamic.setSelection( partitionSchema.isDynamicallyDefined() ); wNumber.setText( Const.NVL( partitionSchema.getNumberOfPartitionsPerSlave(), "" ) ); wName.setFocus(); } private void refreshPartitions() { wPartitions.clearAll( false ); List<String> partitionIDs = partitionSchema.getPartitionIDs(); for ( int i = 0; i < partitionIDs.size(); i++ ) { TableItem item = new TableItem( wPartitions.table, SWT.NONE ); item.setText( 1, partitionIDs.get( i ) ); } wPartitions.removeEmptyRows(); wPartitions.setRowNums(); wPartitions.optWidth( true ); } private void cancel() { originalSchema = null; dispose(); } public void ok() { getInfo(); if ( !partitionSchema.getName().equals( originalSchema.getName() ) ) { if ( DialogUtils.objectWithTheSameNameExists( partitionSchema, existingSchemas ) ) { String title = BaseMessages.getString( PKG, "PartitionSchemaDialog.PartitionSchemaNameExists.Title" ); String message = BaseMessages.getString( PKG, "PartitionSchemaDialog.PartitionSchemaNameExists", partitionSchema.getName() ); String okButton = BaseMessages.getString( PKG, "System.Button.OK" ); MessageDialog dialog = new MessageDialog( shell, title, null, message, MessageDialog.ERROR, new String[] { okButton }, 0 ); dialog.open(); return; } } originalSchema.setName( partitionSchema.getName() ); originalSchema.setPartitionIDs( partitionSchema.getPartitionIDs() ); originalSchema.setDynamicallyDefined( wDynamic.getSelection() ); originalSchema.setNumberOfPartitionsPerSlave( wNumber.getText() ); originalSchema.setChanged(); ok = true; dispose(); } // Get dialog info in partition schema meta-data // private void getInfo() { partitionSchema.setName( wName.getText() ); List<String> parts = new ArrayList<String>(); int nrNonEmptyPartitions = wPartitions.nrNonEmpty(); for ( int i = 0; i < nrNonEmptyPartitions; i++ ) { parts.add( wPartitions.getNonEmpty( i ).getText( 1 ) ); } partitionSchema.setPartitionIDs( parts ); } protected void importPartitions() { List<String> partitionedDatabaseNames = new ArrayList<String>(); for ( int i = 0; i < databases.size(); i++ ) { DatabaseMeta databaseMeta = databases.get( i ); if ( databaseMeta.isPartitioned() ) { partitionedDatabaseNames.add( databaseMeta.getName() ); } } String[] dbNames = partitionedDatabaseNames.toArray( new String[partitionedDatabaseNames.size()] ); if ( dbNames.length > 0 ) { EnterSelectionDialog dialog = new EnterSelectionDialog( shell, dbNames, BaseMessages.getString( PKG, "PartitionSchema.SelectDatabase" ), BaseMessages .getString( PKG, "PartitionSchema.SelectPartitionnedDatabase" ) ); String dbName = dialog.open(); if ( dbName != null ) { DatabaseMeta databaseMeta = DatabaseMeta.findDatabase( databases, dbName ); PartitionDatabaseMeta[] partitioningInformation = databaseMeta.getPartitioningInformation(); if ( partitioningInformation != null ) { // Here we are... wPartitions.clearAll( false ); for ( int i = 0; i < partitioningInformation.length; i++ ) { PartitionDatabaseMeta meta = partitioningInformation[i]; wPartitions.add( new String[] { meta.getPartitionId() } ); } wPartitions.removeEmptyRows(); wPartitions.setRowNums(); wPartitions.optWidth( true ); } } } } }