org.jvoicexml.interpreter.SubdialogExecutorThread.java Source code

Java tutorial

Introduction

Here is the source code for org.jvoicexml.interpreter.SubdialogExecutorThread.java

Source

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

import java.net.URI;
import java.util.Map;

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.jvoicexml.Application;
import org.jvoicexml.DocumentDescriptor;
import org.jvoicexml.event.EventBus;
import org.jvoicexml.event.JVoiceXMLEvent;
import org.jvoicexml.event.error.SemanticError;
import org.jvoicexml.event.plain.jvxml.ReturnEvent;
import org.jvoicexml.event.plain.jvxml.SubdialogResultEvent;
import org.jvoicexml.interpreter.datamodel.DataModel;

/**
 * Asynchronous execution of a subdialog.
 * 
 * @author Dirk Schnelle-Walka
 * @version $Revision$
 * @since 0.7.4
 */
final class SubdialogExecutorThread extends Thread {
    /** Logger for this class. */
    private static final Logger LOGGER = Logger.getLogger(SubdialogExecutorThread.class);

    /** The URI of the subdialog. */
    private final URI uri;

    /** The context of the subdialog. */
    private final VoiceXmlInterpreterContext context;

    /** The current application. */
    private final Application application;

    /** The event bus to propagate errors and results. */
    private final EventBus eventbus;

    /** Parameters of the subdialog call. */
    private final Map<String, Object> parameters;

    /**
     * Constructs a new object.
     * 
     * @param subdialogUri
     *            the URI of the subdialog
     * @param subdialogContext
     *            the context of the subdialog
     * @param appl
     *            the current application
     * @param params
     *            parameters of the subdialog call
     * @param bus
     *            the event bus of the calling context to correctly propagate
     *            messages
     */
    public SubdialogExecutorThread(final URI subdialogUri, final VoiceXmlInterpreterContext subdialogContext,
            final Application appl, final Map<String, Object> params, final EventBus bus) {
        uri = subdialogUri;
        context = subdialogContext;
        application = appl;
        eventbus = bus;
        parameters = params;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void run() {
        final DataModel model = context.getDataModel();
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("initializing parameters...");
        }
        for (String name : parameters.keySet()) {
            final Object value = parameters.get(name);
            model.createVariable(name, value);
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("...initialized parameters");
        }
        try {
            final DocumentDescriptor descriptor = new DocumentDescriptor(uri);
            context.processSubdialog(application, descriptor);
        } catch (ReturnEvent e) {
            final Object result;
            try {
                result = getReturnObject(e);
            } catch (SemanticError sematicerror) {
                eventbus.publish(sematicerror);
                return;
            }
            final SubdialogResultEvent event = new SubdialogResultEvent(result);
            eventbus.publish(event);
            return;
        } catch (JVoiceXMLEvent e) {
            eventbus.publish(e);
            return;
        }
        // The VoiceXML spec leaves it open what should happen if there was no
        // return or exit and the dialog terminated because all forms were
        // processed. So we return TRUE in this case.
        final SubdialogResultEvent event = new SubdialogResultEvent(Boolean.TRUE);
        eventbus.publish(event);
    }

    /**
     * Creates the value for the returned result.
     * 
     * @param event
     *            caught event.
     * @return return result.
     * @throws SemanticError
     *             if a variable could not be evaluated
     */
    private Object getReturnObject(final ReturnEvent event) throws SemanticError {
        final StringBuilder str = new StringBuilder();
        str.append("var out = new Object();");
        final Map<String, Object> variables = event.getVariables();
        for (String name : variables.keySet()) {
            str.append("out.");
            str.append(name);
            str.append(" = ");
            final Object value = variables.get(name);
            if (value instanceof String) {
                str.append("\"");
                str.append(value);
                str.append("\"");
            } else {
                str.append(value);
            }
            str.append(";");
        }
        final DataModel model = context.getDataModel();
        final String expr = str.toString();
        final String unescapedExpr = StringEscapeUtils.unescapeXml(expr);
        model.evaluateExpression(unescapedExpr, Object.class);
        return model.readVariable("out", Object.class);
    }
}