黃燕冰
S1000D Process數(shù)據(jù)模塊解析引擎的設(shè)計與實現(xiàn)
黃燕冰
[中圖分類號]
ASD S1000D《基于公共源數(shù)據(jù)庫的技術(shù)出版物國際規(guī)范》是目前使用最為流行的交互式電子技術(shù)資料手冊標(biāo)準(zhǔn),它采用了結(jié)構(gòu)化的方式把航空保障業(yè)務(wù)數(shù)據(jù)定義為各種不同的數(shù)據(jù)模塊,Process數(shù)據(jù)模塊是其中交互閱讀表達(dá)能力最強的數(shù)據(jù)模塊,其交互要求遠(yuǎn)遠(yuǎn)超過其它數(shù)據(jù)模塊。
在Process數(shù)據(jù)模塊的內(nèi)容中定義了諸多流程控制元素,如變量、循環(huán)、條件、開關(guān)、跳轉(zhuǎn)、賦值、表達(dá)式等控制邏輯要素,使得它的導(dǎo)航閱讀過程就如同計算機指令解析過程,因此該數(shù)據(jù)模塊的解析必須建立一個類似于虛擬機器執(zhí)行器的導(dǎo)航解析引擎。
Process數(shù)據(jù)模塊的導(dǎo)航解析引擎應(yīng)允許與用戶進行交互,要求導(dǎo)航引擎能支持用戶更深入地參與其中,用戶應(yīng)可改變變量的值、跳轉(zhuǎn)到指定元素、單步執(zhí)行、回撤操作等導(dǎo)航行為。
交互式電子技術(shù)手冊閱讀器,簡稱為IETM閱讀器,是電子技術(shù)信息手冊的閱讀平臺,也是武器裝備技術(shù)信息化保障平臺的重要組成部分。IETM閱讀器的主要任務(wù)是提取、顯示技術(shù)信息、并提供與用戶交互的功能。
基于S1000D的IETM閱讀器具備有S1000D標(biāo)準(zhǔn)中所有類型數(shù)據(jù)模塊的閱讀能力,Process數(shù)據(jù)模塊閱讀器只是IETM閱讀器的其中的一個重要組成部分,而Process數(shù)據(jù)模塊解析引擎是Process數(shù)據(jù)模塊閱讀器的核心模塊。
由此可知,Process數(shù)據(jù)模塊解析引擎是IETM閱讀器的一個專用于Process數(shù)據(jù)模塊閱讀的程序模塊。
在介紹Process數(shù)據(jù)模塊導(dǎo)航引擎之前,首先對Process數(shù)據(jù)模塊的主要構(gòu)成內(nèi)容進行詳細(xì)說明。2.1 數(shù)據(jù)模塊內(nèi)容邏輯模型
S1000D Process數(shù)據(jù)模塊的Schema結(jié)構(gòu)相當(dāng)復(fù)雜,包含許多元素和屬性,但是從整體結(jié)構(gòu)上來看,它包含的主要節(jié)點有:variableDeclarations、dmSeq、dmIf、dmLoop,其中dmSeq、dmIf、dmLoop是可以互為上下級的。
● variableDeclarations節(jié)點
該節(jié)點是一個變量定義表,可包含多個變量,變量之間通過變量名稱區(qū)分,變量取值類型有:boolean、string、real、integer、set-string、setreal、set-integer7種數(shù)據(jù)類型。
● dmSeq節(jié)點
該節(jié)點包含dmNode、dmNodeAlt、dmIf、dmLoop 4種節(jié)點,其中dmNode是在導(dǎo)航過程中每一步需要顯示的內(nèi)容,dmNodeAlt是多選一的開關(guān),它可包含多個dmNode,并且每次導(dǎo)航只選取一個dmNode,類似于C語言中的Switch語句。
● dmIf節(jié)點
該節(jié)點包含了expression、dmThenSeq、dmElseSeq 3種節(jié)點,其中expression為表達(dá)式節(jié)點,描述條件判斷節(jié)點的表達(dá)式條件,通過它決定判斷條件的真與假。dmThenSeq、dmElseSeq是它的分支節(jié)點。
● dmLoop節(jié)點
該節(jié)點包含variablePreSet、expression、dmSeq、assertion 4個節(jié)點,其中variablePreSet為循環(huán)體的預(yù)設(shè)內(nèi)容,主要是在進入循環(huán)之前進行變量值的設(shè)置;expression為循環(huán)體條件,判斷循環(huán)體是繼續(xù)執(zhí)行還是跳出循環(huán);dmSeq則是循環(huán)體內(nèi)容,每次循環(huán)中都需要執(zhí)行該節(jié)點內(nèi)容;assertion是循環(huán)體每次執(zhí)行后的設(shè)置,通常用于改變變量的值。
2.2 解析引擎
本文中把Process數(shù)據(jù)模塊解析引擎構(gòu)成要素劃分為如下內(nèi)容:指令讀取器、指令集、導(dǎo)航器、指令執(zhí)行。
它們之間的關(guān)系可由圖1說明。
圖1 解析引擎框架圖
2.2.1 指令讀取器
在本文中引入指令讀取器,其主要目的是讀取Process數(shù)據(jù)模塊的內(nèi)容并且轉(zhuǎn)換成導(dǎo)航器所需的指令。
● 數(shù)據(jù)模塊內(nèi)容模型
指令讀取器需要把Process數(shù)據(jù)模塊內(nèi)容讀取到內(nèi)存中,并通過分析Process數(shù)據(jù)模塊內(nèi)容把內(nèi)容轉(zhuǎn)換成樹狀結(jié)構(gòu)的模型。
依據(jù)Process數(shù)據(jù)模塊Schema內(nèi)容,可把內(nèi)容轉(zhuǎn)換成如圖2邏輯模型。
圖2 Procss數(shù)據(jù)模塊邏輯模型
● 指令讀取
用戶通過與導(dǎo)航引擎交互,驅(qū)動導(dǎo)航器開始工作,而導(dǎo)航器通過指令讀取器獲取下一條指令,并壓入孩子堆棧中以等待執(zhí)行。
2.2.2 指令集
基于導(dǎo)航過程的抽象行為,可以把指令分為以下幾類:可??恐噶?、可顯示指令、可壓棧指令、可運行指令。一個具體的指令可以屬于多個指令類型。
在本文的設(shè)計中,使用接口類區(qū)分不同類型的指令,使用IDockable接口表示可停靠指令、IPushable表示可壓棧指令、IDisplayable表示可顯示指令、IRunnable表示可運行指令。這幾種指令類型的關(guān)系,可由圖3說明。
● 可??恐噶?/p>
可停靠指令是指導(dǎo)航器導(dǎo)航到該對象時需要暫停,等待外部事件,接受到外部事件后才能進一步執(zhí)行,如同匯編中的中斷指令。
在Process數(shù)據(jù)模塊的閱讀過程中,導(dǎo)航引擎接受到用戶的閱讀請求(例如閱讀下一步內(nèi)容、上一步內(nèi)容等)后,一般來說閱讀器不會一直執(zhí)行至結(jié)束,而是在這個過程會停頓下來,把解析后的內(nèi)容呈現(xiàn)給用戶,并且等待接受用戶的下一個交互請求。
圖3 指令類型類圖
這個停頓過程的控制,在解析引擎的設(shè)計中采用了一種特定的指令類型,本文稱為可??恐噶?。
● 可顯示指令
可顯示指令的執(zhí)行需要在閱讀器中顯示閱讀內(nèi)容。
可顯示指令又分為主動顯示和被動顯示指令,主動顯示指令不僅本身內(nèi)容需要顯示,并且它的孩子也需要參與后續(xù)導(dǎo)航;而被動顯示指令只有本身顯示要求,其孩子不需要參與后續(xù)導(dǎo)航。
● 可壓棧指令
可壓棧指令指對應(yīng)節(jié)點的孩子需要參與到后續(xù)導(dǎo)航過程中,導(dǎo)航器在導(dǎo)航到它時需要將它壓入孩子堆棧以等待導(dǎo)航器后續(xù)的解析。
可壓棧指令是非常重要的指令類型,區(qū)分了指令對應(yīng)的數(shù)據(jù)模塊內(nèi)容節(jié)點的孩子內(nèi)容是否需要參與到導(dǎo)航過程中,簡單的說就是導(dǎo)航器是否需要分析節(jié)點的孩子信息,只需通過該節(jié)點對應(yīng)的指令是否是可壓棧的即可。
● 可運行指令
可運行指令指對應(yīng)節(jié)點可被作為導(dǎo)航過程的入口點單獨運行,等同于計算機應(yīng)用程序的主函數(shù)。
導(dǎo)航器的運行內(nèi)容的范圍是被運行節(jié)點以及它的后代。如果在運行節(jié)點的后代中存在引用節(jié)點,那么它的運行內(nèi)容也是可以被擴大的。
Process數(shù)據(jù)模塊中,XML節(jié)點的對應(yīng)指令歸類如圖4所示。
圖4 Process數(shù)據(jù)模塊節(jié)點指令歸類
2.2.3 導(dǎo)航器
導(dǎo)航器在Process數(shù)據(jù)模塊解析引擎中充當(dāng)了邏輯解析器的角色,對指令內(nèi)容進行邏輯運算和解析,是最為核心的組成部分。
在本節(jié)中分別從導(dǎo)航器的存儲結(jié)構(gòu)、導(dǎo)航器與用戶的交互接口、導(dǎo)航器執(zhí)行邏輯三個角度探討導(dǎo)航器設(shè)計方法。
2.2.3.1 存儲結(jié)構(gòu)
由于Process數(shù)據(jù)模塊的邏輯過程是樹形結(jié)構(gòu)而非線性結(jié)構(gòu),需要兩個堆棧記錄導(dǎo)航內(nèi)容,第一個堆棧一般用于記錄父親節(jié)點,第二個堆棧用于記錄孩子節(jié)點,第一個堆棧為父親堆棧,第二個堆棧為孩子堆棧;同時由于導(dǎo)航過程是可回溯的因此引入另外兩個堆棧,分別記錄父親堆棧、孩子堆棧的變化內(nèi)容,命名為父親變化堆棧、孩子變化堆棧。
另外在導(dǎo)航的過程中需要記錄當(dāng)前的執(zhí)行狀態(tài),即當(dāng)前狀態(tài)堆棧的記錄內(nèi)容;還需要使用導(dǎo)航上下文記錄導(dǎo)航器導(dǎo)航過程的一些狀態(tài)和導(dǎo)航相關(guān)服務(wù)。
● 父親堆棧
父親堆棧用于記錄當(dāng)前執(zhí)行點的父親節(jié)點,該父親節(jié)點同時也是一個返回點,如同計算機程序中的方法調(diào)用中的返回地址。當(dāng)該父親節(jié)點的所有孩子節(jié)點執(zhí)行完成后,該節(jié)點需要從父親堆棧中移除。
● 孩子堆棧
孩子堆棧也稱為執(zhí)行堆棧,需要參與后續(xù)導(dǎo)航的指令先是壓入孩子堆棧,再等待導(dǎo)航器執(zhí)行。
導(dǎo)航器下一個執(zhí)行的指令總是從孩子堆棧的棧頂獲取,如果孩子堆棧的內(nèi)容為空則說明全部內(nèi)容已經(jīng)導(dǎo)航結(jié)束。
● 孩子變化堆棧
孩子變化堆棧用于記錄孩子堆棧的變化,在導(dǎo)航回退時使用,可以還原孩子堆棧內(nèi)容。
● 父親變化堆棧
父親變化堆棧用于記錄父親堆棧的變化,在導(dǎo)航回退的使用,可以還原父親堆棧內(nèi)容。
● 當(dāng)前狀態(tài)棧
該堆棧用于記錄導(dǎo)航過程中的導(dǎo)航器的狀態(tài)變化信息,包含有變量的值改變信息、停靠節(jié)點、導(dǎo)航范圍節(jié)點、以及當(dāng)前導(dǎo)航過程中條件的運算結(jié)果等。
上面的存儲結(jié)構(gòu)組裝在一起統(tǒng)稱為導(dǎo)航器的會話狀態(tài)。
2.2.3.2 導(dǎo)航器與用戶的交互接口
導(dǎo)航器接口目前有執(zhí)行、跳轉(zhuǎn)、下一步、上一步、返回等。
● 執(zhí)行
導(dǎo)航器開始執(zhí)行,在執(zhí)行過程中導(dǎo)航器選擇開始對象(可運行指令),并且初始化導(dǎo)航器信息,執(zhí)行開始對象直至達(dá)到可??繉ο?。
● 跳轉(zhuǎn)
導(dǎo)航器執(zhí)行過程中,用戶通過交互活動改變默認(rèn)導(dǎo)航過程,使導(dǎo)航開始節(jié)點更改。從上面可以看出,跳轉(zhuǎn)過程是有用戶參與的,不是導(dǎo)航器的默認(rèn)導(dǎo)航行為。
● 下一步
導(dǎo)航器推進一步,從當(dāng)前??繉ο髮?dǎo)航至下一個??繉ο蟆?/p>
● 上一步
返回到上一次??繝顟B(tài),在這個過程中需要根據(jù)父親變化堆棧、孩子變化堆?;謴?fù)父親堆棧和孩子堆棧的內(nèi)容,同時也需要回滾變量表、當(dāng)前堆棧、導(dǎo)航上下文等內(nèi)容。
● 返回
返回指恢復(fù)到上一個開始導(dǎo)航對象,一般發(fā)生過跳轉(zhuǎn)后才能進行返回,導(dǎo)航器恢復(fù)到導(dǎo)跳轉(zhuǎn)前的狀態(tài)。
2.2.3.3 導(dǎo)航器執(zhí)行邏輯
本文中挑選導(dǎo)航器中比較典型的算法進行解析說明,分別為“下一步”、“上一步”執(zhí)行邏輯,其它的導(dǎo)航與“下一步”的導(dǎo)航邏輯大同小異。
2.2.3.3.1 下一步執(zhí)行邏輯
導(dǎo)航器的執(zhí)行過程以“下一步”最為典型,概要闡述該算法過程:
1)保存上一步歷史,包括當(dāng)前的導(dǎo)航狀態(tài)、變量值,保存父親堆棧和孩子堆棧的狀態(tài);
2)循環(huán)執(zhí)行,直至停止標(biāo)識StopFlag=True,讀取孩子堆棧的棧頂元素,記為TopElement;
3)判斷TopElement是否為空;
a)如果為空,則循環(huán)地把父親堆棧的棧頂元素出棧,直至父親堆棧為空或者碰到循環(huán)指令;如果碰到循環(huán)指令,則判斷循環(huán)是否結(jié)束,如果為結(jié)束則把循環(huán)的孩子元素依次壓入孩子堆棧中,同時執(zhí)行循環(huán)的第二個斷言集合;如果父親堆棧為空,裝入5;
b)如果不為空,則轉(zhuǎn)入4;
4)執(zhí)行TopElement;
a)判斷TopElement是否為循環(huán)指令,如果是則執(zhí)行前置條件判斷;如果結(jié)論為假,則轉(zhuǎn)入2;
b)判斷棧頂元素是否為可??恐噶睿莿t設(shè)置StopFlag=true;執(zhí)行下面步驟:
i.獲取棧頂元素的有效孩子指令(條件判斷節(jié)點獲取有效分支);
ii.把所有可壓棧的孩子指令壓入堆棧中;iii.轉(zhuǎn)入2;
5)保存堆棧和變量變化;
a)比較父親堆棧和孩子堆棧的變化,并把變化內(nèi)容保存到變化堆棧中;
b)比較變量值,把有變化的變量值記錄下來;
6)結(jié)束下一步導(dǎo)航。
2.2.3.3.2 上一步執(zhí)行邏輯
1)還原上一次的歷史狀態(tài);
a)還原變量值;
b)還原孩子堆棧、父親堆棧、當(dāng)前狀態(tài)堆棧;
c)還原孩子變化堆棧、父親變化堆棧;
2)執(zhí)行“下一步”邏輯;
3)結(jié)束“上一步”導(dǎo)航。
2.2.4 指令執(zhí)行
不同指令有著不同的執(zhí)行邏輯,即使相同指令類型的執(zhí)行邏輯也是有差異的。在這里指令的執(zhí)行不同于計算機機器的指令,是一個原子操作,它的粒度更粗些,是一個組合指令,可以由多個指令組成。
指令的執(zhí)行可分為條件計算、斷言賦值(變量賦值)、指令過濾、內(nèi)容顯示。
● 條件計算
條件計算出現(xiàn)在IfNode、LoopNode、AlterNode節(jié)點類型的指令,用于計算該類指令中的條件。
● 斷言賦值
斷言賦值出現(xiàn)在PresetNode、PostsetNode、LoopNode3種類型的節(jié)點中,用于對變量進行賦值操作。
● 指令過濾
指令過濾用于在導(dǎo)航過程中導(dǎo)航器根據(jù)某些條件篩選參與后續(xù)導(dǎo)航節(jié)點,這類指令的執(zhí)行會產(chǎn)生需要參與后續(xù)導(dǎo)航的指令。
● 內(nèi)容顯示
該指令的執(zhí)行一般會在Process數(shù)據(jù)模塊的閱讀器中展示其對于節(jié)點的內(nèi)容,而不同的可顯示指令顯示的內(nèi)容和顯示的方式有著非常大的差異,因此在本文的設(shè)計中引入一種可擴展內(nèi)容執(zhí)行器。
在IETM閱讀器中打開技術(shù)資料手冊,系統(tǒng)進入具體手冊閱讀狀態(tài),原型如圖5所示。的圖標(biāo)分別為“運行”、“上一步”、“下一步”、“返回”等操作。
在原型圖中的手冊目錄下,點擊Process數(shù)據(jù)模塊,系統(tǒng)加載Process數(shù)據(jù)模塊閱讀器,進入Process
● Process數(shù)據(jù)模塊被加載后,系統(tǒng)啟用Process數(shù)據(jù)模塊解析引擎,解析引擎把Process數(shù)據(jù)模塊的內(nèi)容加載到內(nèi)存中,并把它轉(zhuǎn)換成樹狀結(jié)構(gòu)的Process數(shù)據(jù)模塊邏輯模型。
● Process數(shù)據(jù)模塊正式開始導(dǎo)航,系統(tǒng)默認(rèn)以根節(jié)點為運行節(jié)點,開始運行,解析引擎啟用指令讀取器讀取數(shù)據(jù)模塊指令。
● 解析引擎啟動導(dǎo)航器,并且以“下一步”方式驅(qū)動導(dǎo)航器運行,導(dǎo)航器執(zhí)行“下一步”邏輯直至?xí)和!?/p>
● 系統(tǒng)暫停后,解析引擎統(tǒng)一執(zhí)行顯示指令,把內(nèi)容顯示到IETM閱讀器中。
系統(tǒng)暫停后,用戶通過上述四個功能按鈕,可以進一步與解析引擎進行交換,進行“下一步”、“上一步”、“返回”、“運行”等操作。
本文從應(yīng)用需求的角度出發(fā),提出了一種解決S1000DProcess數(shù)據(jù)模塊的解析難題的方法,借鑒堆棧機器的構(gòu)造方法,創(chuàng)新性地使用多個堆棧解決具有樹狀數(shù)據(jù)結(jié)構(gòu)數(shù)據(jù)的Process數(shù)據(jù)模塊的閱讀問題,為Process數(shù)據(jù)模塊閱讀器提供的實現(xiàn)基礎(chǔ)。
導(dǎo)航解析引擎雖然很好地解決Process數(shù)據(jù)模塊的閱讀需求,在設(shè)計上也比較簡潔和統(tǒng)一,但是本設(shè)計中沒有把條件運算、斷言判斷作為指令對待,而是對其進行特殊處理,作為If、Loop指令的附加內(nèi)容有些不妥;另一問題是區(qū)分主動顯示和被動顯示指令應(yīng)該可以避免的;希望后續(xù)的研究中能對其進行改進,使整個解析引擎的解析邏輯更清晰、簡單。
[1] ASD S1000D International Specification for Technical Publications Utilizing a Common Source Database [S].V4.0,2009.05
(編輯:勞邊)
[收修訂稿日期] 2014-09-22
[文章編號][編碼]