JVoiceXmlGrammarProcessor.java :  » XML » jvxml-0.7.2 » org » jvoicexml » interpreter » grammar » Java Open Source

Java Open Source » XML » jvxml 0.7.2 
jvxml 0.7.2 » org » jvoicexml » interpreter » grammar » JVoiceXmlGrammarProcessor.java
/*
 * File:    $HeadURL: https://jvoicexml.svn.sourceforge.net/svnroot/jvoicexml/core/trunk/org.jvoicexml/src/org/jvoicexml/interpreter/grammar/JVoiceXmlGrammarProcessor.java $
 * Version: $LastChangedRevision: 1823 $
 * Date:    $Date $
 * Author:  $LastChangedBy: schnelle $
 *
 * JVoiceXML - A free VoiceXML implementation.
 *
 * Copyright (C) 2005-2009 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.grammar;

import java.net.URI;
import java.util.Collection;

import org.apache.log4j.Logger;
import org.jvoicexml.FetchAttributes;
import org.jvoicexml.GrammarDocument;
import org.jvoicexml.GrammarImplementation;
import org.jvoicexml.ImplementationPlatform;
import org.jvoicexml.UserInput;
import org.jvoicexml.config.JVoiceXmlConfiguration;
import org.jvoicexml.documentserver.JVoiceXmlGrammarDocument;
import org.jvoicexml.event.error.BadFetchError;
import org.jvoicexml.event.error.NoresourceError;
import org.jvoicexml.event.error.UnsupportedFormatError;
import org.jvoicexml.event.plain.ConnectionDisconnectHangupEvent;
import org.jvoicexml.interpreter.ActiveGrammarSet;
import org.jvoicexml.interpreter.GrammarProcessor;
import org.jvoicexml.interpreter.ProcessedGrammar;
import org.jvoicexml.interpreter.VoiceXmlInterpreterContext;
import org.jvoicexml.xml.srgs.Grammar;
import org.jvoicexml.xml.srgs.GrammarType;
import org.jvoicexml.xml.srgs.ModeType;

/**
 * The <code>GrammarProcessor</code> is the main entry point for
 * grammar processing.<br>
 * This class provides a lean method interface to process a grammar
 * in a VoiceXML file.
 *
 * @author Christoph Buente
 * @author Dirk Schnelle-Walka
 * @version $Revision: 1823 $
 */
