added the classes AmidstMessageBox and MessageFormatter

master
Stefan Dollase 2016-11-21 01:48:08 +01:00
parent dc1a6fdfb3
commit 7001052031
8 changed files with 266 additions and 65 deletions

View File

@ -5,7 +5,6 @@ import java.sql.Timestamp;
import java.util.Date;
import java.util.prefs.Preferences;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.kohsuke.args4j.CmdLineException;
@ -18,6 +17,7 @@ import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotThreadSafe;
import amidst.gui.crash.CrashWindow;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.logging.FileLogger;
import amidst.mojangapi.file.DotMinecraftDirectoryNotFoundException;
import amidst.util.OperatingSystemDetector;
@ -172,11 +172,9 @@ public class Amidst {
} catch (DotMinecraftDirectoryNotFoundException e) {
AmidstLogger.warn(e.getMessage());
e.printStackTrace();
JOptionPane.showMessageDialog(
null,
"Amidst is not able to find your '.minecraft' directory, but it requires a working Minecraft installation.",
AmidstMessageBox.displayError(
"Please install Minecraft",
JOptionPane.ERROR_MESSAGE);
"Amidst is not able to find your '.minecraft' directory, but it requires a working Minecraft installation.");
} catch (Exception e) {
handleCrash(e, Thread.currentThread());
}

View File

