package rocks.inspectit.ui.rcp.ci.dialog; import java.util.ArrayList; import java.util.List; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import rocks.inspectit.shared.cs.ci.context.AbstractContextCapture; import rocks.inspectit.shared.cs.ci.context.impl.FieldContextCapture; import rocks.inspectit.shared.cs.ci.context.impl.ParameterContextCapture; import rocks.inspectit.shared.cs.ci.context.impl.ReturnContextCapture; import rocks.inspectit.ui.rcp.InspectIT; import rocks.inspectit.ui.rcp.InspectITImages; import rocks.inspectit.ui.rcp.validation.IControlValidationListener; import rocks.inspectit.ui.rcp.validation.ValidationControlDecoration; /** * Dialog for creating new {@link AbstractContextCapture}. * * @author Ivan Senic * */ public class CaptureContextDialog extends TitleAreaDialog implements IControlValidationListener { /** * Context capture being created. */ private AbstractContextCapture contextCapture; /** * All {@link ValidationControlDecoration}s. */ private List<ValidationControlDecoration<?>> validationControlDecorations = new ArrayList<>(); /** * Defined accessor paths. */ private List<String> paths = new ArrayList<>(); /** * Dialog OK button. */ private Button okButton; /** * Radio for return context type selection. */ private Button returnButton; /** * Radio for parameter context type selection. */ private Button parameterButton; /** * Radio for field context type selection. */ private Button fieldButton; /** * Text box for the name of the captured context. */ private Text nameText; /** * Text box for displaying accessor paths. */ private Text accessorText; /** * Button for adding new path. */ private Button addPath; /** * Button for clearing all path. */ private Button clearPaths; /** * Label for the index of parameter. */ private Label indexLabel; /** * Text box for the index of parameter. */ private Text indexText; /** * Label for the field name of field capture. */ private Label fieldLabel; /** * Text box for the field name of field capture. */ private Text fieldText; /** * Default constructor. * * @param parentShell * Shell. */ public CaptureContextDialog(Shell parentShell) { this(parentShell, null); } /** * Edit mode constructor. Data will be populated with the given {@link AbstractContextCapture}. * * @param parentShell * Shell. * @param contextCapture * context capture to edit */ public CaptureContextDialog(Shell parentShell, AbstractContextCapture contextCapture) { super(parentShell); this.contextCapture = contextCapture; } /** * {@inheritDoc} */ @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText("Add Context Capture"); } /** * {@inheritDoc} */ @Override public void create() { super.create(); this.setTitle("Add Context Capture"); this.setMessage("Define type of the context capturing", IMessageProvider.INFORMATION); } /** * {@inheritDoc} */ @Override protected void createButtonsForButtonBar(Composite parent) { createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CLOSE_LABEL, false); okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); okButton.setEnabled(null != contextCapture); } /** * {@inheritDoc} */ @Override protected void buttonPressed(int buttonId) { if (buttonId == IDialogConstants.OK_ID) { if (returnButton.getSelection()) { contextCapture = new ReturnContextCapture(); } else if (parameterButton.getSelection()) { ParameterContextCapture capture = new ParameterContextCapture(); capture.setIndex(Integer.parseInt(indexText.getText())); contextCapture = capture; } else if (fieldButton.getSelection()) { FieldContextCapture capture = new FieldContextCapture(); capture.setFieldName(fieldText.getText()); contextCapture = capture; } contextCapture.setDisplayName(nameText.getText()); if (CollectionUtils.isNotEmpty(paths)) { contextCapture.setPaths(paths); } } super.buttonPressed(buttonId); } /** * {@inheritDoc} */ @Override protected Control createDialogArea(Composite parent) { Composite main = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(5, false); layout.horizontalSpacing = 10; main.setLayout(layout); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); gd.minimumWidth = 400; gd.minimumHeight = 250; main.setLayoutData(gd); Label typeLabel = new Label(main, SWT.NONE); typeLabel.setText("Catch type:"); returnButton = new Button(main, SWT.RADIO); returnButton.setText("Return value"); returnButton.setImage(InspectIT.getDefault().getImage(InspectITImages.IMG_RETURN)); returnButton.setSelection((null == contextCapture) || (contextCapture instanceof ReturnContextCapture)); returnButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 3, 1)); createInfoLabel(main, "Select for capturing the return value."); new Label(main, SWT.NONE); parameterButton = new Button(main, SWT.RADIO); parameterButton.setText("Parameter"); parameterButton.setImage(InspectIT.getDefault().getImage(InspectITImages.IMG_PARAMETER)); parameterButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); parameterButton.setSelection(contextCapture instanceof ParameterContextCapture); indexLabel = new Label(main, SWT.RIGHT); indexLabel.setText("Index:"); indexLabel.setVisible(contextCapture instanceof ParameterContextCapture); indexLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); indexText = new Text(main, SWT.BORDER | SWT.RIGHT); indexText.setText("0"); indexText.setVisible(contextCapture instanceof ParameterContextCapture); indexText.setEnabled(contextCapture instanceof ParameterContextCapture); indexText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); final ValidationControlDecoration<Text> indexValidation = new ValidationControlDecoration<Text>(indexText, this) { @Override protected boolean validate(Text control) { try { return Integer.parseInt(control.getText()) >= 0; } catch (NumberFormatException e) { return false; } } }; indexValidation.setDescriptionText("Index must be a zero-positive index of parameter in a method."); indexValidation.registerListener(SWT.Modify); parameterButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { boolean selected = parameterButton.getSelection(); indexLabel.setVisible(selected); indexText.setVisible(selected); indexText.setEnabled(selected); indexText.setFocus(); indexText.setSelection(0, indexText.getText().length()); indexValidation.executeValidation(); } }); createInfoLabel(main, "Select for capturing the method parameter value. Specify the correct index of the parameter in the method."); new Label(main, SWT.NONE); fieldButton = new Button(main, SWT.RADIO); fieldButton.setText("Field"); fieldButton.setImage(InspectIT.getDefault().getImage(InspectITImages.IMG_FIELD)); fieldButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); fieldButton.setSelection(contextCapture instanceof FieldContextCapture); fieldLabel = new Label(main, SWT.RIGHT); fieldLabel.setText("Named:"); fieldLabel.setVisible(contextCapture instanceof FieldContextCapture); fieldLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); fieldText = new Text(main, SWT.BORDER | SWT.RIGHT); fieldText.setText("myField"); fieldText.setVisible(contextCapture instanceof FieldContextCapture); fieldText.setEnabled(contextCapture instanceof FieldContextCapture); fieldText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); final ValidationControlDecoration<Text> fieldValidation = new ValidationControlDecoration<Text>(fieldText, null, this) { @Override protected boolean validate(Text control) { return StringUtils.isNotBlank(control.getText()); } }; fieldValidation.setDescriptionText("Name of the field to capture must be defined"); fieldValidation.registerListener(SWT.Modify); fieldButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { boolean selected = fieldButton.getSelection(); fieldLabel.setVisible(selected); fieldText.setVisible(selected); fieldText.setEnabled(selected); fieldText.setFocus(); fieldText.setSelection(0, fieldText.getText().length()); fieldValidation.executeValidation(); } }); createInfoLabel(main, "Select for capturing the field value on the object executing the method. Specify the correct name of the object field."); Label nameLabel = new Label(main, SWT.NONE); nameLabel.setText("Display name:"); nameText = new Text(main, SWT.BORDER); nameText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 3, 1)); nameText.setFocus(); ValidationControlDecoration<Text> nameValidation = new ValidationControlDecoration<Text>(nameText, null, this) { @Override protected boolean validate(Text control) { return StringUtils.isNotBlank(control.getText()); } }; nameValidation.setDescriptionText("Display name for this context capture must be defined"); nameValidation.registerListener(SWT.Modify); createInfoLabel(main, "Display name defines how will the captured value be named."); Label accessorsLabel = new Label(main, SWT.NONE); accessorsLabel.setText("Accessor path:"); accessorText = new Text(main, SWT.BORDER | SWT.READ_ONLY); accessorText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); accessorText.addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { addPath.setFocus(); } }); addPath = new Button(main, SWT.PUSH); addPath.setText("Add Path"); addPath.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); addPath.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { InputDialog pathDialog = new InputDialog(getShell(), "Path to Follow", "Enter field name to navigate on the captured object:", "", null); if (pathDialog.open() == Window.OK) { String path = pathDialog.getValue(); if (StringUtils.isNotBlank(path)) { paths.add(path); updateAccessorText(); } } } }); clearPaths = new Button(main, SWT.PUSH); clearPaths.setText("Clear All Paths"); clearPaths.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); clearPaths.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { paths.clear(); updateAccessorText(); } }); createInfoLabel(main, "Specify path to follow on the captured object. For example, if object of type Customer is captured, and this object has a field named 'id', then you can save the 'id' value by creating a path '-> id'. "); validationControlDecorations.add(indexValidation); validationControlDecorations.add(fieldValidation); validationControlDecorations.add(nameValidation); if (null != contextCapture) { nameText.setText(contextCapture.getDisplayName()); if (CollectionUtils.isNotEmpty(contextCapture.getPaths())) { paths.addAll(contextCapture.getPaths()); updateAccessorText(); } if (contextCapture instanceof ParameterContextCapture) { indexText.setText(String.valueOf(((ParameterContextCapture) contextCapture).getIndex())); } else if (contextCapture instanceof FieldContextCapture) { fieldText.setText(((FieldContextCapture) contextCapture).getFieldName()); } } return main; } /** * Updates text in accessor text. */ private void updateAccessorText() { accessorText.setText(""); StringBuilder builder = new StringBuilder(); for (String path : paths) { builder.append(" -> "); builder.append(path); } accessorText.setText(builder.toString()); } /** * Gets {@link #contextCapture}. * * @return {@link #contextCapture} */ public AbstractContextCapture getContextCapture() { return contextCapture; } /** * {@inheritDoc} */ @Override public void validationStateChanged(boolean valid, ValidationControlDecoration<?> validationControlDecoration) { boolean allValid = true; for (ValidationControlDecoration<?> validation : validationControlDecorations) { if (!validation.isValid()) { allValid = false; break; } } if (null != okButton) { okButton.setEnabled(allValid); } } /** * Creates info icon with given text as tool-tip. * * @param parent * Composite to create on. * @param text * Information text. */ protected void createInfoLabel(Composite parent, String text) { Label label = new Label(parent, SWT.NONE); label.setToolTipText(text); label.setImage(InspectIT.getDefault().getImage(InspectITImages.IMG_INFORMATION)); } }