📄 grammarmanager.cpp
字号:
/****************License************************************************ * * Copyright 2000-2001. SpeechWorks International, Inc. * * Use of this software is subject to notices and obligations set forth * in the SpeechWorks Public License - Software Version 1.1 which is * included with this software. * * SpeechWorks is a registered trademark, and SpeechWorks Here, * DialogModules and the SpeechWorks logo are trademarks of SpeechWorks * International, Inc. in the United States and other countries. * ***********************************************************************/#include "GrammarManager.hpp"#include "VXIrec.h"#include "SimpleLogger.hpp"#include "CommonExceptions.hpp"#include "PropertyList.hpp"#include "VXML.h"#include "DocumentModel.hpp"//#############################################################################// Grammar description class//#############################################################################const VXIchar * const GrammarManager::DTMFTerm = L"@dtmfterm";const VXIchar * const GrammarManager::FinalSilence = L"@finalsilence";const VXIchar * const GrammarManager::MaxTime = L"@maxtime";const VXIchar * const GrammarManager::RecordingType = L"@rectype";enum GrammarScope { GRS_NONE, GRS_FIELD, GRS_DIALOG, GRS_DOC};class GrammarInfo {public: GrammarInfo(VXIrecGrammar *, const vxistring &, const VXMLElement &); ~GrammarInfo(); VXIrecGrammar * GetRecGrammar() { return recgrammar; } void SetEnabled(bool b) { enabled = b; } bool IsEnabled() const { return enabled; } bool IsScope(GrammarScope s) const { return s == scope; } bool IsField(const vxistring & f) const { return f == field; } bool IsDialog(const vxistring & d) const { return d == dialog; } bool IsDoc(const vxistring & d) const { return d == docID; } void GetElement(VXMLElement & e) const { e = element; }private: void _Initialize(const VXMLElement & elem); // This sets the field & dialog names. const VXMLElement element; VXIrecGrammar * recgrammar; // grammar handle returned from rec interface GrammarScope scope; vxistring field; vxistring dialog; vxistring docID; bool enabled;};GrammarInfo::GrammarInfo(VXIrecGrammar * g, const vxistring & id, const VXMLElement & elem) : element(elem), recgrammar(g), scope(GRS_NONE), docID(id), enabled(false){ // (1) Determine the grammar scope. // (1.1) Obtain default from position in the tree. VXMLElement par = elem; while (par != 0) { VXMLElementType name = par.GetName(); if (name == NODE_INITIAL || name == NODE_FIELD || name == NODE_RECORD || name == NODE_TRANSFER) { scope = GRS_FIELD; break; } else if (name == NODE_FORM || name == NODE_MENU) { scope = GRS_DIALOG; break; } else if (name == NODE_VXML) { scope = GRS_DOC; break; } par = par.GetParent(); } // (1.2) if scope explicitly specified in grammar or parent, override! vxistring str; elem.GetAttribute(ATTRIBUTE_SCOPE, str); if (str.empty() && par != 0) { par.GetAttribute(ATTRIBUTE_SCOPE, str); } if (!str.empty()) { if (str == L"dialog") scope = GRS_DIALOG; else if (str == L"document") scope = GRS_DOC; } // (2) Do remaining initialization. _Initialize(elem);}GrammarInfo::~GrammarInfo(){ // NOTE: 'recgrammar' must be freed externally.}void GrammarInfo::_Initialize(const VXMLElement & elem){ if (elem == 0) return; VXMLElementType name = elem.GetName(); if (name == NODE_FIELD || name == NODE_INITIAL) elem.GetAttribute(ATTRIBUTE__ITEMNAME, field); else if (name == NODE_FORM || name == NODE_MENU) { elem.GetAttribute(ATTRIBUTE__ITEMNAME, dialog); return; } _Initialize(elem.GetParent());}//#############################################################################// Recognition Answer class//#############################################################################RecognitionAnswer::RecognitionAnswer() : waveform(NULL), result(NULL), numAnswers(0){ keys.reserve(10); values.reserve(10); scores.reserve(10); utts.reserve(10);}RecognitionAnswer::~RecognitionAnswer(){ if (result != NULL) result->Destroy(&result);}void RecognitionAnswer::Bind(VXIrecRecognitionResult * r){ result = r;}void RecognitionAnswer::Clear(){ keys.clear(); values.clear(); scores.clear(); utts.clear(); waveform = NULL; result = NULL; numAnswers = 0;}RecognitionAnswer & RecognitionAnswer::operator=(RecognitionAnswer & x){ if (&x != this) { numAnswers = x.numAnswers; keys = x.keys; values = x.values; scores = x.scores; utts = x.utts; waveform = x.waveform; result = x.result; x.Clear(); } return *this;}RecognitionAnswer::RecognitionAnswer(RecognitionAnswer & x){ numAnswers = x.numAnswers; keys = x.keys; values = x.values; scores = x.scores; utts = x.utts; waveform = x.waveform; result = x.result; x.Clear();}//#############################################################################// Grammar description class//#############################################################################GrammarManager::GrammarManager(VXIrecInterface * r, const SimpleLogger & l) : log(l), vxirec(r){}GrammarManager::~GrammarManager(){ ReleaseGrammars();}// This function is used to recursively walk through the tree, loading and// speech or dtmf grammars which are found.//void GrammarManager::LoadGrammars(const VXMLElement& doc, vxistring & documentID, PropertyList & properties){ if (doc == 0) return; VXIMapHolder recProps(NULL); // Initialize an empty holder. // (1) Retrieve the ID for this document. This is important for grammar // activation. if (doc.GetName() == NODE_VXML) doc.GetAttribute(ATTRIBUTE__ITEMNAME, documentID); // (2) Look for grammars in current nodes. for (VXMLNodeIterator it(doc); it; ++it) { VXMLNode child = *it; if (child.GetType() != VXMLNode::Type_VXMLElement) continue; const VXMLElement & element = reinterpret_cast<const VXMLElement &>(child); VXMLElementType elementName = element.GetName(); VXIrecGrammar * vg = NULL; if (recProps.GetValue() == NULL) recProps.Acquire(GetRecProperties(properties)); // (3) Handle <grammar> & <dtmf> if (elementName == NODE_GRAMMAR || elementName == NODE_DTMF) { vxistring src; element.GetAttribute(ATTRIBUTE_SRC, src); // (3.1) Override the language setting (if specified as an attribute) vxistring lang; if (element.GetAttribute(ATTRIBUTE_XMLLANG, lang) == true) AddParamValue(recProps, REC_LANGUAGE, lang); // (3.2) Does the grammar come from an external URI? if (!src.empty()) { if (log.IsLogging(2)) { log.StartDiagnostic(2) << L"GrammarManager::LoadGrammars - <grammar " L"src=\"" << src << L"\">"; log.EndDiagnostic(); } VXIMapHolder fetchobj; if (fetchobj.GetValue() == NULL) throw VXIException::OutOfMemory(); vxistring fragment; properties.GetFetchobjCacheAttrs(element, PropertyList::Grammar, fetchobj); properties.GetFetchobjURIs(element, fetchobj, src, fragment); if (!fragment.empty()) log.LogError(215); vxistring mimeType; element.GetAttribute(ATTRIBUTE_TYPE, mimeType); VXIrecResult err = vxirec->LoadGrammarURI(vxirec, recProps.GetValue(), mimeType.c_str(), src.c_str(), fetchobj.GetValue(), &vg); if (err != VXIrec_RESULT_SUCCESS) throw VXIException::InterpreterEvent(EV_ERROR_BAD_GRAMMAR); AddGrammar(vg, documentID, element); } // (3.3) Otherwise this is an inlined grammar. else { log.LogDiagnostic(2, L"GrammarManager::LoadGrammars - <grammar>"); vxistring text; GetEnclosedText(log, element, text); vxistring mimeType; element.GetAttribute(ATTRIBUTE_TYPE, mimeType); if (mimeType.empty() && elementName == NODE_DTMF) vg = GrammarManager::CreateGrammarFromString(vxirec, log, text, REC_MIME_GENERIC_DTMF, recProps); else vg = GrammarManager::CreateGrammarFromString(vxirec, log, text, mimeType.c_str(), recProps); if (vg == NULL) // "Error loading in-line grammar %s",text throw VXIException::InterpreterEvent(EV_ERROR_BAD_INLINE); AddGrammar(vg, documentID, element); } } // (4) Handle <choice> else if (elementName == NODE_CHOICE) { log.LogDiagnostic(2, L"GrammarManager::LoadGrammars - <choice>"); // (4.1) If there is a <grammar> tag, it overrides any implicit grammar. // (4.1.1) Check for <grammar> element. bool foundGrammar = false; for (VXMLNodeIterator it(element); it; ++it) { VXMLNode child = *it; if (child.GetType() != VXMLNode::Type_VXMLElement) continue; const VXMLElement & temp = reinterpret_cast<const VXMLElement&>(child); if (temp.GetName() != NODE_GRAMMAR) continue; foundGrammar = true; break; } // (4.1.2) If found, apply recursion. if (foundGrammar) { // <choice> nodes can't contain properties. Don't need to call Push. LoadGrammars(element, documentID, properties); } // (4.1.3) Otherwise, construct a grammar from the prompt text. else { vxistring text; GetEnclosedText(log, element, text); // The text may be empty, e.g. for a dtmf only grammar. if (!text.empty()) { VXIrecGrammar * vg = NULL; vg = GrammarManager::CreateGrammarFromString(vxirec, log, text, REC_MIME_CHOICE, recProps); if (vg == NULL) // "Error loading in-line grammar %s",text throw VXIException::InterpreterEvent(EV_ERROR_BAD_CHOICE); AddGrammar(vg, documentID, element); } } // (4.2) Create associated DTMF grammar. // // Either an explict dtmf choice is given or implicit numbers are // generated for the first nine. When both are specified, the explicit // choice wins. This will quite possibly create unintentional (and // undetected) duplicates.... vxistring dtmf; element.GetAttribute(ATTRIBUTE_DTMF, dtmf); if (!dtmf.empty()) { VXIrecGrammar * vg = NULL; vg = GrammarManager::CreateGrammarFromString(vxirec, log, dtmf, REC_MIME_CHOICE_DTMF, recProps); if (vg == NULL) throw VXIException::InterpreterEvent(EV_ERROR_BAD_CHOICE); AddGrammar(vg, documentID, element); } } // (5) Handle <field>. else if (elementName == NODE_FIELD) { log.LogDiagnostic(2, L"GrammarManager::LoadGrammars - <field>"); vxistring gram; VXIrecGrammar * vg;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -