I have been thinking about how to design this, and this is what I have in mind. I'd like to know what others think.
I think that there are 3 types of questions that we can ask via an interactive session:
- Y/N question
- M/C question
- Short answer question
For example, the "show server" function has 4 options - all (a), host (h), port (p), webapp (w). When the user types "show server" and hits enter, the question should be like this:
Q1. Select one [a/h/p/w]: _ <enter>
On the other hand, the user types "set server" and hits enter, the question should be like this:
Q1. Hostname: ___ <enter>
Q2. Port number: ___ <enter>
Q3. Web app name: ___ <enter>
Lastly, there is Y/N question such as:
Q1. Hive import [y/n]: _ <enter>
The challenge is that sometimes multiple options form a question (M/C question), and sometimes one option forms a question (short answer question, Y/N question). Granted, I could always present an option as one question. For example,
Q1. all [y/n]: _ <enter>
Q2. host [y/n]: _ <enter>
Q3. port [y/n]: _ <enter>
Q4. webapp [y/n]: _ <enter>
But this seems rather strange to me.
To handle this, I organize options into sub-groups using OptionGroup class. Logically, each OptionGroup represents a group of options that form a question. In my example, options for "show server" (a/h/p/w) are placed in one group while options for "set server" (hostname, port number, web app name) are placed in multiple groups. Therefore, they can be asked as one question and multiple questions respectively.
2) getOptionsViaInteractiveSession() method
Interactive session is implemented in a method with the following signature:
CommandLine getOptionsViaInteractiveSession(IO io, List<Question> questions)
The idea is that each function (e.g. show server, set server, etc) passes a list of Question instances, and this method iterates through them, prints them to, and read input from stdout. At the end, I call parseOptions() with collected input.
3) Question classes
I define a hierarchy of classes as follows:
Question extends OptionGroup
YesNoQuestion extends Question
MultiChoiceQuestion extends Question
ShortAnswerQuestion extends Question
These classes are essentially all OptionGroup, but additionally, they define some question-type-specific behaviors. In particular, Question class defines a method print() that each sub-class overrides. Then, getOptionsViaInteractiveSession() can simply go over a list of Question instances and invokes the print() method to print different types of questions.
4) From MForm to OptionGroup
One thing that is not very clear to me now is how to map MInput (Option) to Question (OptionGroup). In the current implementation of MInput, the concept of OptionGroup does not exist. I might have to add additional fields to indicate which group options belong to.
Please let me know if you have any concerns and/or questions. If everyone is fine with my design, I will go ahead commit the implementation.