📄 vxi.cpp
字号:
} throw VXIException::InterpreterEvent(EV_ERROR_BADFETCH); case 3: // Unable to read from URI log->LogError(204); throw VXIException::InterpreterEvent(EV_ERROR_BADFETCH); case 4: // Unable to parse contents of URI { VXIString *key = NULL, *value = NULL; if ((cbuffer) && ((log->IsLogging(SimpleLogger::DOC_PARSE_ERROR_DUMPS)) || (log->IsLogging(SimpleLogger::DOC_DUMPS))) && (log->LogContent(VXI_MIME_XML, cbuffer, bufferSize, &key, &value))) log->LogError(205, VXIStringCStr(key), VXIStringCStr(value)); else log->LogError(205); if (cbuffer) delete [] cbuffer; if (key) VXIStringDestroy(&key); if (value) VXIStringDestroy(&value); throw VXIException::InterpreterEvent(EV_ERROR_BADFETCH); } default: log->LogError(206); throw VXIException::Fatal(); } if (doc.GetRoot() == 0) { log->LogError(999, SimpleLogger::MESSAGE, L"able to fetch initial document but node empty"); throw VXIException::Fatal(); } } void VXI::ProcessRootScripts(VXMLElement& doc) { if (doc == 0) return; log->LogDiagnostic(2, L"VXI::ProcessRootScripts()"); // Do <var> <script> and <meta> <property> elements for (VXMLNodeIterator it(doc); it; ++it) { VXMLNode child = *it; if (child.GetType() != VXMLNode::Type_VXMLElement) continue; const VXMLElement & elem = reinterpret_cast<const VXMLElement &>(child); VXMLElementType nodeName = elem.GetName(); if (nodeName == NODE_VAR) var_element(elem); else if (nodeName == NODE_META) meta_element(elem); else if (nodeName == NODE_SCRIPT) script_element(elem); } log->LogDiagnostic(2, L"VXI::ProcessRootScripts - done"); } //############################################################################# // Dialog Loop //############################################################################# // There are two cases in which this routine may be entered. // A. After a new document is loaded (lastItem == 0) // B. After a return from <subdialog> // and three ways in which the loop may be re-entered. // 1. Jump to new dialog. // 2. Jump to new form item in the existing dialog. // 3. Jump to new dialog after recognizing a document scope grammar. // // The ECMA script scopes are reset accordingly: // anonymous: A B 1 2 3 // local: A 1 2 3 // dialog: A 1 3 void VXI::RunInnerLoop() { log->LogDiagnostic(2, L"VXI::RunInnerLoop()"); if (exe->currentDialog == 0) { log->LogError(999, SimpleLogger::MESSAGE, L"no current active document"); return; } exe->currentFormItem = exe->lastItem; // next item to process; <goto> etc. exe->lastItem = VXMLElement(); // reset after <subdialog> bool newDialog = (exe->currentFormItem == 0); exe->playingPrompts = true; // flag for prompting after events // Are we re-entering after a recognition? bool unprocessedAnswer = false; while (1) { if (stopRequested) throw VXIException::StopRequest(); try { try { // (1) Adjust scope if necessary if (exe->script.CurrentScope(SCOPE_Anonymous)) exe->script.PopScope(); if (exe->script.CurrentScope(SCOPE_Local)) exe->script.PopScope(); // (2) Initialize dialog (if necessary) if (newDialog) { newDialog = false; exe->playingPrompts = true; // (2.1) Reset ECMA script scope. if (exe->script.CurrentScope(SCOPE_Dialog)) exe->script.PopScope(); exe->script.PushScope(SCOPE_Dialog); // (2.2) Do 'initialization phase' from FIA. VXIMapHolder params(sdParams); sdParams = NULL; FormInit(exe->currentDialog, params); // (2.3) Do 'select phase' from FIA if the item is not already known if (exe->currentFormItem == 0) { DoInnerJump(exe->currentDialog, L""); break; } } // (3) The loop cases. // (3.1) Re-entering loop with an unprocessed recognition result. if (unprocessedAnswer == true) { unprocessedAnswer = false; HandleRemoteMatch(exe->currentDialog, exe->currentFormItem); } // (3.2) Re-entering loop after returning from a <subdialog>. else if (sdResult != NULL) { VXIMapHolder temp(sdResult); sdResult = NULL; ProcessReturn(exe->currentDialog, exe->currentFormItem, temp); } else if (sdEvent != NULL) { // The sdEvent is deallocated in the catch (below). throw VXIException::InterpreterEvent(*sdEvent); } // (3.3) Each time we enter collect phase, we get fresh local scope. // All filled and catched triggered form here will execute in this // scope. The final local scope is popped with we leave. else { if (exe->script.CurrentScope(SCOPE_Local)) exe->script.PopScope(); exe->script.PushScope(SCOPE_Local); mutex.Lock(); if (haveExternalEvents) { vxistring event, message; if (externalEvents.size() > 0) { event = externalEvents.front(); externalEvents.pop_front(); message = externalMessages.front(); externalMessages.pop_front(); } if (externalEvents.empty()) haveExternalEvents = false; mutex.Unlock(); throw VXIException::InterpreterEvent(event, message, exe->currentDialog); } mutex.Unlock(); // Do the 'collect phase & process phase' from the FIA. CollectPhase(exe->currentDialog, exe->currentFormItem); } } catch (const VXIException::InterpreterEvent & e) { // Cleanup sdEvent (if necessary). if (sdEvent != NULL) { delete sdEvent; sdEvent = NULL; } // Handles document events. if (log->IsLogging(2)) { log->StartDiagnostic(2) << L"VXI::RunInnerLoop - got exception: " << e.GetValue(); log->EndDiagnostic(); } if (exe->currentFormItem != 0) DoEvent(exe->currentFormItem, e); else DoEvent(exe->currentDialog, e); } DoInnerJump(exe->currentDialog, L""); break; } catch (JumpDialog & e) { // Handle <goto> events exe->currentDialog = e.dialog; exe->currentFormItem = VXMLElement(); newDialog = true; } catch (const JumpItem & e) { // This handles local <goto>s. exe->currentFormItem = e.item; } catch (AnswerInformation & e) { if (exe->currentDialog != e.dialog) { exe->currentDialog = e.dialog; newDialog = true; } exe->currentFormItem = e.element; unprocessedAnswer = true; } } // while (1) log->LogDiagnostic(2, L"VXI::RunInnerLoop - done"); } void VXI::ProcessReturn(const VXMLElement& form, const VXMLElement & item, VXIMapHolder & result) { log->LogDiagnostic(2, L"VXI::ProcessReturn()"); vxistring filled; item.GetAttribute(ATTRIBUTE__ITEMNAME, filled); exe->script.SetValue(filled, reinterpret_cast<VXIValue*>(result.GetValue())); ProcessFilledElements(filled, form); } // Perform initialization associated with property tags and form level // variables. Reset the event and prompts counts. // void VXI::FormInit(const VXMLElement & form, VXIMapHolder & params) { log->LogDiagnostic(2, L"VXI::FormInit()"); // (1) Set the form properties. exe->properties.SetProperties(form, DIALOG_PROP, VXIMapHolder()); // (2) Clear the prompt & event counts when the form is entered. exe->promptcounts.Clear(); exe->eventcounts.Clear(); exe->formitems.clear(); vxistring itemname; form.GetAttribute(ATTRIBUTE__ITEMNAME, itemname); // (3) Walk through the form nodes. Set up variables as necessary. for (VXMLNodeIterator it(form); it; ++it) { VXMLNode child = *it; if (child.GetType() != VXMLNode::Type_VXMLElement) continue; const VXMLElement & elem = reinterpret_cast<const VXMLElement &>(child); // (3.1) Handle <var> and <script> elements. VXMLElementType nodeName = elem.GetName(); if (nodeName == NODE_VAR) { if (params.GetValue() != NULL) { // (3.1.1) Set matching variables to the value in the param list. // Each located parameter gets removed from the map. vxistring name; elem.GetAttribute(ATTRIBUTE_NAME, name); if (!name.empty()) { const VXIValue * value = VXIMapGetProperty(params.GetValue(), name.c_str()); if (value != NULL) { exe->script.MakeVar(name, value); VXIMapDeleteProperty(params.GetValue(), name.c_str()); continue; } } } // (3.1.2) Otherwise, follow the normal proceedure. var_element(elem); continue; } else if (nodeName == NODE_SCRIPT) script_element(elem); // (3.2) Ignore anything which is not a form item. if (!IsFormItemNode(elem)) continue; // (3.3) Initialize variables for each form item. vxistring name; vxistring expr; elem.GetAttribute(ATTRIBUTE__ITEMNAME, name); if (exe->script.IsVarDeclared(name)) { throw VXIException::InterpreterEvent(EV_ERROR_BADFETCH, L"input item variable name conflict"); } elem.GetAttribute(ATTRIBUTE_EXPR, expr); exe->script.MakeVar(name, expr); nodeName = elem.GetName(); if (nodeName == NODE_FIELD || nodeName == NODE_RECORD || nodeName == NODE_TRANSFER) exe->script.EvalScript(vxistring(L"var ") + name + L"$ = new Object();"); exe->formitems.push_back(name); } // (4) Did all incoming parameters get used? if (params.GetValue() != NULL && VXIMapNumProperties(params.GetValue()) != 0) { if (log->IsLogging(2)) { const VXIchar *key; const VXIValue *value; VXIMapIterator *vi = VXIMapGetFirstProperty(params.GetValue(), &key, &value); while (vi) { vxistring text(L"VXI::FormInit - unused parameter "); text += key; log->LogDiagnostic(2, text.c_str()); if (VXIMapGetNextProperty(vi, &key, &value) !=VXIvalue_RESULT_SUCCESS){ VXIMapIteratorDestroy(&vi); vi = NULL; } } } throw VXIException::InterpreterEvent(EV_ERROR_SEMANTIC); } log->LogDiagnostic(2, L"VXI::FormInit - Done"); } // Returns true iff the element is a form item. // // This is the list from section 6.2 of the VXML 1.0 specification with one // addition - <menu>. // bool VXI::IsFormItemNode(const VXMLElement & doc) { VXMLElementType nodeName = doc.GetName(); if (nodeName == NODE_FIELD || nodeName == NODE_INITIAL || nodeName == NODE_RECORD || nodeName == NODE_TRANSFER || nodeName == NODE_OBJECT || nodeName == NODE_SUBDIALOG || nodeName == NODE_MENU || nodeName == NODE_BLOCK) return true; return false; } bool VXI::IsInputItemNode(const VXMLElement & doc) { VXMLElementType nodeName = doc.GetName(); if (nodeName == NODE_FIELD || nodeName == NODE_RECORD || nodeName == NODE_TRANSFER || nodeName == NODE_OBJECT || nodeName == NODE_SUBDIALOG || nodeName == NODE_MENU) return true; return false; } // Finds the named form item within the dialog. If the name is empty, the // first non-filled item is returned. // void VXI::DoInnerJump(const VXMLElement & elem, const vxistring & item) { if (elem == 0) return; if (log->IsLogging(2)) { log->StartDiagnostic(2) << L"VXI::DoInnerJump(" << item << L")"; log->EndDiagnostic(); } // find form. VXMLElement current = elem; while (1) { VXMLElementType nodeName = current.GetName(); if (nodeName == NODE_MENU) throw JumpItem(current); // Menu is a special case. if (nodeName == NODE_FORM) break; const VXMLElement & parent = current.GetParent(); if (parent == 0) { log->LogError(999, SimpleLogger::MESSAGE, L"could not locate form on local jump"); throw VXIException::Fatal(); } current = parent; }; // (2) If the next item is specified (such as from a previous <goto>, look // for an exact match. if (!item.empty()) { for (VXMLNodeIterator it(current); it; ++it) { VXMLNode child = *it; if (child.GetType() != VXMLNode::Type_VXMLElement) continue; const VXMLElement & elem = reinterpret_cast<const VXMLElement &>(child); if (!IsFormItemNode(elem)) continue; vxistring name; if (!elem.GetAttribute(ATTRIBUTE__ITEMNAME, name)) continue; if (item == name) throw JumpItem(elem); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -