added many comments and JavaDocs

vbdev2
Hai Brenner 2016-07-04 14:17:11 +03:00
parent 2b56928e9a
commit 218677fd96
14 changed files with 142 additions and 25 deletions

View File

@ -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
*/

View File

@ -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";

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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

View File

@ -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) {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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;

View File

@ -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;