diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/CastOrAuditCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/CastOrAuditCallback.java index 47ecd3b..7226f83 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/CastOrAuditCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/CastOrAuditCallback.java @@ -2,13 +2,16 @@ package meerkat.voting.controller.callbacks; import meerkat.protobuf.Voting.UIElement; import meerkat.voting.controller.commands.*; -import meerkat.voting.controller.commands.ControllerCommand; import meerkat.voting.ui.VotingBoothUI.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.concurrent.LinkedBlockingQueue; +/** + * A controller callback for the cast-or-audit request to the UI. + * Upon getting a FinalizeBallotChoice response from the voter, the callback then registers a new command + * to the controller queue, either a CastCommand or an AuditCommand according to the voter's choice + */ public class CastOrAuditCallback extends ControllerCallback { protected final static Logger logger = LoggerFactory.getLogger(CastOrAuditCallback.class); protected final UIElement unrecognizedFinalizeResponseMessage; @@ -31,9 +34,7 @@ public class CastOrAuditCallback extends ControllerCallback> { protected final static Logger logger = LoggerFactory.getLogger(ChannelChoiceCallback.class); @@ -26,12 +29,14 @@ public class ChannelChoiceCallback extends ControllerCallback @Override public void onSuccess(List result) { logger.debug("callback for channel choice returned success"); + // register the chosen BallotAnswers to a command in the controller queue enqueueCommand(new ChannelDeterminedCommand(getRequestIdentifier(), getBallotSerialNumber(), result)); } @Override public void onFailure(Throwable t) { if (t instanceof VoterCancelException) { + // voter has cancelled during the UI channel choice process. A VoterCancelException is thrown logger.debug("ChannelChoiceCallback got a cancellation response"); enqueueCommand(new RestartVotingCommand(getRequestIdentifier(), getBallotSerialNumber())); } diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/ControllerCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/ControllerCallback.java index d5684d2..18719bd 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/ControllerCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/ControllerCallback.java @@ -1,13 +1,17 @@ package meerkat.voting.controller.callbacks; -/** - * Created by hai on 18/05/16. - */ import com.google.common.util.concurrent.FutureCallback; import meerkat.voting.controller.commands.ControllerCommand; - import java.util.concurrent.LinkedBlockingQueue; +/** + * The base (abstract) class of all callbacks for requests sent by the controller to other components (ui, output-device) + * It implements the FutureCallback interface + * Its members are: + * - requestIdentifier - uniquely identifies the request which this callback responds + * - ballotSerialNumber - number of ballot which was currently active when request was sent + * - controllerQueue - so the callback can issue and register a new command to the controller, once the request handling is finished + */ public abstract class ControllerCallback implements FutureCallback { private final int requestIdentifier; diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/EncryptionFailedCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/EncryptionFailedCallback.java index de7a61e..55906be 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/EncryptionFailedCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/EncryptionFailedCallback.java @@ -1,14 +1,16 @@ package meerkat.voting.controller.callbacks; -import jdk.nashorn.internal.runtime.regexp.joni.exception.ValueException; -import meerkat.voting.controller.commands.ControllerCommand; -import meerkat.voting.controller.commands.RestartVotingCommand; -import meerkat.voting.controller.commands.RetryEncryptAndCommitBallotCommand; +import meerkat.voting.controller.commands.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.concurrent.LinkedBlockingQueue; +/** + * This is quite a special callback. It is not issued in a normal flow of the voting. + * This callback is made only for a request to the UI to choose handling of failure in encryption. + * When encryption/signature fails the voter is asked in the UI whether to retry or abort. + * This specific callback decides, upon the answer to this request, which command to register in the controller's queue + */ public class EncryptionFailedCallback extends ControllerCallback { protected final static Logger logger = LoggerFactory.getLogger(EncryptionFailedCallback.class); @@ -20,18 +22,18 @@ public class EncryptionFailedCallback extends ControllerCallback { @Override public void onSuccess(Integer result) { - logger.debug("callback for voting returned success"); + logger.debug("callback for encryption-failed request is initiated successfully"); int res = result.intValue(); if (res == 0) { logger.debug("voter chose to retry encryption"); enqueueCommand(new RetryEncryptAndCommitBallotCommand(getRequestIdentifier(), getBallotSerialNumber())); } else if (res == 1) { - logger.debug("voter chose to cancel the vote"); + logger.debug("voter chose to abort the vote"); enqueueCommand(new RestartVotingCommand(getRequestIdentifier(), getBallotSerialNumber())); } else { - onFailure(new ValueException("EncryptionFailedCallback got an unknown result (" + res + ")")); + onFailure(new IllegalArgumentException("EncryptionFailedCallback got an unknown result (" + res + ")")); } } diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/ErrorMessageRestartCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/ErrorMessageRestartCallback.java index fae8b4e..4d75c1d 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/ErrorMessageRestartCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/ErrorMessageRestartCallback.java @@ -1,12 +1,16 @@ package meerkat.voting.controller.callbacks; -import meerkat.voting.controller.commands.ControllerCommand; -import meerkat.voting.controller.commands.RestartVotingCommand; +import meerkat.voting.controller.commands.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.concurrent.LinkedBlockingQueue; +/** + * This is quite a special callback. It is not issued in a normal flow of the voting. + * This callback is made only for a request to the UI to show the voter an error message. + * Upon approval of the voter, the method onSuccess() of this callback is called, and the voting + * is reset through a command to the controller's queue + */ public class ErrorMessageRestartCallback extends ControllerCallback { protected final static Logger logger = LoggerFactory.getLogger(ErrorMessageRestartCallback.class); diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/NewVoterCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/NewVoterCallback.java index 9b4e365..17f67be 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/NewVoterCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/NewVoterCallback.java @@ -1,13 +1,16 @@ package meerkat.voting.controller.callbacks; -import meerkat.voting.controller.commands.ChannelChoiceCommand; -import meerkat.voting.controller.commands.ControllerCommand; -import meerkat.voting.controller.commands.RestartVotingCommand; +import meerkat.voting.controller.commands.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.concurrent.LinkedBlockingQueue; + +/** + * A controller callback for the StartSession request to the UI. + * Upon approval of the voter, it registers a new ChannelChoiceCommand to the controller queue (which + * then starts the channel choice process) + */ public class NewVoterCallback extends ControllerCallback { protected final static Logger logger = LoggerFactory.getLogger(NewVoterCallback.class); diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceCommitCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceCommitCallback.java index a832572..dd20ec2 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceCommitCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceCommitCallback.java @@ -1,14 +1,16 @@ package meerkat.voting.controller.callbacks; import meerkat.protobuf.Voting.UIElement; -import meerkat.voting.controller.commands.ControllerCommand; -import meerkat.voting.controller.commands.ChooseFinalizeOptionCommand; -import meerkat.voting.controller.commands.ReportErrorCommand; +import meerkat.voting.controller.commands.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.concurrent.LinkedBlockingQueue; +/** + * A controller callback for the Commit request to the output-device. + * When committing is done, the callback's onSuccess() method is called to register a new ChooseFinalizeOptionCommand + * to the controller + */ public class OutputDeviceCommitCallback extends ControllerCallback { protected final static Logger logger = LoggerFactory.getLogger(OutputDeviceCommitCallback.class); protected final UIElement outputDeviceFailureMessage; diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceFinalizeCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceFinalizeCallback.java index 414bdb0..6c5b0d4 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceFinalizeCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/OutputDeviceFinalizeCallback.java @@ -1,14 +1,16 @@ package meerkat.voting.controller.callbacks; import meerkat.protobuf.Voting.UIElement; -import meerkat.voting.controller.commands.ControllerCommand; -import meerkat.voting.controller.commands.ReportErrorCommand; -import meerkat.voting.controller.commands.RestartVotingCommand; +import meerkat.voting.controller.commands.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.concurrent.LinkedBlockingQueue; +/** + * A controller callback for the Finalize request to the output-device. + * When finalizing (either cast or audit) is done, + * the callback's onSuccess() method is called to register a new command to the controller to restart the voting process + */ public class OutputDeviceFinalizeCallback extends ControllerCallback { protected final static Logger logger = LoggerFactory.getLogger(OutputDeviceFinalizeCallback.class); protected final UIElement outputDeviceFailureMessage; diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/VoterCancelException.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/VoterCancelException.java index 4c0d411..2844fc1 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/VoterCancelException.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/VoterCancelException.java @@ -1,8 +1,8 @@ package meerkat.voting.controller.callbacks; /** - * Created by hai on 06/06/16. + * Just a simple unique exception to throw when a voter aborts/cancels the voting during the voting process */ -public class VoterCancelException extends Exception{ +public class VoterCancelException extends Exception { // } diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/VotingCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/VotingCallback.java index 173fa82..b389884 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/VotingCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/VotingCallback.java @@ -1,16 +1,19 @@ package meerkat.voting.controller.callbacks; import meerkat.protobuf.Voting.*; -import meerkat.voting.controller.commands.ControllerCommand; -import meerkat.voting.controller.commands.EncryptAndCommitBallotCommand; -import meerkat.voting.controller.commands.ReportErrorCommand; -import meerkat.voting.controller.commands.RestartVotingCommand; +import meerkat.voting.controller.commands.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.List; import java.util.concurrent.LinkedBlockingQueue; +/** + * A controller callback for the race-voting request to the UI. + * Upon receiving the answers for the race questions, the callback registers a new command to process + * the voter's answers (encrypt and then commit) into the controller's queue. + * If voter cancelled during the process, a cancelling exception is thrown and a RestartVotingCommand is + * registered through the onFailure() method + */ public class VotingCallback extends ControllerCallback> { protected final static Logger logger = LoggerFactory.getLogger(VotingCallback.class); protected final UIElement unsuccessfulVotingMessage; diff --git a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/WaitForFinishCallback.java b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/WaitForFinishCallback.java index 2634e27..f3f0308 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/callbacks/WaitForFinishCallback.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/callbacks/WaitForFinishCallback.java @@ -1,13 +1,16 @@ package meerkat.voting.controller.callbacks; import meerkat.protobuf.Voting.UIElement; -import meerkat.voting.controller.commands.ControllerCommand; -import meerkat.voting.controller.commands.ReportErrorCommand; +import meerkat.voting.controller.commands.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.concurrent.LinkedBlockingQueue; +/** + * This callback is attached to requests to UI which ask the voter to wait for some process to finish. + * It actually asks nothing in the UI, and it is simply attached to the UI request as a place-holder. + * Therefore its onSuccess() method is empty + */ public class WaitForFinishCallback extends ControllerCallback { protected final static Logger logger = LoggerFactory.getLogger(WaitForFinishCallback.class); protected final UIElement somethingWrongMessage; diff --git a/voting-booth/src/main/java/meerkat/voting/controller/commands/AuditCommand.java b/voting-booth/src/main/java/meerkat/voting/controller/commands/AuditCommand.java index d2c99f2..fa7fc4a 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/commands/AuditCommand.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/commands/AuditCommand.java @@ -1,7 +1,7 @@ package meerkat.voting.controller.commands; /** - * Created by hai on 11/04/16. + * a command to audit the ballot */ public class AuditCommand extends ControllerCommand { public AuditCommand(int requestIdentifier, long ballotSerialNumber) { diff --git a/voting-booth/src/main/java/meerkat/voting/controller/commands/CastCommand.java b/voting-booth/src/main/java/meerkat/voting/controller/commands/CastCommand.java index 0621efb..c4e96bc 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/commands/CastCommand.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/commands/CastCommand.java @@ -1,7 +1,7 @@ package meerkat.voting.controller.commands; /** - * Created by hai on 11/04/16. + * a command to cast the ballot */ public class CastCommand extends ControllerCommand { public CastCommand(int requestIdentifier, long ballotSerialNumber) { diff --git a/voting-booth/src/main/java/meerkat/voting/controller/commands/ChannelChoiceCommand.java b/voting-booth/src/main/java/meerkat/voting/controller/commands/ChannelChoiceCommand.java index f555e4b..9d86edb 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/commands/ChannelChoiceCommand.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/commands/ChannelChoiceCommand.java @@ -1,7 +1,7 @@ package meerkat.voting.controller.commands; /** - * Created by hai on 11/04/16. + * a command to initiate the channel choice flow at the beginning of the voting */ public class ChannelChoiceCommand extends ControllerCommand { public ChannelChoiceCommand(int requestIdentifier, long ballotSerialNumber) { diff --git a/voting-booth/src/main/java/meerkat/voting/controller/commands/ChannelDeterminedCommand.java b/voting-booth/src/main/java/meerkat/voting/controller/commands/ChannelDeterminedCommand.java index 47d6f8b..c9b7023 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/commands/ChannelDeterminedCommand.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/commands/ChannelDeterminedCommand.java @@ -4,7 +4,7 @@ import meerkat.protobuf.Voting.*; import java.util.List; /** - * Created by hai on 11/04/16. + * This command is registered in the controller right after the voter answered all the channel choice questions */ public class ChannelDeterminedCommand extends ControllerCommand { public List channelChoiceAnswers; diff --git a/voting-booth/src/main/java/meerkat/voting/controller/commands/ChooseFinalizeOptionCommand.java b/voting-booth/src/main/java/meerkat/voting/controller/commands/ChooseFinalizeOptionCommand.java index 76b0e77..0cdbacc 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/commands/ChooseFinalizeOptionCommand.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/commands/ChooseFinalizeOptionCommand.java @@ -1,7 +1,7 @@ package meerkat.voting.controller.commands; /** - * Created by hai on 11/04/16. + * a command to initiate asking the voter how to finalize (cast-or-audit) the ballot */ public class ChooseFinalizeOptionCommand extends ControllerCommand { public ChooseFinalizeOptionCommand(int requestIdentifier, long ballotSerialNumber) { diff --git a/voting-booth/src/main/java/meerkat/voting/controller/commands/ControllerCommand.java b/voting-booth/src/main/java/meerkat/voting/controller/commands/ControllerCommand.java index 5bfc5c2..7743723 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/commands/ControllerCommand.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/commands/ControllerCommand.java @@ -1,5 +1,9 @@ package meerkat.voting.controller.commands; +/** + * This is the base class for the controller commands. + * These commands are registered in a command queue of the controller. + */ public abstract class ControllerCommand { protected final int requestIdentifier; protected final long ballotSerialNumber; diff --git a/voting-booth/src/main/java/meerkat/voting/controller/commands/EncryptAndCommitBallotCommand.java b/voting-booth/src/main/java/meerkat/voting/controller/commands/EncryptAndCommitBallotCommand.java index d7e4508..3917a31 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/commands/EncryptAndCommitBallotCommand.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/commands/EncryptAndCommitBallotCommand.java @@ -3,6 +3,10 @@ package meerkat.voting.controller.commands; import meerkat.protobuf.Voting.BallotAnswer; import java.util.List; +/** + * a command registered after voter answered all ballot questions. + * The controller then initiates an encryption-signature-commit flow + */ public class EncryptAndCommitBallotCommand extends ControllerCommand { private final List votingAnswers; diff --git a/voting-booth/src/main/java/meerkat/voting/controller/commands/ReportErrorCommand.java b/voting-booth/src/main/java/meerkat/voting/controller/commands/ReportErrorCommand.java index b4a1fe7..fe3e369 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/commands/ReportErrorCommand.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/commands/ReportErrorCommand.java @@ -2,6 +2,10 @@ package meerkat.voting.controller.commands; import meerkat.protobuf.Voting.*; +/** + * This command is not a part of the normal flow of the controller. + * It asks the controller to handle (report to voter) some error message + */ public class ReportErrorCommand extends ControllerCommand { private final UIElement errorMessage; diff --git a/voting-booth/src/main/java/meerkat/voting/controller/commands/RestartVotingCommand.java b/voting-booth/src/main/java/meerkat/voting/controller/commands/RestartVotingCommand.java index 57906d2..600a163 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/commands/RestartVotingCommand.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/commands/RestartVotingCommand.java @@ -1,6 +1,9 @@ package meerkat.voting.controller.commands; +/** + * a command to restart a voting flow (for a new voter) + */ public class RestartVotingCommand extends ControllerCommand { public RestartVotingCommand(int requestIdentifier, long ballotSerialNumber) { super(requestIdentifier, ballotSerialNumber); diff --git a/voting-booth/src/main/java/meerkat/voting/controller/commands/RetryEncryptAndCommitBallotCommand.java b/voting-booth/src/main/java/meerkat/voting/controller/commands/RetryEncryptAndCommitBallotCommand.java index 66dc992..b79a55f 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/commands/RetryEncryptAndCommitBallotCommand.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/commands/RetryEncryptAndCommitBallotCommand.java @@ -1,5 +1,10 @@ package meerkat.voting.controller.commands; +/** + * This is quite a special command not part of the normal voting flow. + * It extends the base EncryptAndCommitBallotCommand for occasions where first attempt of encryption failed + * and the voter asks to re-try encrypting and committing. + */ public class RetryEncryptAndCommitBallotCommand extends EncryptAndCommitBallotCommand { public RetryEncryptAndCommitBallotCommand(int requestIdentifier, diff --git a/voting-booth/src/main/java/meerkat/voting/controller/selector/QuestionSelector.java b/voting-booth/src/main/java/meerkat/voting/controller/selector/QuestionSelector.java index e9decae..6603b62 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/selector/QuestionSelector.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/selector/QuestionSelector.java @@ -4,12 +4,26 @@ import meerkat.protobuf.Voting.*; import java.util.List; /** - * Created by hai on 02/05/16. + * An interface for the question-selection component. + * This component handles the connection between the channel choice questions and the race questions. + * It gets the answers for the channel choice questions and determines which race question to put in the voter's ballot. + * It also creates an identifier for this chosen channel. This identifier should appear in the plaintext of the ballot. + * The channel identifier does not identify a specific voter, but rather it identifies a specific voting channel */ public interface QuestionSelector { + /** + * determines an identifier for the channel of the voter + * @param channelChoiceAnswers The answers given by the voter to the channel choice questions + * @return an identifier of the channel. To be used by selectQuestionsForVoter(). This identifier should also appear on the plaintext of the ballot + */ public byte[] getChannelIdentifier (List channelChoiceAnswers); + /** + * determines which race questions to present to the voter according to its channel + * @param channelIdentifier the identifier of this specific channel + * @return the race questions (to present to the voter) + */ public List selectQuestionsForVoter (byte[] channelIdentifier); } diff --git a/voting-booth/src/main/java/meerkat/voting/controller/selector/SimpleListCategoriesSelector.java b/voting-booth/src/main/java/meerkat/voting/controller/selector/SimpleListCategoriesSelector.java index 6181f05..7f2af87 100644 --- a/voting-booth/src/main/java/meerkat/voting/controller/selector/SimpleListCategoriesSelector.java +++ b/voting-booth/src/main/java/meerkat/voting/controller/selector/SimpleListCategoriesSelector.java @@ -11,28 +11,47 @@ import java.lang.Math; /** * A simple implementation of a QuestionSelector. * This implementation simply regards every single answer in the channel choice phase as an identifier of a category - * Every category is an array of ballot questions. + * Every category is an array of ballot race questions. * Data of categories is initialized and stored by a SimpleCategoriesSelectionData protobuf. * After receiving the answers from a channel choice phase, this class simply gathers all the categories * chosen and compiles the list of ballot questions to include in the ballot for this voter (a question - * is included if its index appears in any chosen category, or in the default category shared by all voters) + * is included in the ballot if its index appears in any chosen category, or in the default category shared by all voters) */ public class SimpleListCategoriesSelector implements QuestionSelector { protected final static Logger logger = LoggerFactory.getLogger(SimpleListCategoriesSelector.class); + // all the possible race questions private final BallotQuestion[] allBallotQuestions; + + // this category is presented to any voter (regardless of his answers to the channel choice questions) private final int[] sharedDefaults; + + // all the categories. + // first index is the channel choice question number + // second index is a possible answer to this question + // categoryChoosers[questionNumber][answerNumber] is an array of indices (to the ballotQuestions array). + // This category of questions is included in the ballot if voter answered this specific answer to this channel choice question private final int[][][] categoryChoosers; + private final static byte QUESTION_SELECTED = (byte)1; private final static byte QUESTION_NOT_SELECTED = (byte)0; - + /** + * A very straight-forward constructor for the SimpleListCategoriesSelector + * @param allBallotQuestions all possible race questions for this election + * @param data a protobuf containing all the index categories + */ public SimpleListCategoriesSelector(List allBallotQuestions, SimpleCategoriesSelectionData data) { + // copies the ballot race question list into a member array this.allBallotQuestions = new BallotQuestion[allBallotQuestions.size()]; allBallotQuestions.toArray(this.allBallotQuestions); + + // copies the shared category list (as appears in the protobuf data) into a member array sharedDefaults = listToIntArray(data.getSharedDefaults().getQuestionIndexList()); + + // copies the category lists (as appear in the protobuf data) into a 3-dimensional member array int[][][] selectionDataTmp = new int[data.getCategoryChooserList().size()][][]; int channelChoiceQuestionNumber = 0; for (CategoryChooser catChooser: data.getCategoryChooserList()) { @@ -45,12 +64,21 @@ public class SimpleListCategoriesSelector implements QuestionSelector { ++channelChoiceQuestionNumber; } categoryChoosers = selectionDataTmp; + + // verifies in advance that there are not very suspicious indices in the selection data assertDataValid(); } + /* + * asserts that the selection data does not contain a question index which is beyond the length of + * the ballot race questions array. Otherwise, throws an IndexOutOfBoundsException + */ private void assertDataValid () { - int questionsLength = allBallotQuestions.length; + // find the maximum question index in the selection data int maxQuestionIndex = -1; + for (int index: sharedDefaults) { + maxQuestionIndex = Math.max(maxQuestionIndex, index); + } for (int[][] categoryChooser: categoryChoosers) { for (int[] category: categoryChooser) { for (int index: category) { @@ -58,6 +86,9 @@ public class SimpleListCategoriesSelector implements QuestionSelector { } } } + + // asserts that the maximal question index in the selection data does not overflow the ballot race questions array + int questionsLength = allBallotQuestions.length; if (maxQuestionIndex >= questionsLength) { String errorMessage = "Selection data refers to question index " + maxQuestionIndex + " while we have only " + questionsLength + " questions totally"; logger.error(errorMessage); @@ -66,8 +97,21 @@ public class SimpleListCategoriesSelector implements QuestionSelector { } + /** + * an implementation of the QuestionSelector interface method. + * In this selector class the identifier simply marks all the ballot race questions which appear in at least one + * category of the categories chosen by the voter (or in the shared defaults category) in the channel choice round. + * @param channelChoiceAnswers The answers given by the voter to the channel choice questions + * @return the channel identifier + */ @Override public byte[] getChannelIdentifier(List channelChoiceAnswers) { + /* + * Currently, this implementation of the QuestionSelector interface returns an over-simplified identifier which + * is merely an array of booleans (which flags the questions to appear in the ballot) + * For elections with more than one possible channel we should return a more printable and recognizable + * identifier to be put in the plaintext of the ballot + */ byte[] isSelected = new byte[allBallotQuestions.length]; java.util.Arrays.fill(isSelected, QUESTION_NOT_SELECTED); @@ -86,6 +130,10 @@ public class SimpleListCategoriesSelector implements QuestionSelector { return isSelected; } + /* + * Verifies that the ballot answer is of length 1. (We do not yet handle multi-choice questions in the channel choice round). + * Otherwise, throws an exception. + */ private void assertAnswerLengthIsOne (BallotAnswer ballotAnswer, int questionNumber) { if (ballotAnswer.getAnswerCount() != 1) { String errorMessage = "SimpleListCategoriesSelector expects a single answer for every channel choice question\n"; @@ -109,6 +157,9 @@ public class SimpleListCategoriesSelector implements QuestionSelector { return selectedQuestions; } + /* + * copies a List of Integers into an int[] array of same length + */ private int[] listToIntArray(List l) { int[] res = new int[l.size()]; int index = 0;