Управление ветвлением опроса
В листинге 7.15 показан метод setBranch, который вызывается из метода doPostQ, когда ответ пользователя на данный вопрос определяет выбор очередной ветви опроса. Этот метод просто просматривает все элементы ВТ ock и ищет имя (значение атрибута name), совпадающее с заданным именем блока. В этом методе также устанавливаются значения переменных nowBlock и nowNode.
Листинг 7.15. Метод setBranch (Interpreter.java)
// jump to another block has been detected private void setBranch(String block ){ int ct = blockNodeList.getLength(); for( int i = 1 ; i < ct ; i++ ){ // block 0 was the start nowBlock = blockNodeList.item(i); String name = ((Element)nowBlock).getAttribute("name"); if( name.equals( block )){ checkBlockType() ; // to set terminal flag setQnodeInBlock( 0 ) ; // set nowNode return ; } } System.err.println("Interpreter.setBranch failed to find " + block ); nowBlock = nowNode = null ; }
Метод doPostQ, начало которого приводится в листинге 7.16, вызывается из метода doPost и управляет созданием новой HTML-страницы. Обратите внимание на то, что в первую очередь этот метод проверяет, не был ли зафиксирован соответствующим объектом Recorder тот факт, что опрос завершен. Это сделано для того, чтобы пользователь не мог с помощью кнопки Back (Назад) браузера возвратиться на предыдущую страницу для ввода данных, когда опрос уже завершен и данные записаны.
Следующая часть кода отводится для обработки специального случая, когда переменная quesid равна intro, то есть вопрос является первым в анкете. Во всех других случаях ответ пользователя записывается путем сравнения значений opt, взятых из формы, с атрибутами тега Qopt с помощью объекта Recorder этого сеанса.
Листинг 7.16. Начало метода doPost (Interpreter.java)
// req contains user response public void doPostQ( PrintWriter out, HttpServletRequest req, Recorder recordB ){ if( recordB.terminated ){ writeHead( out ); out.println("<b>This questionnaire has been terminated</b>"); return ; } String action = req.getParameter("action"); String quesid = req.getParameter("quesid"); if( !action.equals("Next") ){ out.println("Unexpected state in Interpreter.doPost<br>"); return ; } if( quesid.equals("intro") ){ // this calls for generating first question // doIntro already set nowNode to first <Ques> node genQuest( out ); return ; } // if here, not generating first question, examine request Element E = (Element) nowNode ; NodeList oplist = E.getElementsByTagName("Qopt"); int type = lookUpType( E.getAttribute("type")); String lim = E.getAttribute("limit"); // ? String[] optS = req.getParameterValues("opt"); recordB.record( quesid, type, optS );
Следующий шаг метода doPostQ, как показано в листинге 7.17, сводится к тому, чтобы определить, инициирует ли последний записанный ответ пользователя переход к новой ветви опроса. Естественно, новая ветвь начинается с первого вопроса в блоке, как указано в методе setBranch. Если переходить на новую ветвь не нужно, определяется место данного вопроса в текущем элементе Block и выполняется переход к следующему вопросу. Также нужно предусмотреть ситуацию, когда элемент, следующий за текущим вопросом, является завершающим; в этом случае мы вызываем метод getTerminal, функции которого описаны в следующем разделе и связаны с формированием последней страницы опроса.
Листинг 7.17. Метод doPost, продолжение (Interpreter.java)
String branch = branchLookUp( oplist, optS ); if( branch != null ){ //System.out.println("Taking Branch:" + branch ); setBranch( branch ); // sets nowBlock and nowNode to new value if( nowNode == null ) genTerminal( out, recordB ); else genQuest( out ); return ; }
// branch is null, nowBlock has 1 or more <Ques NodeList qlist = ((Element)nowBlock).getElementsByTagName("Ques"); int n = 0 ; int nct = qlist.getLength(); while( qlist.item(n) != nowNode && n < nct ) n++ ; // n = nowNode Node nxtN = qlist.item(n+1); if( nxtN != null ){ nowNode = nxtN ; genQuest( out ); System.out.println("Found nextQ"); return ; } if( terminal ) genTerminal( out, recordB ); else out.println("nextQ NULL, not terminal<br>" ); } // end doPostQ