org.jvoicexml.interpreter.formitem.AbstractFormItem.java Source code

Java tutorial

Introduction

Here is the source code for org.jvoicexml.interpreter.formitem.AbstractFormItem.java

Source

/*
 * File:    $HeadURL$
 * Version: $LastChangedRevision$
 * Date:    $Date$
 * Author:  $LastChangedBy$
 *
 * JVoiceXML - A free VoiceXML implementation.
 *
 * Copyright (C) 2005-2014 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.formitem;

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.FormItem;
import org.jvoicexml.interpreter.FormItemLocalExecutableTagContainer;
import org.jvoicexml.interpreter.VoiceXmlInterpreterContext;
import org.jvoicexml.interpreter.datamodel.DataModel;
import org.jvoicexml.xml.VoiceXmlNode;
import org.jvoicexml.xml.vxml.AbstractCatchElement;
import org.jvoicexml.xml.vxml.Property;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Base functionality of a {@link FormItem}.
 * <p>
 * Each {@link FormItem} has an associated variable with its name that can be
 * retrieved by {@link #getName()} in the {@link ScriptingEngine}.
 * </p>
 *
 * @author Dirk Schnelle-Walka
 * @version $Revision$
 */
abstract class AbstractFormItem implements FormItem, FormItemLocalExecutableTagContainer {
    /** Logger for this class. */
    private static final Logger LOGGER = Logger.getLogger(AbstractFormItem.class);

    /** The current <code>VoiceXmlInterpreterContext</code>. */
    private final VoiceXmlInterpreterContext context;

    /** The corresponding xml node in the VoiceXML document. */
    private final VoiceXmlNode node;

    /**
     * The name of a dialog-scoped form item variable that will hold the name of
     * the form item.
     */
    private final String name;

    /**
     * Constructs a new form item as a template.
     */
    public AbstractFormItem() {
        node = null;
        context = null;
        name = null;
    }

    /**
     * Create a new form item.
     *
     * @param ctx
     *            The current <code>VoiceXmlInterpreterContext</code>.
     * @param voiceNode
     *            The corresponding XML node in the VoiceXML document.
     */
    public AbstractFormItem(final VoiceXmlInterpreterContext ctx, final VoiceXmlNode voiceNode) {
        node = voiceNode;
        context = ctx;
        name = FormItemNameFactory.getName(node);
    }

    /**
     * Factory method to create a new instance from a template.
     * 
     * @param ctx
     *            The current <code>VoiceXmlInterpreterContext</code>.
     * @param voiceNode
     *            The corresponding XML node in the VoiceXML document.
     * @return created form item
     * @since 0.7.6
     */
    public abstract AbstractFormItem newInstance(final VoiceXmlInterpreterContext ctx,
            final VoiceXmlNode voiceNode);

    /**
     * {@inheritDoc}
     * 
     * @return retrieves the value of the associated variable in the
     *         {@link DataModel}
     */
    @Override
    public final Object getFormItemVariable() {
        final DataModel model = context.getDataModel();
        try {
            return model.readVariable(name, Object.class);
        } catch (SemanticError ignore) {
            // In this case, the form item variable is simply undefined.
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("retrieved undefined form item variable");
            }
            return null;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int setFormItemVariable(final Object value) throws SemanticError {
        final DataModel model = context.getDataModel();
        return model.updateVariable(name, value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final String getName() {
        return name;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final Object evaluateExpression(final DataModel model) throws SemanticError {
        final String expr = node.getAttribute("expr");
        final String unescapedExpr = StringEscapeUtils.unescapeXml(expr);
        return model.evaluateExpression(unescapedExpr, Object.class);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean evaluateCondition() throws SemanticError {
        final String condAttribute = node.getAttribute("cond");
        if (condAttribute == null) {
            return true;
        }
        final String unescapedCond = StringEscapeUtils.unescapeXml(condAttribute);
        final DataModel model = context.getDataModel();
        return model.evaluateExpression(unescapedCond, Boolean.class);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isSelectable() throws SemanticError {
        final Object result = getFormItemVariable();
        final boolean cond = evaluateCondition();
        final DataModel model = context.getDataModel();
        final boolean selectable = ((result == model.getUndefinedValue()) || (result == null)) && cond;

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("checking if selectable");
            final String logResult = model.toString(result);
            LOGGER.debug("value of   '" + name + "': '" + logResult + "'");
            LOGGER.debug("cond of    '" + name + "': '" + cond + "'");
            LOGGER.debug("selectable '" + name + "': " + selectable);
        }

        return selectable;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final VoiceXmlNode getNode() {
        return node;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final String getNodeTagName() {
        if (node == null) {
            return null;
        }
        return node.getTagName();
    }

    /**
     * Retrieves the current {@link VoiceXmlInterpreterContext}.
     *
     * @return the current <code>VoiceXmlInterpreterContext</code>.
     */
    protected final VoiceXmlInterpreterContext getContext() {
        return context;
    }

    /**
     * Retrieves all nested catch elements.
     * 
     * @return all nested catch elements
     */
    public Collection<AbstractCatchElement> getCatchElements() {
        if (node == null) {
            return null;
        }

        final Collection<AbstractCatchElement> catches = new java.util.ArrayList<AbstractCatchElement>();
        final NodeList children = node.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            final Node child = children.item(i);
            if (child instanceof AbstractCatchElement) {
                final AbstractCatchElement catchElement = (AbstractCatchElement) child;
                catches.add(catchElement);
            }
        }

        return catches;
    }

    /**
     * {@inheritDoc}
     */
    public Collection<VoiceXmlNode> getLocalExecutableTags() {
        if (node == null) {
            return null;
        }

        final Collection<VoiceXmlNode> nodes = new java.util.ArrayList<VoiceXmlNode>();
        final NodeList children = node.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            final Node child = children.item(i);
            if (child instanceof Property) {
                final VoiceXmlNode voiceXmlNode = (VoiceXmlNode) child;
                nodes.add(voiceXmlNode);
            }
        }

        return nodes;
    }
}