/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
package org.pentaho.di.ui.trans.steps.regexeval;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.util.Utils;
import org.pentaho.di.core.Props;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.steps.regexeval.RegexEvalMeta;
import org.pentaho.di.ui.core.PropsUI;
import org.pentaho.di.ui.core.gui.GUIResource;
import org.pentaho.di.ui.core.gui.WindowProperty;
import org.pentaho.di.ui.core.widget.StyledTextComp;
import org.pentaho.di.ui.trans.step.BaseStepDialog;
/**
* Dialog to test a regular expression
*
* @author Samatar
* @since 20-04-2009
*/
public class RegexEvalHelperDialog extends Dialog {
private static Class<?> PKG = RegexEvalMeta.class; // for i18n purposes, needed by Translator2!!
private Button wOK, wCancel;
private Listener lsOK, lsCancel;
private Shell shell;
private PropsUI props;
private String regexscript;
private String regexoptions;
private boolean canonicalEqualityFlagSet;
private TransMeta transmeta;
private CTabFolder wNoteFolder;
private FormData fdNoteFolder;
private CTabItem wNoteContentTab;
private FormData fdNoteContentComp;
private Label wlRegExScript;
private StyledTextComp wRegExScript;
private FormData fdlRegExScript, fdRegExScript;
private Label wlValue1;
private Text wValue1;
private FormData fdlValue1, fdValue1;
private Label wlValue2;
private Text wValue2;
private FormData fdlValue2, fdValue2;
private Label wlValue3;
private Text wValue3;
private FormData fdlValue3, fdValue3;
private Group wValuesGroup;
private FormData fdValuesGroup;
private Group wCaptureGroups;
private FormData fdCaptureGroups;
private Text wRegExScriptCompile;
private FormData fdRegExScriptCompile;
private List wGroups;
private FormData fdGroups;
private Label wlGroups;
private FormData fdlGroups;
private Label wlValueGroup;
private Text wValueGroup;
private FormData fdlValueGroup, fdValueGroup;
GUIResource guiresource = GUIResource.getInstance();
private boolean errorDisplayed;
/**
* Dialog to allow someone to test regular expression
*
* @param parent
* The parent shell to use
* @param RegexScript
* The expression to test
* @param RegexOptions
* Any extended options for the regular expression
* @param canonicalEqualityFlagSet
*/
public RegexEvalHelperDialog( Shell parent, TransMeta transmeta, String RegexScript, String RegexOptions,
boolean canonicalEqualityFlagSet ) {
super( parent, SWT.NONE );
props = PropsUI.getInstance();
this.regexscript = RegexScript;
this.regexoptions = RegexOptions;
this.transmeta = transmeta;
this.errorDisplayed = false;
this.canonicalEqualityFlagSet = canonicalEqualityFlagSet;
}
private boolean isCanonicalEqualityFlagSet() {
return this.canonicalEqualityFlagSet;
}
public String open() {
Shell parent = getParent();
Display display = parent.getDisplay();
shell = new Shell( parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN | SWT.NONE );
props.setLook( shell );
shell.setImage( guiresource.getImageSpoon() );
FormLayout formLayout = new FormLayout();
formLayout.marginWidth = Const.FORM_MARGIN;
formLayout.marginHeight = Const.FORM_MARGIN;
shell.setLayout( formLayout );
shell.setText( BaseMessages.getString( PKG, "RegexEvalHelperDialog.Shell.Label" ) );
int margin = Const.MARGIN;
int middle = 30;
wNoteFolder = new CTabFolder( shell, SWT.BORDER );
props.setLook( wNoteFolder, Props.WIDGET_STYLE_TAB );
// ////////////////////////
// START OF NOTE CONTENT TAB///
// /
wNoteContentTab = new CTabItem( wNoteFolder, SWT.NONE );
wNoteContentTab.setText( BaseMessages.getString( PKG, "RegexEvalHelperDialog.RegExTab.Label" ) );
Composite wNoteContentComp = new Composite( wNoteFolder, SWT.NONE );
props.setLook( wNoteContentComp );
FormLayout fileLayout = new FormLayout();
fileLayout.marginWidth = 3;
fileLayout.marginHeight = 3;
wNoteContentComp.setLayout( fileLayout );
// RegEx Script
wlRegExScript = new Label( wNoteContentComp, SWT.RIGHT );
wlRegExScript.setText( BaseMessages.getString( PKG, "RegexEvalHelperDialog.Script.Label" ) );
props.setLook( wlRegExScript );
fdlRegExScript = new FormData();
fdlRegExScript.left = new FormAttachment( 0, 0 );
fdlRegExScript.top = new FormAttachment( 0, 2 * margin );
wlRegExScript.setLayoutData( fdlRegExScript );
wRegExScript =
new StyledTextComp( transmeta, wNoteContentComp, SWT.MULTI
| SWT.LEFT | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL, "" );
wRegExScript.setText( "" );
props.setLook( wRegExScript, Props.WIDGET_STYLE_FIXED );
props.setLook( wRegExScript );
fdRegExScript = new FormData();
fdRegExScript.left = new FormAttachment( 0, 0 );
fdRegExScript.top = new FormAttachment( wlRegExScript, 2 * margin );
fdRegExScript.right = new FormAttachment( 100, -2 * margin );
fdRegExScript.bottom = new FormAttachment( 40, -margin );
wRegExScript.setLayoutData( fdRegExScript );
wRegExScriptCompile = new Text( wNoteContentComp, SWT.MULTI | SWT.LEFT | SWT.BORDER | SWT.V_SCROLL );
wRegExScriptCompile.setText( "" );
props.setLook( wRegExScriptCompile, Props.WIDGET_STYLE_FIXED );
fdRegExScriptCompile = new FormData();
fdRegExScriptCompile.left = new FormAttachment( 0, 0 );
fdRegExScriptCompile.top = new FormAttachment( wRegExScript, margin );
fdRegExScriptCompile.right = new FormAttachment( 100, 0 );
wRegExScriptCompile.setLayoutData( fdRegExScriptCompile );
wRegExScriptCompile.setEditable( false );
wRegExScriptCompile.setFont( guiresource.getFontNote() );
// ////////////////////////
// START OF Values GROUP
//
wValuesGroup = new Group( wNoteContentComp, SWT.SHADOW_NONE );
props.setLook( wValuesGroup );
wValuesGroup.setText( BaseMessages.getString( PKG, "RegexEvalHelperDialog.TestValues.Label" ) );
FormLayout groupLayout = new FormLayout();
groupLayout.marginWidth = 10;
groupLayout.marginHeight = 10;
wValuesGroup.setLayout( groupLayout );
// Value1
wlValue1 = new Label( wValuesGroup, SWT.RIGHT );
wlValue1.setText( BaseMessages.getString( PKG, "RegexEvalHelperDialog.Value1.Label" ) );
props.setLook( wlValue1 );
fdlValue1 = new FormData();
fdlValue1.left = new FormAttachment( 0, 0 );
fdlValue1.top = new FormAttachment( wRegExScriptCompile, margin );
fdlValue1.right = new FormAttachment( middle, -margin );
wlValue1.setLayoutData( fdlValue1 );
wValue1 = new Text( wValuesGroup, SWT.SINGLE | SWT.LEFT | SWT.BORDER );
props.setLook( wValue1 );
fdValue1 = new FormData();
fdValue1.left = new FormAttachment( middle, margin );
fdValue1.top = new FormAttachment( wRegExScriptCompile, margin );
fdValue1.right = new FormAttachment( 100, -margin );
wValue1.setLayoutData( fdValue1 );
// Value2
wlValue2 = new Label( wValuesGroup, SWT.RIGHT );
wlValue2.setText( BaseMessages.getString( PKG, "RegexEvalHelperDialog.Value2.Label" ) );
props.setLook( wlValue2 );
fdlValue2 = new FormData();
fdlValue2.left = new FormAttachment( 0, 0 );
fdlValue2.top = new FormAttachment( wValue1, margin );
fdlValue2.right = new FormAttachment( middle, -margin );
wlValue2.setLayoutData( fdlValue2 );
wValue2 = new Text( wValuesGroup, SWT.SINGLE | SWT.LEFT | SWT.BORDER );
props.setLook( wValue2 );
fdValue2 = new FormData();
fdValue2.left = new FormAttachment( middle, margin );
fdValue2.top = new FormAttachment( wValue1, margin );
fdValue2.right = new FormAttachment( 100, -margin );
wValue2.setLayoutData( fdValue2 );
// Value3
wlValue3 = new Label( wValuesGroup, SWT.RIGHT );
wlValue3.setText( BaseMessages.getString( PKG, "RegexEvalHelperDialog.Value3.Label" ) );
props.setLook( wlValue3 );
fdlValue3 = new FormData();
fdlValue3.left = new FormAttachment( 0, 0 );
fdlValue3.top = new FormAttachment( wValue2, margin );
fdlValue3.right = new FormAttachment( middle, -margin );
wlValue3.setLayoutData( fdlValue3 );
wValue3 = new Text( wValuesGroup, SWT.SINGLE | SWT.LEFT | SWT.BORDER );
props.setLook( wValue3 );
fdValue3 = new FormData();
fdValue3.left = new FormAttachment( middle, margin );
fdValue3.top = new FormAttachment( wValue2, margin );
fdValue3.right = new FormAttachment( 100, -margin );
wValue3.setLayoutData( fdValue3 );
fdValuesGroup = new FormData();
fdValuesGroup.left = new FormAttachment( 0, margin );
fdValuesGroup.top = new FormAttachment( wRegExScriptCompile, margin );
fdValuesGroup.right = new FormAttachment( 100, -margin );
wValuesGroup.setLayoutData( fdValuesGroup );
// ///////////////////////////////////////////////////////////
// / END OF VALUEs GROUP
// ////////////////////////
// START OF Values GROUP
//
wCaptureGroups = new Group( wNoteContentComp, SWT.SHADOW_NONE );
props.setLook( wCaptureGroups );
wCaptureGroups.setText( "Capture" );
FormLayout captureLayout = new FormLayout();
captureLayout.marginWidth = 10;
captureLayout.marginHeight = 10;
wCaptureGroups.setLayout( captureLayout );
// ValueGroup
wlValueGroup = new Label( wCaptureGroups, SWT.RIGHT );
wlValueGroup.setText( BaseMessages.getString( PKG, "RegexEvalHelperDialog.ValueGroup.Label" ) );
props.setLook( wlValueGroup );
fdlValueGroup = new FormData();
fdlValueGroup.left = new FormAttachment( 0, 0 );
fdlValueGroup.top = new FormAttachment( wValuesGroup, margin );
fdlValueGroup.right = new FormAttachment( middle, -margin );
wlValueGroup.setLayoutData( fdlValueGroup );
wValueGroup = new Text( wCaptureGroups, SWT.SINGLE | SWT.LEFT | SWT.BORDER );
props.setLook( wValueGroup );
fdValueGroup = new FormData();
fdValueGroup.left = new FormAttachment( middle, margin );
fdValueGroup.top = new FormAttachment( wValuesGroup, margin );
fdValueGroup.right = new FormAttachment( 100, -margin );
wValueGroup.setLayoutData( fdValueGroup );
wlGroups = new Label( wCaptureGroups, SWT.RIGHT );
wlGroups.setText( BaseMessages.getString( PKG, "RegexEvalHelperDialog.GroupFields.Label" ) );
props.setLook( wlGroups );
fdlGroups = new FormData();
fdlGroups.left = new FormAttachment( 0, 0 );
fdlGroups.top = new FormAttachment( wValueGroup, margin );
fdlGroups.right = new FormAttachment( middle, -margin );
wlGroups.setLayoutData( fdlGroups );
wGroups = new List( wCaptureGroups, SWT.LEFT | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE );
props.setLook( wValue3 );
fdGroups = new FormData();
fdGroups.left = new FormAttachment( middle, margin );
fdGroups.top = new FormAttachment( wValueGroup, margin );
fdGroups.right = new FormAttachment( 100, -margin );
fdGroups.bottom = new FormAttachment( 100, -margin );
wGroups.setLayoutData( fdGroups );
fdCaptureGroups = new FormData();
fdCaptureGroups.left = new FormAttachment( 0, margin );
fdCaptureGroups.top = new FormAttachment( wValuesGroup, margin );
fdCaptureGroups.right = new FormAttachment( 100, -margin );
fdCaptureGroups.bottom = new FormAttachment( 100, -margin );
wCaptureGroups.setLayoutData( fdCaptureGroups );
// ///////////////////////////////////////////////////////////
// / END OF VALUEs GROUP
// ///////////////////////////////////////////////////////////
fdNoteContentComp = new FormData();
fdNoteContentComp.left = new FormAttachment( 0, 0 );
fdNoteContentComp.top = new FormAttachment( 0, 0 );
fdNoteContentComp.right = new FormAttachment( 100, 0 );
fdNoteContentComp.bottom = new FormAttachment( 100, 0 );
wNoteContentComp.setLayoutData( fdNoteContentComp );
wNoteContentComp.layout();
wNoteContentTab.setControl( wNoteContentComp );
// ///////////////////////////////////////////////////////////
// / END OF NOTE CONTENT TAB
// ///////////////////////////////////////////////////////////
// ////////////////////////
fdNoteFolder = new FormData();
fdNoteFolder.left = new FormAttachment( 0, 0 );
fdNoteFolder.top = new FormAttachment( 0, margin );
fdNoteFolder.right = new FormAttachment( 100, 0 );
fdNoteFolder.bottom = new FormAttachment( 100, -50 );
wNoteFolder.setLayoutData( fdNoteFolder );
// Some buttons
wOK = new Button( shell, SWT.PUSH );
wOK.setText( BaseMessages.getString( PKG, "System.Button.OK" ) );
wCancel = new Button( shell, SWT.PUSH );
wCancel.setText( BaseMessages.getString( PKG, "System.Button.Cancel" ) );
BaseStepDialog.positionBottomButtons( shell, new Button[] { wOK, wCancel }, margin, wNoteFolder );
// Add listeners
lsOK = new Listener() {
public void handleEvent( Event e ) {
ok();
}
};
lsCancel = new Listener() {
public void handleEvent( Event e ) {
cancel();
}
};
wOK.addListener( SWT.Selection, lsOK );
wCancel.addListener( SWT.Selection, lsCancel );
wValue1.addModifyListener( new ModifyListener() {
public void modifyText( ModifyEvent e ) {
testValue( 1, true, null );
}
} );
wValue2.addModifyListener( new ModifyListener() {
public void modifyText( ModifyEvent e ) {
testValue( 2, true, null );
}
} );
wValue3.addModifyListener( new ModifyListener() {
public void modifyText( ModifyEvent e ) {
testValue( 3, true, null );
}
} );
wValueGroup.addModifyListener( new ModifyListener() {
public void modifyText( ModifyEvent e ) {
testValue( 4, true, null );
}
} );
wRegExScript.addModifyListener( new ModifyListener() {
public void modifyText( ModifyEvent e ) {
errorDisplayed = false;
testValues();
}
} );
// 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();
while ( !shell.isDisposed() ) {
if ( !display.readAndDispatch() ) {
display.sleep();
}
}
return regexscript;
}
private void testValues() {
String realScript = transmeta.environmentSubstitute( wRegExScript.getText() );
for ( int i = 1; i < 5; i++ ) {
testValue( i, false, realScript );
}
}
private void testValue( int index, boolean testRegEx, String regExString ) {
String realScript = regExString;
if ( realScript == null ) {
realScript = transmeta.environmentSubstitute( wRegExScript.getText() );
}
if ( Utils.isEmpty( realScript ) ) {
if ( testRegEx ) {
MessageBox mb = new MessageBox( shell, SWT.OK | SWT.ICON_ERROR );
mb.setMessage( BaseMessages.getString( PKG, "RegexEvalHelperDialog.EnterScript.Message" ) );
mb.setText( BaseMessages.getString( PKG, "RegexEvalHelperDialog.EnterScript.Title" ) );
mb.open();
}
return;
}
String realValue = null;
Text control = null;
switch ( index ) {
case 1:
realValue = Const.NVL( transmeta.environmentSubstitute( wValue1.getText() ), "" );
control = wValue1;
break;
case 2:
realValue = Const.NVL( transmeta.environmentSubstitute( wValue2.getText() ), "" );
control = wValue2;
break;
case 3:
realValue = Const.NVL( transmeta.environmentSubstitute( wValue3.getText() ), "" );
control = wValue3;
break;
case 4:
realValue = Const.NVL( transmeta.environmentSubstitute( wValueGroup.getText() ), "" );
control = wValueGroup;
break;
default:
break;
}
try {
Pattern p;
if ( isCanonicalEqualityFlagSet() ) {
p = Pattern.compile( regexoptions + realScript, Pattern.CANON_EQ );
} else {
p = Pattern.compile( regexoptions + realScript );
}
Matcher m = p.matcher( realValue );
boolean ismatch = m.matches();
if ( ismatch ) {
control.setBackground( guiresource.getColorGreen() );
} else {
control.setBackground( guiresource.getColorRed() );
}
if ( index == 4 ) {
wGroups.removeAll();
int nrFields = m.groupCount();
int nr = 0;
for ( int i = 1; i <= nrFields; i++ ) {
if ( m.group( i ) == null ) {
wGroups.add( "" );
} else {
wGroups.add( m.group( i ) );
}
nr++;
}
wlGroups.setText( BaseMessages.getString( PKG, "RegexEvalHelperDialog.FieldsGroup", nr ) );
}
wRegExScriptCompile.setForeground( guiresource.getColorBlue() );
wRegExScriptCompile.setText( BaseMessages
.getString( PKG, "RegexEvalHelperDialog.ScriptSuccessfullyCompiled" ) );
wRegExScriptCompile.setToolTipText( "" );
} catch ( Exception e ) {
if ( !errorDisplayed ) {
wRegExScriptCompile.setForeground( guiresource.getColorRed() );
wRegExScriptCompile.setText( e.getMessage() );
wRegExScriptCompile.setToolTipText( BaseMessages.getString(
PKG, "RegexEvalHelperDialog.ErrorCompiling.Message" )
+ Const.CR + e.toString() );
this.errorDisplayed = true;
}
}
}
public void dispose() {
props.setScreen( new WindowProperty( shell ) );
shell.dispose();
}
public void getData() {
if ( regexscript != null ) {
wRegExScript.setText( regexscript );
}
}
private void cancel() {
dispose();
}
private void ok() {
if ( wRegExScript.getText() != null ) {
regexscript = wRegExScript.getText();
}
dispose();
}
}