public final class JVoiceXmlGrammarProcessor
        implements GrammarProcessor {
    /**
     * Logger for this class.
     */
    private static final Logger LOGGER =
            Logger.getLogger(JVoiceXmlGrammarProcessor.class);

    /**
     * This helper has some helper methods to perform several tasks.
     */
    private final GrammarProcessorHelper helper;

    /** grammar identifier central. */
    private GrammarIdentifierCentral identifier;

    /** The grammar transformer central. */
    private GrammarTransformerCentral transformer;

    /**
     * Private constructor to prevent manual instantiation.
     */
    public JVoiceXmlGrammarProcessor() {
        helper = new GrammarProcessorHelper();
        identifier = new GrammarIdentifierCentral();
        transformer = new GrammarTransformerCentral();
    }

    /**
     * {@inheritDoc}
     */
    public void init(final JVoiceXmlConfiguration configuration) {
        final Collection<GrammarIdentifier> identifiers =
            configuration.loadObjects(GrammarIdentifier.class, "jvxmlgrammar");
        for (GrammarIdentifier current : identifiers) {
            identifier.addIdentifier(current);
        }
        final Collection<GrammarTransformer> transformers =
            configuration.loadObjects(GrammarTransformer.class, "jvxmlgrammar");
        for (GrammarTransformer current : transformers) {
            transformer.addTransformer(current);
        }
    }

    /**
     * Sets the central to identify grammars.
     * @param central GrammarIdentifierCentral
     * @since 0.5
     */
    public void setGrammaridentifier(final GrammarIdentifierCentral central) {
        identifier = central;
    }

    /**
     * Sets the central to transform grammars.
     * @param central GrammarTransformerCentral
     * @since 0.5
     */
    public void setGrammartransformer(final GrammarTransformerCentral central) {
        transformer = central;
    }

    /**
     * {@inheritDoc}
     */
    public ProcessedGrammar process(
            final VoiceXmlInterpreterContext context,
            final FetchAttributes attributes,
            final Grammar grammar,
            final ActiveGrammarSet grammars)
            throws NoresourceError, BadFetchError, UnsupportedFormatError {
        /*
         * check if grammar is external or not an process with
         * appropriates methods
         */
        final GrammarDocument document;
        if (helper.isExternalGrammar(grammar)) {
            document = processExternalGrammar(context, attributes, grammar);
        } else {
            document = processInternalGrammar(grammar);
        }

        // If the grammar is already processed, we assume that this has been
        // done using the correct transformer.
        // However, it may happen, that there are different engines with
        // different formats. This may result in an error.
        if (grammars.contains(document)) {
            final ProcessedGrammar processed = grammars.get(document);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("grammar already processed: "
                        + document.getDocument());
                LOGGER.debug("grammar implementation: "
                        + processed.getImplementation());
            }

            return processed;
        }

        /*
         * now, we have the content of the grammar as well as the
         * type. Now transfer this grammar into a valid grammar object
         */
        final ImplementationPlatform platform =
            context.getImplementationPlatform();
        final UserInput input;
        try {
            input = platform.getUserInput();
        } catch (ConnectionDisconnectHangupEvent e) {
            throw new NoresourceError(e.getMessage(), e);
        }

        // This happens only for grammars that are defined in the form.
        final GrammarImplementation<?> grammarImpl;
        final ModeType mode = grammar.getMode();
        grammarImpl = transformer.createGrammar(input, document, mode);

        /*
         * finally add the grammar to a scoped Map
         */
        final ProcessedGrammar processed =
            new ProcessedGrammar(document, grammarImpl);
        grammars.add(processed);
        return processed;
    }

    /**
     * Takes the route of processing an inline grammar. In fact, it
     * just identifies the grammar and puts it into a temporary
     * container. The container used is the ExternalGrammar, that can
     * hold the grammar as a String representation as well as the
     * corresponding media type, if one is applicable.
     *
     * @param grammar
     *        Takes a VoiceXML Node and processes the contained
     *        grammar.
     *
     * @return The result of the processing. A grammar
     *         representation which can be used to transform into a
     *         RuleGrammar.
     * @throws UnsupportedFormatError
     *         If the grammar could not be identified. This means, the
     *         grammar is not valid or (even worse) not supported.
     */
    private GrammarDocument processInternalGrammar(final Grammar grammar)
            throws UnsupportedFormatError {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("process internal grammar");
        }

        final String grammarBuffer = grammar.toString();
        final GrammarDocument document =
            new JVoiceXmlGrammarDocument(grammarBuffer);

        final GrammarType actualType =
            identifier.identifyGrammar(document);

        if (actualType != null) {
            document.setMediaType(actualType);
        } else {
            GrammarType type = grammar.getType();
            LOGGER.warn("Unable to identify the type of the grammar. "
                    + "Traying to continue with suggested type: " + type);
            document.setMediaType(type);
        }

        return document;

    }

    /**
     * Take the route of processing an external grammar.
     *
     * @param context
     *        The current context
     * @param attributes
     *        attributes governing the fetch.
     * @param grammar
     *        The grammar to be processed.
     *
     * @return Is just the string representation of the
     *         grammar as well as the type.
     *
     * @throws UnsupportedFormatError
     *         If an unsupported grammar has to be processed.
     * @throws BadFetchError
     *         If the document could not be fetched successfully.
     */
    private GrammarDocument processExternalGrammar(
            final VoiceXmlInterpreterContext context,
            final FetchAttributes attributes, final Grammar grammar)
            throws BadFetchError, UnsupportedFormatError {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("process external grammar");
        }

        // First of all, we need to check, if user has provided any
        // grammar type.
        final URI src;
        try {
            src = grammar.getSrcUri();
        } catch (java.net.URISyntaxException use) {
            throw new BadFetchError(use);
        }

        final FetchAttributes adaptedAttributes =
            adaptFetchAttributes(attributes, grammar);
        final GrammarDocument document =
                context.acquireExternalGrammar(src, adaptedAttributes);
        if (document == null) {
            throw new BadFetchError("Unable to load grammar '" + src + "'!");
        }

        // now we need to know the actual type.
        final GrammarType actualType =
                identifier.identifyGrammar(document);
        // let's check, if the declared type is supported.
        if (actualType == null) {
            throw new BadFetchError(grammar.getType() + " is not supported.");
        }

        document.setMediaType(actualType);

        /**
         * @todo check preferred and declared (from the grammar object) type.
         */

        // Yes they really match. return the external grammar.
        return document;
    }

    /**
     * Extracts the fetch attributes from the grammar and overrides the
     * settings of the document default fetch attributes.
     * @param docAttributes fetch attributes for the document.
     * @param grammar the current grammar.
     * @return attributes governing the fetch.
     */
    private FetchAttributes adaptFetchAttributes(
            final FetchAttributes docAttributes, final Grammar grammar) {
        final FetchAttributes attributes;
        if (docAttributes == null) {
            attributes = new FetchAttributes();
        } else {
            attributes = new FetchAttributes(docAttributes);
        }

        final String fetchHint = grammar.getFetchhint();
        if (fetchHint != null) {
            attributes.setFetchHint(fetchHint);
        }
        final long fetchTimeout = grammar.getFetchTimeoutAsMsec();
        if (fetchTimeout > 0) {
            attributes.setFetchTimeout(fetchTimeout);
        }
        final long maxAge = grammar.getMaxageAsMsec();
        if (maxAge > 0) {
            attributes.setMaxage(maxAge);
        }
        final long maxStale = grammar.getMaxageAsMsec();
        if (maxStale > 0) {
            attributes.setMaxstale(maxStale);
        }

        return attributes;
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.