Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 2 of 2
Listing 3. QuestionInteraction.java
// Implement this interface to display question and accept answer
public interface QuestionInteraction
{
// Use of double dispatch when the implementation of this interface
// sets the answer (second dispatch)
public void answer(Question q);
}
Listing 4 shows an interface for loading the actions. This interface does not restrict the data in any way. A potential implementation
could read the survey from file(s) or a database, and the data format could be XML or any other structure. The only contract
this interface requires is that the implementation must create appropriate Actions:
Listing 4. ActionSource.java
// Interface to provide the source of all actions. The actions
// are already wired together (decision tree).
public interface ActionSource
{
/** Get the starting action. */
public Action getStartingAction();
/** Get the action given its ID. */
public Action getAction(String id);
}
Once the survey content loads and the logic is all wired together, we need a controller class (ActionFlow shown in Listing 5) to facilitate the navigation and execution of one action at a time:
Listing 5. ActionFlow.java
public class ActionFlow
{
//......
/** Set the source of the actions. */
public void setSource(ActionSource src) {
actionSource_ = src;
if (src != null)
currentAction_ = src.getStartingAction();
}
public boolean isComplete() { return complete_; }
public Action getCurrentAction() { return currentAction_; }
/** Move forward one step in the flow, if possible. */
public void moveForward()
{
//......
Action next = getNextAction();
if (next != null)
{
next.setPreviousAction(currentAction_);
currentAction_ = next; //move forward
}
//......
}
/** Move backward one step in the flow, if possible.
* Otherwise, stay at current step. */
public void moveBackward()
{
//......
Action prev = currentAction_.getPreviousAction();
if (prev != null) {
currentAction_.setPreviousAction(null);
currentAction_ = prev; //move backward
complete_ = false;
}
}
/** Answer the current question (current step is assumed to
* be a Question). */
public void perform()
{
currentAction_.perform();
moveForward();
}
}
Putting things together, we now get something like below for the client code:
try {
System.out.println("Processing file " + dataFile);
final DocumentBuilder db = getDocBuilder(); // Get an XML document builder
final Document doc = db.parse(new FileInputStream(dataFile));
ActionLoader loader = new ActionLoader(doc);
ActionFlow flow = new ActionFlow(loader);
while (!flow.isComplete())
flow.perform();
}
catch (...) {
}
On the client code, we have ActionLoader, which implements ActionSource. This class parses XML survey content and builds the appropriate decision tree by wiring the questions together (implemented
as QuestionConcrete).
The XML survey content could look something like below:
<act:ActionList version="1.0" xmlns:act="http://www.good_thang.net/xmlns/ActionList">
<act:Action id="1" type="Question">
<act:Content value="What type of vehicle did you purchase?" />
<act:Explanation value="Pick your choice" />
<act:AnswerList>
<act:Answer value="Car" consequence="2" />
<act:Answer value="Truck" consequence="3" />
<act:Answer value="SUV" consequence="4" />
</act:AnswerList>
</act:Action>
<act:Action id="2" type="Question">
<act:Content value="What type of car?" />
<act:AnswerList>
<act:Answer value="Sport Coupe" />
<act:Answer value="Sedan" />
</act:AnswerList>
</act:Action>
<act:Action id="3" type="Question">
<act:Content value="What type of truck?" />
<act:AnswerList>
<act:Answer value="Pickup" />
<act:Answer value="4x4" />
</act:AnswerList>
</act:Action>
<act:Action id="4" type="Question">
<act:Content value="Which brand of SUV?" />
<act:AnswerList>
<act:Answer value="Fore Runner" />
<act:Answer value="Passport" />
<act:Answer value="Path Finder" />
</act:AnswerList>
</act:Action>
</act:ActionList>
This article illustrates a simple and extendable solution for managing complex surveys by presenting only the surveying questions applicable to the audience. The solution also applies to other problems that require the user to make choices within a complex decision tree, such as interviewing users, selecting menu options, and so on. With this solution, the survey (or menu, or interviewing) content and how it should be conducted (logic) can be decoupled from the code, allowing fast and low-cost development.
Archived Discussions (Read only)