added many comments and JavaDocs
parent
2b56928e9a
commit
218677fd96
|
@ -2,6 +2,8 @@ package meerkat.voting.output.outputcommands;
|
|||
|
||||
import meerkat.voting.controller.callbacks.ControllerCallback;
|
||||
|
||||
//TODO: make this class generic
|
||||
|
||||
/**
|
||||
* Base class for the commands to put in the output-device queue
|
||||
*/
|
||||
|
|
|
@ -33,7 +33,7 @@ public interface StorageManager {
|
|||
|
||||
public Map<String, UIElement> readSystemMessages() throws IOException;
|
||||
|
||||
|
||||
// These are just static key identifiers for accessing the matching System Messages in the message map
|
||||
public final static String WAIT_FOR_COMMIT_MESSAGE = "waitForCommit";
|
||||
public final static String WAIT_FOR_AUDIT_MESSAGE = "waitForAudit";
|
||||
public final static String WAIT_FOR_CAST_MESSAGE = "waitForCast";
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package meerkat.voting.storage;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import meerkat.protobuf.Voting.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -8,7 +7,6 @@ import org.slf4j.LoggerFactory;
|
|||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -17,13 +15,15 @@ import java.util.Map;
|
|||
*/
|
||||
public class StorageManagerMockup implements StorageManager {
|
||||
|
||||
private boolean adminHardwareKeyInserted;
|
||||
private Logger logger;
|
||||
private static final Logger logger = LoggerFactory.getLogger(StorageManagerMockup.class);
|
||||
|
||||
public static final String electionParamFullFilename = "/home/hai/meerkat-java/meerkat_election_params_tempfile.dat";
|
||||
public static final String systemMessagesFilename = "/home/hai/meerkat-java/meerkat_booth_system_messages.dat";
|
||||
|
||||
private boolean adminHardwareKeyInserted;
|
||||
|
||||
|
||||
public StorageManagerMockup () {
|
||||
logger = LoggerFactory.getLogger(StorageManagerMockup.class);
|
||||
logger.info("A StorageManagerMockup is constructed");
|
||||
this.adminHardwareKeyInserted = false;
|
||||
}
|
||||
|
|
|
@ -18,20 +18,24 @@ import org.slf4j.LoggerFactory;
|
|||
import static java.lang.System.in;
|
||||
|
||||
|
||||
/**
|
||||
* an asynchronous thread implementation of the VotingBoothUI interface
|
||||
* This is a mock-up implementation using just the console as our UI device
|
||||
*/
|
||||
public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SystemConsoleUI.class);
|
||||
|
||||
private BufferedReader bufferedReader;
|
||||
private LinkedBlockingQueue<UICommand> queue;
|
||||
private final Logger logger;
|
||||
private final int tickDurationInMillisec = 10;
|
||||
private Date startWaitingTime;
|
||||
|
||||
private volatile boolean shutDownHasBeenCalled;
|
||||
|
||||
|
||||
|
||||
public SystemConsoleUI() {
|
||||
logger = LoggerFactory.getLogger(SystemConsoleUI.class);
|
||||
final int tickDurationInMillisec = 10; // period between view update calls
|
||||
|
||||
logger.info("A VB UI console is constructed");
|
||||
queue = new LinkedBlockingQueue<>();
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(in));
|
||||
|
@ -44,6 +48,9 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* the run() method. Simply loops and takes commands from the UI's queue and handles them accordingly
|
||||
*/
|
||||
@Override
|
||||
public void run () {
|
||||
logger.info("UI starts running");
|
||||
|
@ -66,6 +73,13 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
queue.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* chooses the next method to run according to the type of the given UICommand.
|
||||
* Special case for the TickCommand.
|
||||
* As this command is registered in the queue constantly, we simply ignore this command if the UI is not in
|
||||
* a waiting state
|
||||
* @param command any valid UICommand
|
||||
*/
|
||||
private void handleSingleCommand(UICommand command) {
|
||||
if (!(command instanceof TickCommand)) {
|
||||
if (startWaitingTime != null) {
|
||||
|
@ -103,12 +117,20 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* start a new session by registering a StartSessionUICommand
|
||||
* @param callback - a boolean future callback to return when done
|
||||
*/
|
||||
@Override
|
||||
public void startNewVoterSession(FutureCallback<Void> callback) {
|
||||
logger.debug("UI interface call to startNewVoterSession");
|
||||
queue.add(new StartSessionUICommand((ControllerCallback)callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* welcomes the new voter at the beginning of the session
|
||||
* @param command a StartSessionUICommand with a acallback
|
||||
*/
|
||||
private void doShowWelcomeScreen(StartSessionUICommand command) {
|
||||
logger.debug("UI entered doShowWelcomeScreen");
|
||||
System.out.println("Welcome, new voter!");
|
||||
|
@ -118,11 +140,19 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
callback.onSuccess(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* marks that the waiting, for something else to have happened, is finished
|
||||
*/
|
||||
private void stopWaiting () {
|
||||
System.out.println ();
|
||||
startWaitingTime = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* waits until the ENTER key is pressed in the console
|
||||
* @param message a message to show the user in the console
|
||||
*/
|
||||
private void waitForEnter(String message) {
|
||||
if (message != null) {
|
||||
System.out.println(message);
|
||||
|
@ -141,6 +171,11 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* call for the channel choice phase by registering a ChannelChoiceUICommand in the queue
|
||||
* @param questions questions to determine the right voting channel for this voter
|
||||
* @param callback that's where we store the answers to decide channel upon for the current voter
|
||||
*/
|
||||
@Override
|
||||
public void chooseChannel(List<BallotQuestion> questions, FutureCallback<List<BallotAnswer>> callback) {
|
||||
logger.debug("UI interface call to chooseChannel");
|
||||
|
@ -148,6 +183,10 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
queue.add(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* lists the channel choice questions to the voter and gathers the voter's answers
|
||||
* @param command a ChannelChoiceUICommand with the data and a callback
|
||||
*/
|
||||
private void doAskChannelChoiceQuestions (ChannelChoiceUICommand command) {
|
||||
logger.debug("UI: doAskChannelChoiceQuestions");
|
||||
System.out.println("Showing questions for choosing channel:\n");
|
||||
|
@ -166,12 +205,21 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* call for the race voting question phase by registering a RaceVotingUICommand in the queue
|
||||
* @param questions all ballot questions to present to the voter
|
||||
* @param callback the responses to the questions collected by the UI, to send back to the controller. Responses are null if voter chose to cancel session
|
||||
*/
|
||||
@Override
|
||||
public void askVoterQuestions(List<BallotQuestion> questions, FutureCallback<List<BallotAnswer>> callback) {
|
||||
logger.debug("UI interface call to chooseChannel");
|
||||
queue.add(new RaceVotingUICommand(questions, (ControllerCallback)callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* lists the race voting questions to the voter and gathers the voter's answers
|
||||
* @param command a RaceVotingUICommand with a callback
|
||||
*/
|
||||
private void doAskVotingQuestions (RaceVotingUICommand command) {
|
||||
logger.debug("UI: doAskVotingQuestions");
|
||||
System.out.println("Showing questions for race voting:\n");
|
||||
|
@ -190,12 +238,20 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* call for the cast-or-audit phase by registering a CastOrAuditUICommand in the queue
|
||||
* @param callback the returned choice of how to finalize the ballot
|
||||
*/
|
||||
@Override
|
||||
public void castOrAudit(FutureCallback<FinalizeBallotChoice> callback) {
|
||||
logger.debug("UI interface call to castOrAudit");
|
||||
queue.add(new CastOrAuditUICommand((ControllerCallback)callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* asks the voter whether to cast or audit the ballot
|
||||
* @param command a simple CastOrAuditUICommand with the callback
|
||||
*/
|
||||
private void doCastOrAudit(CastOrAuditUICommand command) {
|
||||
logger.debug("UI entered doCastOrAudit");
|
||||
System.out.println ("Finalizing your vote. Do you wish to (C)ast or (A)udit?");
|
||||
|
@ -225,12 +281,21 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* makes the UI (and voter) wait for something else to happen, by registering a WaitForFinishUICommand in the queue
|
||||
* @param message a message to show the user on the UI device while waiting
|
||||
* @param callback a success return value of the wait (cancelling returns false)
|
||||
*/
|
||||
@Override
|
||||
public void notifyVoterToWaitForFinish(UIElement message, FutureCallback<Void> callback) {
|
||||
logger.debug("UI interface call to notifyVoterToWaitForFinish");
|
||||
queue.add(new WaitForFinishUICommand(message, (ControllerCallback)callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the voter (in the console) to wait until some other process is finished
|
||||
* @param command a simple WaitForFinishUICommand with the callback
|
||||
*/
|
||||
public void doWaitForFinish (WaitForFinishUICommand command) {
|
||||
logger.debug("UI entered doWaitForFinish");
|
||||
|
||||
|
@ -247,13 +312,23 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
System.out.print ("Waiting : .");
|
||||
}
|
||||
|
||||
/**
|
||||
* show an error to the voter. Halts the system until a technician handles it
|
||||
* @param errorMessage message to show in UI device
|
||||
* @param callback returns interrupt
|
||||
*/
|
||||
@Override
|
||||
public void showErrorMessageAndHalt(UIElement errorMessage, FutureCallback<Boolean> callback) {
|
||||
logger.debug("UI interface call to showErrorMessageAndHalt");
|
||||
throw new UnsupportedOperationException("Not implemented becuase currently not sure if we ever use it.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* show an error to the voter. let him press a (chosen) button for handling the error.
|
||||
* @param errorMessage message to show in UI device
|
||||
* @param buttonLabels labels for buttons to present to voter
|
||||
* @param callback the number of the selected button
|
||||
*/
|
||||
@Override
|
||||
public void showErrorMessageWithButtons(UIElement errorMessage, UIElement[] buttonLabels, FutureCallback<Integer> callback) {
|
||||
logger.debug("UI interface call to showErrorMessageWithButtons");
|
||||
|
@ -261,6 +336,10 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
queue.add(new FatalErrorUICommand(errorMessage, buttonLabels, (ControllerCallback)callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* show an error to the voter. let him press a (chosen) button for handling the error.
|
||||
* @param command a FatalErrorUICommand with the callback
|
||||
*/
|
||||
private void doFatalError (FatalErrorUICommand command) {
|
||||
logger.debug("UI entered doFatalError");
|
||||
|
||||
|
@ -301,12 +380,20 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* this method is run when a TickCommand was received while in waiting state
|
||||
*/
|
||||
private void doTick () {
|
||||
if (startWaitingTime != null) {
|
||||
System.out.print ("."); // still waiting
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get an input line from the console
|
||||
* @return a line from the voter
|
||||
* @throws IOException
|
||||
*/
|
||||
private String readInputLine() throws IOException{
|
||||
String s;
|
||||
try {
|
||||
|
@ -323,6 +410,11 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* asserts that the question data matches the types that we can handle in the ConsoleUI
|
||||
* (better and more sophisticated UI will be able to handle more types of data)
|
||||
* @param questions list of the questions
|
||||
*/
|
||||
private void assertQuestionsAreValid (List<BallotQuestion> questions) {
|
||||
for (int index = 0; index < questions.size(); ++index) {
|
||||
BallotQuestion question = questions.get(index);
|
||||
|
@ -339,6 +431,15 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* present the questions to the voter console sequentially.
|
||||
* Voter may choose at any time to skip a question, go back or even cancel the whole session
|
||||
* @param questions list of questions to present
|
||||
* @return list of answers to the questions (at the same order)
|
||||
* @throws VoterCancelThrowable this is thrown if a voter chose to cancel in the middle of the process
|
||||
* @throws IOException
|
||||
*/
|
||||
private List<BallotAnswer> askVoterForAnswers(List<BallotQuestion> questions) throws VoterCancelThrowable, IOException {
|
||||
|
||||
assertQuestionsAreValid (questions);
|
||||
|
@ -348,7 +449,7 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
while (index < questions.size()) {
|
||||
BallotQuestion question = questions.get(index);
|
||||
System.out.println("Question number " + index);
|
||||
showQuestionOnScreen(question);
|
||||
showQuestionInConsole(question);
|
||||
|
||||
System.out.println("UI screen: Enter your answer. You can also type '(b)ack' or '(c)ancel' or '(s)kip");
|
||||
String s = readInputLine();
|
||||
|
@ -372,8 +473,11 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
return answers;
|
||||
}
|
||||
|
||||
//show question on the screen for the voter
|
||||
private void showQuestionOnScreen(BallotQuestion question) {
|
||||
/**
|
||||
* present a question in the console to the voter
|
||||
* @param question a text ballot question
|
||||
*/
|
||||
private void showQuestionInConsole(BallotQuestion question) {
|
||||
if (!isQuestionOnlyText(question)) {
|
||||
System.err.println("debug: an element in question is not of TEXT type");
|
||||
throw new UnsupportedOperationException();
|
||||
|
@ -388,6 +492,11 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether the data of the question is only text. This is the only type we can handle in ConsoleUI
|
||||
* @param question a ballot question to check
|
||||
* @return True if the question data is only text
|
||||
*/
|
||||
private boolean isQuestionOnlyText (BallotQuestion question) {
|
||||
boolean isText = true;
|
||||
if (question.getQuestion().getType() != UIElementDataType.TEXT
|
||||
|
@ -424,5 +533,4 @@ public class SystemConsoleUI implements VotingBoothUI, Runnable {
|
|||
return shutDownHasBeenCalled;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.util.TimerTask;
|
|||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
* Created by hai on 25/04/16.
|
||||
* A thread that sends the UI clock TickCommands in a given constant frequency
|
||||
*/
|
||||
class TickerTimerTask extends TimerTask {
|
||||
private LinkedBlockingQueue<UICommand> uiQueue;
|
||||
|
|
|
@ -7,10 +7,13 @@ import java.util.List;
|
|||
|
||||
|
||||
/**
|
||||
* An interface for the user interface component of the voting booth
|
||||
* An interface for the UI component of the voting booth
|
||||
*/
|
||||
public interface VotingBoothUI {
|
||||
|
||||
/**
|
||||
* a simple enum for the voter's finalize choice
|
||||
*/
|
||||
public enum FinalizeBallotChoice {
|
||||
CAST,
|
||||
AUDIT
|
||||
|
|
|
@ -3,7 +3,7 @@ package meerkat.voting.ui.uicommands;
|
|||
import meerkat.voting.controller.callbacks.*;
|
||||
|
||||
/**
|
||||
* Created by hai on 21/04/16.
|
||||
* This command signals the UI that the voter should now choose whether to Cast or Audit the ballot
|
||||
*/
|
||||
public class CastOrAuditUICommand extends UICommand {
|
||||
public CastOrAuditUICommand(ControllerCallback callback) {
|
||||
|
|
|
@ -6,7 +6,7 @@ import meerkat.voting.controller.callbacks.*;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by hai on 18/04/16.
|
||||
* This command signals the UI to present channel choice questions to the voter and send back the answers
|
||||
*/
|
||||
public class ChannelChoiceUICommand extends UICommand {
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import meerkat.protobuf.Voting.UIElement;
|
|||
import meerkat.voting.controller.callbacks.*;
|
||||
|
||||
/**
|
||||
* Created by hai on 18/04/16.
|
||||
* This command signals the UI that a fatal error occurred and it should notify the voter
|
||||
*/
|
||||
public class FatalErrorUICommand extends UICommand {
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import meerkat.voting.controller.callbacks.*;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by hai on 18/04/16.
|
||||
* This command signals the UI to present the race voting questions to the voter
|
||||
*/
|
||||
public class RaceVotingUICommand extends UICommand {
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package meerkat.voting.ui.uicommands;
|
|||
import meerkat.voting.controller.callbacks.*;
|
||||
|
||||
/**
|
||||
* Created by hai on 18/04/16.
|
||||
* This command signals the UI to present a new session to a voter
|
||||
*/
|
||||
public class StartSessionUICommand extends UICommand {
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@ package meerkat.voting.ui.uicommands;
|
|||
import meerkat.voting.controller.callbacks.*;
|
||||
|
||||
/**
|
||||
* Created by hai on 18/04/16.
|
||||
* This is a special UI command which just points out that a tick of the clock occurred
|
||||
* (so a progress bar can advance while waiting)
|
||||
*/
|
||||
public class TickCommand extends UICommand {
|
||||
|
||||
|
|
|
@ -3,6 +3,10 @@ package meerkat.voting.ui.uicommands;
|
|||
import meerkat.voting.controller.callbacks.*;
|
||||
|
||||
//TODO: make this class generic
|
||||
|
||||
/**
|
||||
* Base class for the commands to put in the UI queue
|
||||
*/
|
||||
public abstract class UICommand {
|
||||
protected final ControllerCallback callback;
|
||||
|
||||
|
|
|
@ -4,9 +4,8 @@ import meerkat.protobuf.Voting.*;
|
|||
import meerkat.voting.controller.callbacks.*;
|
||||
|
||||
/**
|
||||
* Created by hai on 18/04/16.
|
||||
* This command signals the UI to wait with an appropriate message until a new command replaces this state
|
||||
*/
|
||||
|
||||
public class WaitForFinishUICommand extends UICommand {
|
||||
|
||||
private final UIElement message;
|
||||
|
|
Loading…
Reference in New Issue