📄 grammarmanager.cpp
字号:
mimeType.c_str(), fetchobj.GetValue(), localProps); AddGrammar(vg, documentID, element); } // (2.3) Otherwise this is an inlined grammar. else { log.LogDiagnostic(2, L"GrammarManager::LoadGrammars - <grammar>"); AddGrammar(BuildInlineGrammar(element, localProps), documentID, element); } } // (3) Handle <link>. Properties cannot be defined in <link>. else if (elementName == NODE_LINK) { log.LogDiagnostic(2, L"GrammarManager::LoadGrammars - <link>"); // (3.1) Create DTMF grammar is specified. vxistring dtmf; element.GetAttribute(ATTRIBUTE_DTMF, dtmf); if (!dtmf.empty()) { // Flatten grammar properties if necessary. if (levelProperties.GetValue() == NULL) levelProperties.Acquire(GetRecProperties(properties)); // NOTE: We don't need to worry about xml:lang, xml:base, or weight; // This is a generated (no xml:base) dtmf (xml:lang) grammar. VXIrecGrammar * vg = NULL; vg = GrammarManager::CreateGrammarFromString(vxirec, log, dtmf, REC_MIME_CHOICE_DTMF, levelProperties); if (vg == NULL) throw VXIException::InterpreterEvent(EV_ERROR_BAD_CHOICE); AddGrammar(vg, documentID, element); } // (3.2) Create child grammars. BuildGrammars(element, documentID, properties, levelProperties); } // (4) Handle <field>. else if (elementName == NODE_FIELD) { log.LogDiagnostic(2, L"GrammarManager::LoadGrammars - <field>"); // (4.1) Get the properties from the field. bool doPop = properties.PushProperties(element); VXIMapHolder localProps(NULL); if (doPop || levelProperties.GetValue() == NULL) localProps.Acquire(GetRecProperties(properties)); else localProps = levelProperties; // Set weight, language, and fetchhint. SetGrammarLoadProperties(element, localProps); // (4.2) Build option grammar (if necessary). BuildOptionGrammars(documentID, element, localProps); // (4.3) Add the built-in grammars (if they exist). VXIrecGrammar * vg = NULL; vxistring type; element.GetAttribute(ATTRIBUTE_TYPE, type); if (!type.empty()) { vxistring newuri(L"builtin:grammar/"); newuri += type; vg = GrammarManager::CreateGrammarFromURI(vxirec, log, newuri, NULL, NULL, localProps); AddGrammar(vg, documentID, element); newuri = L"builtin:dtmf/"; newuri += type; vg = GrammarManager::CreateGrammarFromURI(vxirec, log, newuri, NULL, NULL, localProps); AddGrammar(vg, documentID, element); } // (4.4) Recursively add grammars (this handles <grammar>) BuildGrammars(element, documentID, properties, localProps); if (doPop) properties.PopProperties(); } // (5) Handle <menu>. else if (elementName == NODE_MENU) { log.LogDiagnostic(2, L"GrammarManager::LoadGrammars - <menu>"); // (5.1) Get the properties from the menu. bool doPop = properties.PushProperties(element); VXIMapHolder localProps(NULL); if (doPop || levelProperties.GetValue() == NULL) localProps.Acquire(GetRecProperties(properties)); else localProps = levelProperties; // Set weight, language, and fetchhint. SetGrammarLoadProperties(element, localProps); // (5.2) Get grammar accept attribute & handle <choice>s. vxistring accept; if (element.GetAttribute(ATTRIBUTE_ACCEPT, accept) == true && accept == L"approximate") { BuildGrammars(element, documentID, properties, localProps, 1); } else BuildGrammars(element, documentID, properties, localProps, 0); // (5.3) Undo pop if necessary. if (doPop) properties.PopProperties(); } // (6) Handle <choice> else if (elementName == NODE_CHOICE) { log.LogDiagnostic(2, L"GrammarManager::LoadGrammars - <choice>"); // (6.1) If there is a <grammar> tag, it overrides any implicit grammar. // (6.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; } // (6.1.2) If found, apply recursion. if (foundGrammar) { // <choice> nodes can't contain properties. Don't need to call Push. BuildGrammars(element, documentID, properties, levelProperties); } // (6.2) DTMF & CDATA grammars. vxistring dtmf; element.GetAttribute(ATTRIBUTE_DTMF, dtmf); vxistring text; if (!foundGrammar) GetEnclosedText(log, element, text); if (!dtmf.empty() || !text.empty()) { // (6.2.1) Set up properties. // This should not ever be necessary, but just in case... if (levelProperties.GetValue() == NULL) { levelProperties.Acquire(GetRecProperties(properties)); log.LogError(999, SimpleLogger::MESSAGE, L"GrammarManager::BuildGrammars levelProperties " L"not already built for a <choice>"); } // (6.2.2) Build DTMF grammars if (!dtmf.empty()) { VXIrecGrammar * vg = GrammarManager::CreateGrammarFromString( vxirec, log, dtmf, REC_MIME_CHOICE_DTMF, levelProperties); if (vg == NULL) throw VXIException::InterpreterEvent(EV_ERROR_BAD_CHOICE); AddGrammar(vg, documentID, element); } // (6.2.3) Build CDATA grammars (if not overriden by explicit <grammar> if (!text.empty()) { // Set accept property. This changes the pseudo-read-only // levelProperties, so we'll undo the change after creating the // grammar. vxistring accept; if (element.GetAttribute(ATTRIBUTE_ACCEPT, accept)) { if (accept == L"approximate") AddParamValue(levelProperties, REC_GRAMMAR_ACCEPTANCE, 1); else AddParamValue(levelProperties, REC_GRAMMAR_ACCEPTANCE, 0); } else AddParamValue(levelProperties, REC_GRAMMAR_ACCEPTANCE, menuAcceptLevel ? 1 : 0); VXIrecGrammar * vg = GrammarManager::CreateGrammarFromString( vxirec, log, text, REC_MIME_CHOICE, levelProperties); if (vg == NULL) throw VXIException::InterpreterEvent(EV_ERROR_BAD_CHOICE); AddGrammar(vg, documentID, element); // As promised, undo the REC_GRAMMAR_ACCEPTANCE property. VXIMapDeleteProperty(levelProperties.GetValue(), REC_GRAMMAR_ACCEPTANCE); } } } // (7) Otherwise, nothing was found at this level. Use recursion to check // the next level down. else { bool doPop = properties.PushProperties(element); if (doPop) { VXIMapHolder temp(NULL); BuildGrammars(element, documentID, properties, temp, menuAcceptLevel); } else BuildGrammars(element, documentID, properties, levelProperties, menuAcceptLevel); if (doPop) properties.PopProperties(); } } } // The defaults have a very simple structure. The element in this case is the // desired language. This has an 'id' attribute and contains the <link> and // <property> elements. // void GrammarManager::BuildUniversals(const VXMLElement& doc, PropertyList & properties) { // (1) Collect all the properties defined at this level. This is the only // point at which properties may be declared. properties.PushProperties(doc); VXIMapHolder localProps(GetRecProperties(properties)); // (2) Get the name of the language. vxistring languageID; if (!doc.GetAttribute(ATTRIBUTE_ID, languageID)) { log.LogError(999, SimpleLogger::MESSAGE, L"defaults document corrupted - " L"no id attribute on <language> element"); throw VXIException::InterpreterEvent(EV_ERROR_BADFETCH); } // (3) Find each link. for (VXMLNodeIterator temp3(doc); temp3; ++temp3) { VXMLNode child = *temp3; if (child.GetType() != VXMLNode::Type_VXMLElement) continue; const VXMLElement & link = reinterpret_cast<const VXMLElement&>(child); if (link.GetName() != NODE_LINK) continue; // (3.1) Get the name of the link. vxistring linkName; if (!link.GetAttribute(ATTRIBUTE_EVENT, linkName)) { log.LogError(999, SimpleLogger::MESSAGE, L"defaults document corrupted " L"- no event attribute on <link> element"); throw VXIException::InterpreterEvent(EV_ERROR_BADFETCH); } // (3.2) Process dtmf grammars for this link. vxistring dtmf; link.GetAttribute(ATTRIBUTE_DTMF, dtmf); if (!dtmf.empty()) { // NOTE: We don't need to worry about xml:lang, xml:base, or weight; // This is a generated (no xml:base) dtmf (xml:lang) grammar. VXIrecGrammar * vg = NULL; vg = GrammarManager::CreateGrammarFromString(vxirec, log, dtmf, REC_MIME_CHOICE_DTMF, localProps); if (vg == NULL) throw VXIException::InterpreterEvent(EV_ERROR_BAD_CHOICE); AddUniversal(vg, link, languageID, linkName); } // (4) And each grammar. for (VXMLNodeIterator temp4(link); temp4; ++temp4) { VXMLNode child = *temp4; if (child.GetType() != VXMLNode::Type_VXMLElement) continue; const VXMLElement & gram = reinterpret_cast<const VXMLElement &>(child); if (gram.GetName() != NODE_GRAMMAR) continue; // (4.1) Get caching properties on the <grammar> element. SetGrammarLoadProperties(gram, localProps); // (4.2) Process remote grammars vxistring src; gram.GetAttribute(ATTRIBUTE_SRC, src); if (!src.empty()) { // (4.2.1) Generate error if fragment-only URI in external grammar if (!src.empty() && src[0] == '#') { log.LogError(215); throw VXIException::InterpreterEvent(EV_ERROR_SEMANTIC, L"a fragment-only URI is not permited in external grammar"); } VXIMapHolder fetchobj; if (fetchobj.GetValue() == NULL) throw VXIException::OutOfMemory(); properties.GetFetchobjCacheAttrs(gram, PropertyList::Grammar, fetchobj); // (4.2.2) Load the grammar from the URI. vxistring mimeType; gram.GetAttribute(ATTRIBUTE_TYPE, mimeType); VXIrecGrammar * vg = GrammarManager::CreateGrammarFromURI(vxirec, log, src, mimeType.c_str(), fetchobj.GetValue(), localProps); AddUniversal(vg, gram, languageID, linkName); } else { AddUniversal(BuildInlineGrammar(gram, localProps), gram, languageID, linkName); } } // end <grammar> } // end <link> properties.PopProperties(); } class VXIVectorHolder { public: VXIVectorHolder() : _v(NULL) { _v = VXIVectorCreate(); } ~VXIVectorHolder() { if (_v != NULL) VXIVectorDestroy(&_v); } VXIVector * GetValue() const { return _v; } private: VXIVectorHolder(const VXIVectorHolder &); /* intentionally not defined. */ VXIVector * _v; }; void GrammarManager::BuildOptionGrammars(const vxistring & documentID, const VXMLElement & element, const VXIMapHolder & props) { log.LogDiagnostic(2, L"GrammarManager::BuildOptionGrammars()"); // (1) Create new vectors to hold the grammar. VXIVectorHolder speechUtts; VXIVectorHolder speechVals; VXIVectorHolder dtmfUtts; VXIVectorHolder dtmfVals; VXIVectorHolder gramAcceptanceAttrs; if (speechUtts.GetValue() == NULL || speechVals.GetValue() == NULL || dtmfUtts.GetValue() == NULL || dtmfVals.GetValue() == NULL || gramAcceptanceAttrs.GetValue() == NULL) throw VXIException::OutOfMemory(); // (2) Get each option. for (VXMLNodeIterator it(element); it; ++it) { VXMLNode child = *it; // (2.1) Ignore anything which isn't an option. if (child.GetType() != VXMLNode::Type_VXMLElement) continue; VXMLElement & domElem = reinterpret_cast<VXMLElement &>(child); if (domElem.GetName() != NODE_OPTION) continue; // (2.2) Get attributes and CDATA. vxistring value; domElem.GetAttribute(ATTRIBUTE_VALUE, value); vxistring dtmf; domElem.GetAttribute(ATTRIBUTE_DTMF, dtmf); vxistring accept; domElem.GetAttribute(ATTRIBUTE_ACCEPT, accept); vxistring text; GrammarManager::GetEnclosedText(log, domElem, text); if (value.empty()) value = text; if (value.empty()) value = dtmf; // (2.3) Add to vectors as appropriate. if (!text.empty()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -