Java tutorial
/* * File: $HeadURL$ * Version: $LastChangedRevision$ * Date: $Date$ * Author: $LastChangedBy$ * * JVoiceXML - A free VoiceXML implementation. * * Copyright (C) 2005-2012 JVoiceXML group - http://jvoicexml.sourceforge.net * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package org.jvoicexml.interpreter; import java.util.Collection; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.log4j.Logger; import org.jvoicexml.event.error.SemanticError; import org.jvoicexml.interpreter.datamodel.DataModel; import org.jvoicexml.xml.VoiceXmlNode; import org.jvoicexml.xml.vxml.Prompt; /** * When a prompt must be chosen, a set of prompts to be queued is chosen * according to the following algorithm: * * <ol> * <li> * Form an ordered list of prompts consisting of all prompts in the * enclosing element in document order. * </li> * <li> * Remove from this list all prompts whose <code>cond</code> evaluates to false * after conversion to boolean. * </li> * <li> * Find the <em>correct count</em>: the highest count among the prompt elements * still on the list less than or equal to the current count value. * </li> * <li> * Remove from the list all the elements that don't have the * <em>correct count</em>. * </li> * </ol> * * <p> * All elements that remain on the list will be queued for play. * </p> * * @author Dirk Schnelle-Walka * @version $Revision$ */ final class PromptChooser { /** Logger for this class. */ private static final Logger LOGGER = Logger.getLogger(PromptChooser.class); /** The prompt countable item for which prompts should be chosen. */ private final PromptCountable countable; /** The current VoiceXML interpreter context. */ private final VoiceXmlInterpreterContext context; /** * Constructs a new <code>PromptChooser</code> for the given * <code>FormItem</code>. * * @param cnt The countable input item for which prompts should be chosen. * @param ctx The current VoiceXML interpreter context. */ public PromptChooser(final PromptCountable cnt, final VoiceXmlInterpreterContext ctx) { countable = cnt; context = ctx; } /** * Retrieves the list of prompts that will be queued for play. * * @return Collection of prompts that will be queued for play. * @exception SemanticError * Error evaluating the condition. */ public Collection<Prompt> collect() throws SemanticError { final int count = countable.getPromptCount(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("find all prompts of '" + countable.getName() + "' with count " + count); } final Collection<Prompt> allPrompts = findAllPrompts(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("found " + allPrompts.size() + " prompt(s) in '" + countable.getName() + "'"); } final Collection<Prompt> condPrompts = filterCond(allPrompts); if (LOGGER.isDebugEnabled()) { LOGGER.debug("found " + condPrompts.size() + " prompt(s) after cond evaluation in '" + countable.getName() + "'"); } final int highestCount = findHighestCount(condPrompts, count); if (LOGGER.isDebugEnabled()) { LOGGER.debug("highest count of " + countable.getName() + "' is " + highestCount + " <= " + count); } final Collection<Prompt> correctCountPrompts = filterCount(condPrompts, highestCount); if (LOGGER.isDebugEnabled()) { LOGGER.debug("found " + correctCountPrompts.size() + " prompt(s) with count " + highestCount + " in '" + countable.getName() + "'"); } return correctCountPrompts; } /** * Form an ordered list of prompts consisting of all prompts in the * enclosing element in document order. * * @return List of prompts. */ private Collection<Prompt> findAllPrompts() { final VoiceXmlNode node = countable.getNode(); return node.getChildNodes(Prompt.class); } /** * Remove from this list all prompts whose cond evaluates to false after * conversion to boolean. * * @param prompts Collection of prompts to be filtered. * @return list of filtered prompts. * * @exception SemanticError * Error evaluating the condition. */ private Collection<Prompt> filterCond(final Collection<Prompt> prompts) throws SemanticError { final Collection<Prompt> filteredPrompts = new java.util.ArrayList<Prompt>(); final DataModel model = context.getDataModel(); for (Prompt prompt : prompts) { final String cond = prompt.getCond(); final String unescapedCond = StringEscapeUtils.unescapeXml(cond); final boolean result = model.evaluateExpression(unescapedCond, Boolean.class); if (result) { filteredPrompts.add(prompt); } } return filteredPrompts; } /** * Find the <em>correct count</em>: the highest count among the prompt * elements still on the list less than or equal to the current count value. * * @param prompts Collection of prompts to examine. * @param count The current count value. * * @return highest count among the prompts. */ private int findHighestCount(final Collection<Prompt> prompts, final int count) { int highestCount = 0; for (Prompt prompt : prompts) { final int currentCount = prompt.getCountAsInt(); if (currentCount <= count) { if (currentCount > highestCount) { highestCount = currentCount; } } } return highestCount; } /** * Remove from the list all the elements that don't have the * <em>correct count</em>. * * @param prompts Collection of prompts to be filtered. * @param count The correct count. * @return Collection of prompts with the correct count. */ private Collection<Prompt> filterCount(final Collection<Prompt> prompts, final int count) { final Collection<Prompt> filteredPrompts = new java.util.ArrayList<Prompt>(); for (Prompt prompt : prompts) { final int currentCount = prompt.getCountAsInt(); if (currentCount == count) { filteredPrompts.add(prompt); } } return filteredPrompts; } }