InstantiationResultsDialog.java
package org.osate.ui.internal.instantiate;
import java.io.IOException;
import java.util.Map;
import java.util.function.Function;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPersistentPreferenceStore;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.osate.core.OsateCorePlugin;
/* TODO: I don't like that this class depends on AbstractMultiJobHandler.Result. The dialog sholdn't have
* dependencies on a UI handler. The result class either needs to be moved somewhere else, or this
* class needs to be made sufficiently abstract that the implementation doesn't care about that class
* specifically.
*/
/**
* @since 3.0
*/
final class InstantiationResultsDialog<T> extends Dialog {
private final String actionName;
private final String labelName;
private final Model<T> model;
private final IPreferenceStore prefs;
private boolean hideInFutureOriginal;
private boolean hideInFuture;
/**
* @since 4.0
*/
public InstantiationResultsDialog(final Shell shell, final String actionName, final String labelName,
final Function<T, String> labelProvider, final Map<T, InternalJobResult> results,
final IPreferenceStore prefs) {
super(shell);
setShellStyle(getShellStyle() | SWT.RESIZE);
this.actionName = actionName;
this.labelName = labelName;
this.model = new Model<T>(actionName, labelProvider, results);
this.prefs = prefs;
}
private static String toFirstUpperCase(final String input) {
return input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase();
}
private static final class Model<T> {
private final String message;
private final Integer[] elements;
private final String[] name;
private final String[] status;
private final String[] errorMessage;
private String buildMessage(final String actionName, final boolean allGood, final boolean cancelled,
final boolean errs,
final boolean logged) {
final StringBuilder sb = new StringBuilder();
if (allGood) {
sb.append("All models created successfully.");
} else {
if (cancelled) {
sb.append(toFirstUpperCase(actionName));
sb.append(" cancelled. ");
}
if (errs) {
if (logged) {
sb.append("Errors and exceptions during ");
sb.append(actionName.toLowerCase());
sb.append(". Please open the \"Error Log\" view.");
} else {
sb.append("Errors during ");
sb.append(actionName.toLowerCase());
}
} else if (logged) {
sb.append("Exceptions during ");
sb.append(actionName.toLowerCase());
sb.append(". Please open the \"Error Log\" view.");
}
}
return sb.toString();
}
public Model(final String actionName, final Function<T, String> labelProvider,
final Map<T, InternalJobResult> results) {
final int size = results.size();
elements = new Integer[size];
for (int i = 0; i < size; i++) {
elements[i] = Integer.valueOf(i);
}
name = new String[size];
status = new String[size];
errorMessage = new String[size];
boolean allGood = true;
boolean cancelled = false;
boolean errors = false;
boolean logged = false;
int i = 0;
for (final Map.Entry<T, InternalJobResult> entry : results.entrySet()) {
final InternalJobResult current = entry.getValue();
name[i] = labelProvider.apply(entry.getKey());
if (current.successful) {
status[i] = "OK";
} else {
allGood = false;
if (current.cancelled) {
cancelled = false;
status[i] = "Cancelled";
} else {
// Cannot have error message or exceptions if cancelled
if (current.errorMessage != null) {
errors = true;
status[i] = "Error";
errorMessage[i] = current.errorMessage;
} else if (current.exception != null) {
logged = true;
final Exception e = current.exception;
/*
* NB. Inherited these specific exception checks from the original
* InstantiateHandler (now obsolete).
*/
status[i] = "Exception";
if (e instanceof UnsupportedOperationException) {
errorMessage[i] = "Operation not supported: " + e.getMessage();
} else {
errorMessage[i] = e.getClass().getCanonicalName();
}
}
}
}
i += 1;
}
message = buildMessage(actionName, allGood, cancelled, errors, logged);
}
public String getMessage() {
return message;
}
public Integer[] getElements() {
return elements;
}
public String getName(final int idx) {
return name[idx];
}
public String getStatus(final int idx) {
return status[idx];
}
public String getErrorMessage(final int idx) {
final String errMsg = errorMessage[idx];
return errMsg == null ? "" : errMsg;
}
}
@Override
protected void configureShell(final Shell shell) {
super.configureShell(shell);
shell.setText(toFirstUpperCase(actionName) + " Results");
}
@Override
protected void createButtonsForButtonBar(final Composite parent) {
createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
}
@Override
protected Control createDialogArea(Composite parent) {
final Composite composite = (Composite) super.createDialogArea(parent);
/* Do we need a message on top? */
final Label label = new Label(composite, SWT.NONE);
label.setText(model.getMessage());
label.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false));
final TableViewer viewer = new TableViewer(composite,
SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
final Table table = viewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
final TableViewerColumn col1 = new TableViewerColumn(viewer, SWT.NONE);
col1.getColumn().setText(labelName);
col1.getColumn().setWidth(350);
col1.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
return model.getName((Integer) element);
}
});
final TableViewerColumn col2 = new TableViewerColumn(viewer, SWT.NONE);
col2.getColumn().setText("Status");
col2.getColumn().setWidth(200);
col2.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
return model.getStatus((Integer) element);
}
});
final TableViewerColumn col3 = new TableViewerColumn(viewer, SWT.NONE);
col3.getColumn().setText("Error Message");
col3.getColumn().setWidth(200);
col3.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
return model.getErrorMessage((Integer) element);
}
});
final GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
viewer.getControl().setLayoutData(layoutData);
viewer.setContentProvider(new ModelContentProvider());
viewer.setInput(model);
hideInFutureOriginal = !prefs.getBoolean(OsateCorePlugin.ALWAYS_SHOW_INSTANTIATION_RESULTS);
hideInFuture = hideInFutureOriginal;
final Button hide = new Button(composite, SWT.CHECK);
hide.setSelection(hideInFuture);
hide.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
hide.setText("Don't show this dialog when successful");
hide.setToolTipText("Check this button to only show this dialog when an instantiation "
+ "is cancelled or fails. Use the \"OSATE > Instantiation\" preference pane to bring it back.");
hide.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent event) {
hideInFuture = hide.getSelection();
}
});
return composite;
}
@Override
protected void okPressed() {
boolean doSave = true;
if (hideInFuture && !hideInFutureOriginal) {
// User just toggled the "don't show option"
doSave = MessageDialog.openQuestion(getShell(), "Confirm change",
"This results dialog will be hidden in the future. You can restore it by going to the \"OSATE > Instantiation\" preference pane. Do you wish to make this change?");
}
if (doSave) {
prefs.setValue(OsateCorePlugin.ALWAYS_SHOW_INSTANTIATION_RESULTS, !hideInFuture);
final Job saveJob = Job.create("Save prefences", monitor -> {
try {
((IPersistentPreferenceStore) prefs).save();
} catch (final IOException e) {
Display.getDefault().asyncExec(() -> {
MessageDialog.openError(getShell(), "Error",
"There was a problem saving the preferences: " + e.getMessage());
});
}
});
saveJob.schedule();
}
super.okPressed();
}
private static final class ModelContentProvider implements IStructuredContentProvider {
@SuppressWarnings("rawtypes")
@Override
public Object[] getElements(final Object inputElement) {
return ((Model) inputElement).getElements();
}
}
}