Schema in HiveMind

    支持自定義數據格式是HiveMind的又一大特色。通過<schema>元素,可以爲配置擴展點,服務或攔截器的參數定值格式。而且隨着HiveMind的自身發展,Schema所支持內容也會越來越豐富。現階段schema僅支持對一系列element做處理,通過它可以把由它指定的xml文件片段解析成一個對象或對象的集合。
    HiveMind對schema的這種支持源於Apache開元項目Jarkata的一個子項目Digester。Digester是一種基於規則的XML解析技術,它以SAX接口爲基礎,但不同於DOM的解析方法。Digester不會將數據解析爲某一種特殊的格式(如DOM的樹形結構),而是產生一個規則集(規則是一元素路徑爲基礎的),通過定製一些列規則生成一個對象或對象集。這個過程可以理解爲XML到Object的映射過程。Tapestry3就是採用的這種技術對各類配置文件(*.application,*.jwc,*.page)進行解析的。Tapestry4和HiveMind中不再採用這種技術,但是它們使用的解析方式很多都是源於它。
    基於規則的XML解析可以理解爲:規則=路徑+處理;路徑是XML出現的先後順序,而處理是對對應路徑的一個處理,由預先定義的一些列操作完成。在HiveMind裏,<schema>可以包含多個<element>,<element>可以包含多個<attribute>,<element>, <rules> , <conversion>。<element>的name屬性用於定義XML片段中出現的元素,<attribute>用於定義對應元素裏面的屬性。而<rules>和<conversion>都是用於定義規則的,<conversion>是<rules>的一個簡化形式,用於處理最常見的幾種操作。
    下面給出一個<schema>的簡單例子:
<schema>
    <element name="person">
        <attribute name="name"/>
        <rules>
            <create-object class="com.csdn.hivemind.Person"/>
            <read-attribute attribute="name" property="personName"/>
            <invoke-parent method="addElement"/>
        </rules>
        <element name="habit">
            <attribute name="name"/>
            <rules>
                <create-object class="com.csdn.hivemind.Habit"/>
                <read-attribute attribute="name" property="habitName"/>
                <invoke-parent depth="1" method="addHabit"/>
            </rules>
        </element>
        <element name="profession">
            <attribute name="name"/>
            <rules>
                <create-object class="com.csdn.hivemind.Profession"/>
                <read-attribute attribute="name" property="professionName"/>
                <invoke-parent depth="1" method="addProfession"/>
            </rules>
        </element>
    </element>
</schema>
    上例給出了一個schema的簡單例子,通過它可以解析如下的XML片段,併產生一個Person對象:
<person name="Hawk">
    <habit name="sports"/>
    <profession name="student"/>
</person>
    在讀取需要解析XML數據的時候HiveMind會用一個處理器來完成這項工作。在處理之前schema和xml片段都會以樹形形式保存在內存中,處理時處理器將這兩項作爲參數讀入。整個處理的過程如下:schema in hivemind

    從圖中可以看出整個處理的過程是一個遞歸的過程,首先讀入一個xml的元素,找到schema中對應的元素並調用它所有的rule的begin方法。之後xml對象和schema同時往下走一層。XML再次找到一個節點habit,並從schema中找出對應的元素,調用rule的begin方法。此時habit沒有子節點,不再遞歸下去,調用rule的end方法。同樣的順序處理profession元素,之後person的所有子節點處理完,調用它的rule的end方法。
    rule是一系列繼承與統一接口的類,必須實現begin和end方法。不同的規則會決定在哪一個或兩個方法中對元素的數據進行處理。值得注意的是同意個元素的規則begin調用的順序和end調用的順序是相反的。例如對於person元素調用begin的順序是create-object,read-attribute,invoke-parent而調用end的順尋是invoke-parent,read-attribute,create-object。這樣做的目的主要是保證對於每一條rule的end方法,再它之前begin的rule都不會在它之前end。避免造成數據混亂。
    在處理schema時各條rule處理的結果在schema處理器中有一個棧負責保存。每一條create-object規則的begin方法都會往棧頂插入一個對象,並在end方法中彈出。schema處理器會將自身作爲棧底元素首先方法棧中,所以根節點person的invoker-parent將會調用的是schema處理器的addElement方法。而habit和profession的<invoke-parent depth="1" method="..."/>規則調用的將是person的方法。
    在所有操作處理完之後,schema處理器將會放回由addElement方法加入的所有對象,默認爲一個List。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章