package org.jactr.eclipse.runtime.ui.looper;
/*
* default logging
*/
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.jactr.eclipse.runtime.session.ISession;
import org.jactr.eclipse.ui.UIPlugin;
public class LoopNotifier implements ILoopListener
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(LoopNotifier.class);
private volatile LoopDialog _dialog;
private Map<ISession, Set<List<String>>> _ignorePatterns;
private List<String> _notifyingProductionLoop;
private ISession _notifyingSession;
public LoopNotifier()
{
_ignorePatterns = new HashMap<ISession, Set<List<String>>>();
}
public void loopDetected(final ISession session, final String modelName,
final List<String> productionLoop, final int iterations)
{
if (iterations <= 1) return;
Set<List<String>> ignoreSet = _ignorePatterns.get(session);
if (ignoreSet != null && ignoreSet.contains(productionLoop)) return;
Display.getDefault().asyncExec(new Runnable() {
public void run()
{
try
{
notifyUser(session, modelName, productionLoop, iterations);
}
catch (Exception e)
{
LOGGER.debug("Failed to notify user ", e);
}
}
});
}
synchronized public void add(ISession session)
{
_ignorePatterns.put(session, new HashSet<List<String>>());
}
synchronized public void clear(ISession session)
{
Set<List<String>> ignore = _ignorePatterns.remove(session);
if (ignore != null) ignore.clear();
if (_dialog != null && _notifyingSession == session) _dialog.close();
}
synchronized protected void ignore(ISession session, List<String> pattern)
{
Set<List<String>> ignore = _ignorePatterns.get(session);
if (ignore != null) ignore.add(pattern);
}
private void notifyUser(ISession session, String modelName,
List<String> productionLoop, int iterations)
{
_notifyingProductionLoop = productionLoop;
_notifyingSession = session;
if (!session.isOpen() || session.hasBeenDestroyed())
{
if (_dialog != null) _dialog.close();
return;
}
String message = String.format(
"Loop detected in %s. Sequence %s repeated %d times. Stop execution?",
modelName, productionLoop, iterations);
if (_dialog == null)
{
String toggleMessage = "Ignore identical patterns in this run.";
_dialog = new LoopDialog(Display.getDefault().getActiveShell(),
"Loop detected. Suspend?", null, message, MessageDialog.QUESTION,
new String[] { IDialogConstants.STOP_LABEL,
IDialogConstants.IGNORE_LABEL }, 0, toggleMessage, false);
Display.getDefault().beep();
_dialog.setBlockOnOpen(false);
_dialog.open();
}
_dialog.setMessage(message);
}
protected void terminate(ISession session)
{
if (session.hasBeenDestroyed() || !session.isOpen()) return;
try
{
session.close();
}
catch (Exception ce)
{
// should probably do something witht his..
UIPlugin.log(ce);
}
}
private class LoopDialog extends MessageDialogWithToggle
{
public LoopDialog(Shell parentShell, String dialogTitle, Image image,
String message, int dialogImageType, String[] dialogButtonLabels,
int defaultIndex, String toggleMessage, boolean toggleState)
{
super(parentShell, dialogTitle, image, message, dialogImageType,
dialogButtonLabels, defaultIndex, toggleMessage, toggleState);
}
public void setMessage(String message)
{
messageLabel.setText(message);
getShell().pack();
}
private boolean _wasSet = false;
@Override
protected void setReturnCode(int code)
{
_wasSet = true;
super.setReturnCode(code);
}
@Override
protected Button createToggleButton(Composite parent)
{
Button button = super.createToggleButton(parent);
button.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e)
{
}
public void widgetSelected(SelectionEvent e)
{
getButton(0).setFocus();
}
});
return button;
}
@Override
public boolean close()
{
if (_wasSet)
{
if (getToggleState())
ignore(_notifyingSession, _notifyingProductionLoop);
// yes
if (getReturnCode() == IDialogConstants.STOP_ID)
terminate(_notifyingSession);
}
_wasSet = false;
_dialog = null;
_notifyingSession = null;
_notifyingProductionLoop = null;
return super.close();
}
}
}