@ -6,8 +6,6 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@ -27,6 +25,7 @@ import amidst.gui.main.viewer.ViewerFacade;
import amidst.gui.main.viewer.ViewerFacadeBuilder;
import amidst.gui.seedsearcher.SeedSearcher;
import amidst.gui.seedsearcher.SeedSearcherWindow;
import amidst.logging.AmidstMessageBox;
import amidst.mojangapi.MojangApi;
import amidst.mojangapi.file.MojangApiParsingException;
import amidst.mojangapi.minecraftinterface.MinecraftInterfaceException;
@ -283,24 +282,17 @@ public class MainWindow {
@CalledOnlyBy(AmidstThread.EDT)
public void displayMessage(String title, String message) {
JOptionPane.showMessageDialog(frame, message, title, JOptionPane.INFORMATION_MESSAGE);
AmidstMessageBox.displayInfo(frame, title, message);
}
@CalledOnlyBy(AmidstThread.EDT)
public void displayError(String message) {
JOptionPane.showMessageDialog(frame, message, "Error", JOptionPane.ERROR_MESSAGE);
AmidstMessageBox.displayError(frame, "Error", message);
}
@CalledOnlyBy(AmidstThread.EDT)
public void displayException(Exception exception) {
JOptionPane.showMessageDialog(frame, getStackTraceAsString(exception), "Error", JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
private String getStackTraceAsString(Exception exception) {
StringWriter writer = new StringWriter();
exception.printStackTrace(new PrintWriter(writer));
return writer.toString();
AmidstMessageBox.displayError(frame, "Error", exception);
}
@CalledOnlyBy(AmidstThread.EDT)

View File

@ -2,8 +2,6 @@ package amidst.gui.main;
import java.awt.Desktop;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.function.Consumer;
@ -17,6 +15,7 @@ import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotNull;
import amidst.documentation.NotThreadSafe;
import amidst.logging.AmidstLogger;
import amidst.logging.AmidstMessageBox;
import amidst.threading.WorkerExecutor;
@NotThreadSafe
@ -56,30 +55,13 @@ public class UpdatePrompt {
return new UpdatePrompt(
currentVersion,
workerExecutor,
exception -> displayExceptionDirectly(exception),
() -> displayMessageDirectly(NO_UPDATES_AVAILABLE),
exception -> AmidstMessageBox.displayError(TITLE, exception),
() -> AmidstMessageBox.displayInfo(TITLE, NO_UPDATES_AVAILABLE),
message -> askToConfirmDirectly(message));
}
}
}
@CalledOnlyBy(AmidstThread.EDT)
private static void displayExceptionDirectly(Exception exception) {
JOptionPane.showMessageDialog(null, getStackTraceAsString(exception), TITLE, JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
private static String getStackTraceAsString(Exception exception) {
StringWriter writer = new StringWriter();
exception.printStackTrace(new PrintWriter(writer));
return writer.toString();
}
@CalledOnlyBy(AmidstThread.EDT)
private static void displayMessageDirectly(String message) {
JOptionPane.showMessageDialog(null, message, TITLE, JOptionPane.INFORMATION_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
private static boolean askToConfirmDirectly(String message) {
return JOptionPane.showConfirmDialog(null, message, TITLE, JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION;

View File

@ -1,7 +1,5 @@
package amidst.logging;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
@ -19,11 +17,13 @@ public class AmidstLogger {
private static final boolean IS_USING_ALERTS = true;
private static final boolean IS_SHOWING_DEBUG = true;
private static final Map<String, Logger> LOGGER = new HashMap<>();
private static final Map<String, Logger> LOGGER = createLoggerMap();
static {
addListener("console", CONSOLE_LOGGER);
addListener("master", IN_MEMORY_LOGGER);
private static Map<String, Logger> createLoggerMap() {
Map<String, Logger> result = new HashMap<>();
result.put("console", CONSOLE_LOGGER);
result.put("master", IN_MEMORY_LOGGER);
return result;
}
public static void addListener(String name, Logger logger) {
@ -64,6 +64,10 @@ public class AmidstLogger {
}
}
public static void warn(Throwable e) {
warn(MessageFormatter.format(e));
}
public static void error(Object... messages) {
synchronized (LOG_LOCK) {
if (IS_USING_ALERTS) {
@ -77,7 +81,7 @@ public class AmidstLogger {
public static void crash(Throwable e, String message) {
synchronized (LOG_LOCK) {
String exceptionText = getExceptionText(e);
String exceptionText = MessageFormatter.format(e);
for (Logger listener : LOGGER.values()) {
listener.crash(e, exceptionText, message);
}
@ -89,22 +93,4 @@ public class AmidstLogger {
return IN_MEMORY_LOGGER.getContents();
}
}
private static String getExceptionText(Throwable e) {
if (e != null) {
return getStackTraceAsString(e);
} else {
return "";
}
}
public static void printTraceStack(Throwable e) {
warn(getStackTraceAsString(e));
}
private static String getStackTraceAsString(Throwable e) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
return writer.toString();
}
}

View File

@ -0,0 +1,104 @@
package amidst.logging;
import java.awt.Component;
import javax.swing.JOptionPane;
import amidst.documentation.AmidstThread;
import amidst.documentation.CalledOnlyBy;
import amidst.documentation.NotThreadSafe;
@NotThreadSafe
public enum AmidstMessageBox {
;
@CalledOnlyBy(AmidstThread.EDT)
public static void displayError(String title, Throwable e) {
displayMessageBox(title, MessageFormatter.format(e), JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayError(String title, Throwable e, String message) {
displayMessageBox(title, MessageFormatter.format(e, message), JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayError(String title, Throwable e, String message, String part1, String[] parts) {
displayMessageBox(title, MessageFormatter.format(e, message, part1, parts), JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayError(String title, String message) {
displayMessageBox(title, MessageFormatter.format(message), JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayError(String title, String message, String part1, String[] parts) {
displayMessageBox(title, MessageFormatter.format(message, part1, parts), JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayInfo(String title, String message) {
displayMessageBox(title, MessageFormatter.format(message), JOptionPane.INFORMATION_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayInfo(String title, String message, String part1, String[] parts) {
displayMessageBox(title, MessageFormatter.format(message, part1, parts), JOptionPane.INFORMATION_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayError(Component parent, String title, Throwable e) {
displayMessageBox(parent, title, MessageFormatter.format(e), JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayError(Component parent, String title, Throwable e, String message) {
displayMessageBox(parent, title, MessageFormatter.format(e, message), JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayError(
Component parent,
String title,
Throwable e,
String message,
String part1,
String[] parts) {
displayMessageBox(parent, title, MessageFormatter.format(e, message, part1, parts), JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayError(Component parent, String title, String message) {
displayMessageBox(parent, title, MessageFormatter.format(message), JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayError(Component parent, String title, String message, String part1, String[] parts) {
displayMessageBox(parent, title, MessageFormatter.format(message, part1, parts), JOptionPane.ERROR_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayInfo(Component parent, String title, String message) {
displayMessageBox(parent, title, MessageFormatter.format(message), JOptionPane.INFORMATION_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
public static void displayInfo(Component parent, String title, String message, String part1, String[] parts) {
displayMessageBox(
parent,
title,
MessageFormatter.format(message, part1, parts),
JOptionPane.INFORMATION_MESSAGE);
}
@CalledOnlyBy(AmidstThread.EDT)
private static void displayMessageBox(String title, String message, int type) {
JOptionPane.showMessageDialog(null, message, title, type);
}
@CalledOnlyBy(AmidstThread.EDT)
private static void displayMessageBox(Component parent, String title, String message, int type) {
JOptionPane.showMessageDialog(parent, message, title, type);
}
}

View File

@ -0,0 +1,56 @@
package amidst.logging;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Objects;
import amidst.documentation.Immutable;
@Immutable
public enum MessageFormatter {
;
public static String format(Throwable e, String message) {
return format(message) + "\n\n" + format(e);
}
public static String format(Throwable e, String message, String part1, String[] parts) {
return format(message, part1, parts) + "\n\n" + format(e);
}
public static String format(String message) {
return String.valueOf(message);
}
public static String format(Throwable e) {
if (e != null) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
return writer.toString();
} else {
return "null";
}
}
public static String format(String message, String part1, String... parts) {
Objects.requireNonNull(message, "the message cannot be null");
int expectedNumberOfMessageParts = 2 + parts.length;
String[] messageParts = message.split("\\{\\}", expectedNumberOfMessageParts);
if (messageParts.length == 0) {
return "";
} else if (messageParts.length == 1) {
return messageParts[0];
} else {
StringBuilder b = new StringBuilder();
b.append(messageParts[0]);
b.append(format(part1));
b.append(messageParts[1]);
for (int i = 2; i < messageParts.length; i++) {
b.append(format(parts[i - 2]));
b.append(messageParts[i]);
}
return b.toString();
}
}
}

View File

@ -49,7 +49,7 @@ public enum JsonReader {
remote = readRemoteVersionList();
} catch (IOException | MojangApiParsingException e) {
AmidstLogger.warn("Unable to read remote version list.");
AmidstLogger.printTraceStack(e);
AmidstLogger.warn(e);
AmidstLogger.warn("Aborting version list load. URL: " + REMOTE_VERSION_LIST);
}
if (remote != null) {
@ -62,7 +62,7 @@ public enum JsonReader {
local = readLocalVersionListFromResource();
} catch (IOException | MojangApiParsingException e) {
AmidstLogger.warn("Unable to read local version list.");
AmidstLogger.printTraceStack(e);
AmidstLogger.warn(e);
AmidstLogger.warn("Aborting version list load. URL: " + LOCAL_VERSION_LIST);
}
if (local != null) {

View File

@ -0,0 +1,83 @@
package amidst.logging;
import org.junit.Assert;
import org.junit.Test;
public class MessageFormatterTest {
@Test
public void testEmptyMessage() {
String message = "";
String expected = "";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1"));
}
@Test
public void testSimplyMessage() {
String message = "{}";
String expected = "p1";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1"));
}
@Test
public void testBeforeMessage() {
String message = "{}m1";
String expected = "p1m1";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1"));
}
@Test
public void testAfterMessage() {
String message = "m1{}";
String expected = "m1p1";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1"));
}
@Test
public void testBetweenMessages() {
String message = "m1{}m2";
String expected = "m1p1m2";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1"));
}
@Test
public void testChain1() {
String message = "m1{}m2{}m3{}m4{}m5{}";
String expected = "m1p1m2p2m3p3m4p4m5p5";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1", "p2", "p3", "p4", "p5"));
}
@Test
public void testChain2() {
String message = "m1{}m2{}m3{}m4{}m5";
String expected = "m1p1m2p2m3p3m4p4m5";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1", "p2", "p3", "p4"));
}
@Test
public void testChain3() {
String message = "{}m1{}m2{}m3{}m4{}m5";
String expected = "p1m1p2m2p3m3p4m4p5m5";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1", "p2", "p3", "p4", "p5"));
}
@Test
public void testChain4() {
String message = "{}m1{}m2{}m3{}m4{}";
String expected = "p1m1p2m2p3m3p4m4p5";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1", "p2", "p3", "p4", "p5"));
}
@Test
public void testTooManyParts() {
String message = "m1{}m2";
String expected = "m1p1m2";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1", "p2"));
}
@Test
public void testTooFewParts() {
String message = "m1{}m2{}";
String expected = "m1p1m2{}";
Assert.assertEquals(expected, MessageFormatter.format(message, "p1"));
}
}