package org.genedb.db.loading;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.Console;
/**
* Prompt the user whether to skip or retry a file that failed to load,
* or to abort the entire run. In many cases, loading errors result from
* minor infelicities in the input files that are easy to correct by hand.
* The user can correct the problem using a text editor, and then click
* 'Retry'. On the other hand, loading errors can also (God forbid) be the
* result of bugs in the loading code, in which case the only reasonable
* response is to abort.
* <p>
* If a console is available, the prompt is textual. Otherwise, a dialog
* box is used. In practice it is rare that a console is available, since
* LoadEmbl is usually invoked using an ant target.
*
* @author rh11
*
*/
class SkipRetryAbort {
public enum Response { SKIP, RETRY, ABORT };
/**
* On a parsing error, prompt the user whether to skip the failed file,
* retry (after fixing the problem), or abort the whole loading
* run.
*
* @param e the parsing error
* @return a response code indicating the user's choice
*/
public Response getResponse(Throwable e) {
Console console = System.console();
if (console == null) {
return new SkipRetryAbort().promptUsingDialog(e);
} else {
return promptUsingConsole(console, e);
}
}
private Response promptUsingConsole(Console console, Throwable e) {
console.printf("%s\n", e.getMessage());
while (true) {
String response = console.readLine("Would you like to retry, skip the file, or abort the load?");
if (response.equals("retry")) {
return Response.RETRY;
}
else if (response.equals("skip")) {
return Response.SKIP;
}
else if (response.equals("abort")) {
return Response.ABORT;
}
}
}
Dialog dialog;
Response dialogResponse;
private Response promptUsingDialog(Throwable e) {
String prompt = e.getMessage() + ". \nWhat would you like to do?";
Frame hiddenFrame = new Frame(getClass().getName());
dialog = new Dialog(hiddenFrame, "Skip, retry, or abort?", true);
dialog.setAlwaysOnTop(true);
dialog.setLocation(100, 100);
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent windowEvent) {
windowEvent.getWindow().dispose();
}
});
dialog.add(new Label(prompt), BorderLayout.NORTH);
dialog.add(buttonPanel(), BorderLayout.SOUTH);
dialog.pack();
dialog.setVisible(true);
hiddenFrame.dispose();
if (dialogResponse == null)
throw new RuntimeException("Skip/retry/abort dialog cancelled.");
return dialogResponse;
}
private class ResponseButton extends Button {
ResponseButton(String label, final Response response) {
super(label);
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
dialogResponse = response;
dialog.dispose();
}
});
}
}
private Component buttonPanel() {
Panel buttonPanel = new Panel();
buttonPanel.add(new ResponseButton("Skip", Response.SKIP));
buttonPanel.add(new ResponseButton("Retry", Response.RETRY));
buttonPanel.add(new ResponseButton("Abort", Response.ABORT));
return buttonPanel;
}
}
class AlwaysSkip extends SkipRetryAbort {
@Override
public Response getResponse(Throwable e) {
return Response.SKIP;
}
}