📄 grammarmanager.cpp
字号:
element.GetAttribute(ATTRIBUTE_TYPE, mimeType);
VXIrecGrammar * vg
= GrammarManager::CreateGrammarFromURI(vxirec, log, src,
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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -