Live a simple life

          沉默(zhu_xing@live.cn)
          隨筆 - 48, 文章 - 0, 評(píng)論 - 132, 引用 - 0
          數(shù)據(jù)加載中……

          【Eclipse插件開(kāi)發(fā)】基于WTP開(kāi)發(fā)自定義的JSP編輯器(十):WTP TLD內(nèi)容模型介紹

                     前面的系列文章中,我們已經(jīng)分析了WTP的語(yǔ)法Document(IStructuredDocument)和語(yǔ)義Documnt(ICSSDocument或者IDOMDocument)以及和二者密切相關(guān)的IStructuredModel,并在這基礎(chǔ)之上對(duì)WTP默認(rèn)提供的StructuredTextEditor進(jìn)行了部分功能定制。


                      
                      問(wèn)題出現(xiàn)了,我們想要的信息全部包含在IStructuredDocument、IDOMDocument(ICSSDocument)或IStructuredModel中嗎? 沒(méi)有。例如,如果我們需要訪問(wèn)上圖JSP文檔TLD相關(guān)信息(例如:判斷當(dāng)前JSP文檔中使用的特定標(biāo)簽在TLD中是如何聲明的、和當(dāng)前JSP文檔想關(guān)聯(lián)的TLD是怎樣定義的、、、),這些信息并不是直接放置于語(yǔ)法Document(IStructuredDocument)或者語(yǔ)義Document(IDOMDocument或者ICSSDocument)中的。除了TLD相關(guān)的信息外,我們需要的還有其他的描述信息,所有這些信息可以看做元數(shù)據(jù)信息,WTP將其稱為content model(直譯為內(nèi)容模型吧^_^)。在本節(jié)中我們就先介紹一種內(nèi)容模型:TLD內(nèi)容模型(TLD Content Model),在后面緊接下來(lái)的章節(jié)中,我們會(huì)基于本節(jié)介紹的TLD內(nèi)容模型開(kāi)發(fā)一個(gè)自動(dòng)編輯策略(auto edit strategy)。

                  【TLD Content Document】
                    所謂的TLD Content Document,從字面上就可以猜測(cè)出來(lái)是對(duì)某一TLD的描述文檔。那我們就先看一個(gè)TLD定義文件:
          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
          <taglib>
              
          <tlibversion>1.0</tlibversion>
              
          <jspversion>1.0</jspversion>
              
          <shortname>test1</shortname>
              
          <uri>http://www.aygfsteel.com/zhuxing/tags/test1</uri>
              
          <tag>
                  
          <name>test</name>
                  
          <tagclass>any</tagclass>
                  
          <bodycontent>empty</bodycontent>
                  
          <attribute>
                      
          <name>scope</name>
                      
          <required>true</required>
                      
          <rtexprvalue>true</rtexprvalue>
                  
          </attribute>
              
          </tag>
          </taglib>

                    
                      從結(jié)構(gòu)上看,我們的一個(gè)TLD可以看做一個(gè)樹(shù)形結(jié)構(gòu)的對(duì)象,具體節(jié)點(diǎn)種類可以分為:taglib、tag、attribute,示意圖如下:
                      
                      對(duì)應(yīng)于上圖,我們定義了一個(gè)uri為http://www.aygfsteel.com/zhuxing/tags/test1的TLD(TLD Document),內(nèi)含一個(gè)名為test的標(biāo)簽(TLD Element),該標(biāo)簽中含有一個(gè)名為scope的屬性(TLD Attribute)。如果我們能夠拿到這樣的一個(gè)樹(shù)形結(jié)構(gòu)文檔對(duì)象,我們就可以獲取到我們想獲取的有關(guān)特定TLD的信息了。上圖中,其實(shí)也列舉了幾個(gè)相關(guān)的重要接口,這也是我們以后在操作TLD Content Model的時(shí)候需要經(jīng)常打交道的:
                  org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDDocument
                  org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDElementDeclaration
                  org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDAttributeDeclaration

                【W(wǎng)TP Content Model】
                     我們?cè)诒竟?jié)開(kāi)頭部分就說(shuō)了,TLD Content Model只是一種WTP Content Model,WTP為所有類型的content model設(shè)計(jì)了統(tǒng)一的類型接口(樹(shù)形結(jié)構(gòu)composite的接口實(shí)現(xiàn)):
                      
                      從上面的類型體系圖可以看出,CMNode就是WTP內(nèi)容模型樹(shù)的統(tǒng)一頂級(jí)接口,相關(guān)接口定義在org.eclipse.wst.xml.core插件中,大家可以去看一下。我們?cè)谑褂肳TP content model的時(shí)候常用的接口有:
                      1、org.eclipse.wst.xml.core.internal.contentmodel.CMNode
                      2、org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap
                      3、org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration
                      4、org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration
                      5、org.eclipse.wst.xml.core.internal.contentmodel.CMDocument
                      6、org.eclipse.wst.xml.core.internal.contentmodel.CMEntityDeclaration
                      7、org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMNodeWrapper(CMNode的適配接口)

                      我們上面列舉的三個(gè)關(guān)于TLD Content Model的接口都是CMNode子接口:
                      1、TLDDocument接口是CMDocument的子接口
                      2、TLDElementDeclaration接口是CMElementDeclaration(CMContent)的子接口
                      3、TLDAttributeDeclaration接口是CMAttributeDeclaration的子接口
                  
                      PS:有興趣可以看一下另外兩種常用的content model:HTMLCMDocument和JSPCMDocument。
                      
                      【使用TLD Content Model】
                         WTP content model的創(chuàng)建不需要我們負(fù)責(zé),我們只是讀取content model里的數(shù)據(jù),常用接口有兩類:
                         1、org.eclipse.wst.xml.core插件中定義的CMNode系列抽象接口
                         2、特定類型content model相關(guān)的擴(kuò)展接口
                        上面說(shuō)的第一類接口我們已經(jīng)列舉過(guò),有關(guān)第二類接口也非常常用,它幫助我們更方便的訪問(wèn)特定content model相關(guān)的信息。例如,相對(duì)于TLD Content Model,相關(guān)的擴(kuò)展接口就是我們上面提到的TLDDocument、TLDElementDeclaration和TLDAttributeDeclaration。
                      
                          【TLDDocument、TLDElementDeclaration和TLDAttributeDeclaration】
                          1、TLDDocument接口提供的操作:
                          
                          我們可以很方便地借助TLDDocument接口訪問(wèn)到的信息:URI、version、shortname等,通過(guò)其父接口CMDocument.getElements操作獲取tld element列表(TLDTLDElementDeclaration列表)。

                          2、TLDElementDeclaration接口提供的操作:
                          
                          我們可以很方便地借助TLDElementDeclaration接口訪問(wèn)到的信息:tag class、body content等,通過(guò)其父接口CMElementDeclaration.getAttributes操作獲取tld attribute列表(TLDAttributeDeclaration列表)。

                          3、TLDAttributeDeclaration接口提供的操作:
                          
                          我們可以很方便地借助TLDAttributeDeclaration接口訪問(wèn)到的信息:是否是必填屬性等
                          
                          【TaglibTracker:taglib條目】
                  
                            如上圖所示,每一個(gè)tld條目可以被表示為一個(gè)taglib tracker,這里的taglib tracker是位置相關(guān)的?。?!我們接著看一下TaglibTracker(org.eclipse.jst.jsp.core.internal.contentmodel.tld.TaglibTracker)的實(shí)現(xiàn)代碼:   

          /*******************************************************************************
           * Copyright (c) 2004 IBM Corporation and others.
           * All rights reserved. This program and the accompanying materials
           * are made available under the terms of the Eclipse Public License v1.0
           * which accompanies this distribution, and is available at
           * 
          http://www.eclipse.org/legal/epl-v10.html
           * 
           * Contributors:
           *     IBM Corporation - initial API and implementation
           ******************************************************************************
          */
          package org.eclipse.jst.jsp.core.internal.contentmodel.tld;



          import org.eclipse.jst.jsp.core.internal.contentmodel.CMDocumentWrapperImpl;
          import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
          import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
          import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocumentTracker;

          /**
           * TaglibTracker class
           
          */
          public class TaglibTracker extends CMDocumentWrapperImpl implements CMDocumentTracker {

              
          private IStructuredDocumentRegion fStructuredDocumentRegion;

              
          public TaglibTracker(String newURI, String newPrefix, CMDocument tld, IStructuredDocumentRegion aStructuredDocumentRegion) {
                  
          super(newURI, newPrefix, tld);
                  fStructuredDocumentRegion 
          = aStructuredDocumentRegion;
              }

              
          public IStructuredDocumentRegion getStructuredDocumentRegion() {
                  
          return fStructuredDocumentRegion;
              }

              
          public String toString() {
                  
          if (getStructuredDocumentRegion() != null)
                      
          return getPrefix() + "@" + getStructuredDocumentRegion().getStartOffset(); //$NON-NLS-1$
                  return super.toString();
              }
          }

                          分析以上代碼實(shí)現(xiàn),我們看到兩點(diǎn):
                          1、TaglibTracker是和特定IStructuredDocumentRegion綁定的,間接是位置相關(guān)的
                          2、TaglibTracker實(shí)現(xiàn)了CMNodeWrapper接口,可以適配為對(duì)應(yīng)的original CMNode,可以通過(guò)TaglibTracker獲取對(duì)應(yīng)的CMDocument(TLDDocument)。

                           附加說(shuō)明,taglib tracker的收集通過(guò)兩種途徑:一是通過(guò)taglib指令直接引用;二是include指令間接導(dǎo)入(被include文件中的tld將被加入到當(dāng)前JSP 文檔對(duì)應(yīng)的taglib tracker列表中)

                      【TLDCMDocumentManager】
                      
          問(wèn)題出來(lái)了:前面講了這么多,怎么獲取TLD Content Model實(shí)例呢?TLDCMDocumentManager(org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager),TLDCMDocumentManager的獲取需要借助于TaglibController(org.eclipse.jst.jsp.core.internal.contentmodel.TaglibController)中定義的getTLDCMDocumentManager(IDocument document)接口。   
                    
                          TLDCMDocumentManager中定義了幾個(gè)非常重要的操作,我們使用的時(shí)候要區(qū)分對(duì)待:
                          List  getTaglibTrackers():當(dāng)前文檔相關(guān)的taglib tracker條目,隨著對(duì)應(yīng)IStructuredDocument的變化而變化
                          Hashtable  getDocuments():當(dāng)前文檔相關(guān)的taglib tracker條目,只增不減,不會(huì)隨著IStructuredDocument的變化而即時(shí)刪除掉對(duì)應(yīng)的無(wú)效taglib tracker條目
                          【說(shuō)明】:如果想獲取實(shí)時(shí)準(zhǔn)確地taglib tracker信息,請(qǐng)使用getTaglibTrackers操作?。?!                

                          List getCMDocumentTrackers(int offset):特定位置之前引入的taglib tracker條目
                          List getCMDocumentTrackers(String prefix, int offset):特定位置之前引入的指定prefix的taglib tracker條目

                          【說(shuō)明】:前面我們介紹TaglibTracker的時(shí)候已經(jīng)說(shuō)過(guò)了TaglibTracker是位置相關(guān)的,一個(gè)TaglibTracker是和特定的IStructuredDocumentRegion綁定的,由于IStructuredDocumentRegion本身持有準(zhǔn)確的位置信息,所以查詢特定位置之前引入的taglib tracker條目成為可能。聯(lián)系實(shí)際更加直觀,在特定taglib指令之前使用對(duì)應(yīng)的標(biāo)簽,則會(huì)出現(xiàn)標(biāo)簽不識(shí)別的問(wèn)題。
                          
                          【TLD Content Model使用的一般流程】
                                          

                          【代碼示例】
                           示例代碼一:獲取特定JSP文檔對(duì)應(yīng)的TLD Content Model(TLD CMDocument實(shí)現(xiàn))列表

          /**
               * 獲取特定JSP文檔相關(guān)的TLD列表
               * 
               * 
          @param structuredDocument
               * 
          @return
               
          */
              
          public static TLDDocument[] getTLDDoucments(IStructuredDocument structuredDocument) {
                  
          //獲取本structuredDocument對(duì)應(yīng)的TLDCMDocumentManager實(shí)例
                  TLDCMDocumentManager tldDocumentManager = TaglibController.getTLDCMDocumentManager(structuredDocument);
                  
                  
          //獲取當(dāng)前文檔中的taglib tracker條目
                  List taglibTrackers = tldDocumentManager.getTaglibTrackers();
                  
                  
          //獲取taglib tracker條目對(duì)應(yīng)的TLDDocument
                  TLDDocument[] tldDocuments = new TLDDocument[taglibTrackers.size()];
                  
          for (int i = 0; i < taglibTrackers.size(); i++) {
                      TaglibTracker taglibTracker 
          = (TaglibTracker)taglibTrackers.get(i);
                      tldDocuments[i] 
          = (TLDDocument)taglibTracker.getDocument();
                  }
                  
          return tldDocuments;
              }
                          
                          示例代碼二:分析一個(gè)特定的TLDDocument(分析tld element,分析tld attribute)  
          /**
               * 獲取特定TLDDocument中的tag列表(tld element列表)
               * 
               * 
          @param tldDocument
               * 
          @return
               
          */
              
          public static TLDElementDeclaration[] getTags(TLDDocument tldDocument) {
                  
          //獲取tld element列表
                  CMNamedNodeMap children = tldDocument.getElements();
                  
                  TLDElementDeclaration[] tags 
          = new TLDElementDeclaration[children.getLength()];
                  
          for (int i = 0; i < tags.length; i++) {
                      tags[i] 
          = (TLDElementDeclaration)children.item(i);
                  }
                  
          return tags;
              }
              
              
          /**
               * 獲取特定tag中(tld element)定義的屬性列表
               * 
               * 
          @param tagElement
               * 
          @return
               
          */
              
          public static TLDAttributeDeclaration[] getAttributes(TLDElementDeclaration tagElement) {
                  
          //獲取tld attribute列表
                  CMNamedNodeMap children = tagElement.getAttributes();
                  
                  TLDAttributeDeclaration[] attributes 
          = new TLDAttributeDeclaration[children.getLength()];
                  
          for (int i = 0; i < attributes.length; i++) {
                      attributes[i] 
          = (TLDAttributeDeclaration)children.item(i);
                  }
                  
          return attributes;
              }

                      
                     PS:說(shuō)明,有關(guān)TLDCMDocumentManager中提供的位置相關(guān)的taglib tracker查詢接口大家可以自己編寫(xiě)相應(yīng)的測(cè)試代碼,著重理解taglib tracker位置相關(guān)的特性。

                  

                      下一節(jié)中,我們會(huì)開(kāi)發(fā)一個(gè)TLD Content Model分析視圖,之后一節(jié)會(huì)定制WTP編輯器默認(rèn)的自動(dòng)編輯策略(auto edit strategy)。



          本博客中的所有文章、隨筆除了標(biāo)題中含有引用或者轉(zhuǎn)載字樣的,其他均為原創(chuàng)。轉(zhuǎn)載請(qǐng)注明出處,謝謝!

          posted on 2008-10-13 17:50 zhuxing 閱讀(2439) 評(píng)論(3)  編輯  收藏 所屬分類: Eclipse Plug-in & OSGIWTP(Web Tools Platform)

          評(píng)論

          # re: 【Eclipse插件開(kāi)發(fā)】基于WTP開(kāi)發(fā)自定義的JSP編輯器(十):WTP TLD內(nèi)容模型介紹  回復(fù)  更多評(píng)論   

          朱星大哥,這一系列的文章簡(jiǎn)直太經(jīng)典了,頂一個(gè)!
          前面的StructrueModel的分析視圖代碼,好像放錯(cuò)了,放成StructuredDocument的分析視圖代碼了,能不能更新一下啊,小弟自己跟著步驟,沒(méi)弄出來(lái),好像treeviewer.serInput 沒(méi)有調(diào)用,我自己把 structureModel傳進(jìn)去,缺又老是報(bào)錯(cuò),求救啊!
          2008-10-15 21:17 | 飛揚(yáng)的麥子

          # re: 【Eclipse插件開(kāi)發(fā)】基于WTP開(kāi)發(fā)自定義的JSP編輯器(十):WTP TLD內(nèi)容模型介紹  回復(fù)  更多評(píng)論   

          好了,我問(wèn)題解決了,是自己的一些代碼沒(méi)寫(xiě)全呵呵,不過(guò)最好還是把 代碼換成正確的,方便后來(lái)人啊!不好意思,您的名字打錯(cuò)了,應(yīng)該是朱興!
          2008-10-15 22:39 | 飛揚(yáng)的麥子

          # re: 【Eclipse插件開(kāi)發(fā)】基于WTP開(kāi)發(fā)自定義的JSP編輯器(十):WTP TLD內(nèi)容模型介紹[未登錄](méi)  回復(fù)  更多評(píng)論   

          請(qǐng)問(wèn) wtp怎么加載的這個(gè)TLD文件,是怎么找到的? 怎么確定是哪一個(gè)tld文件,從哪里指定???你程序里面這個(gè)TLD都沒(méi)加載到。。。
          2012-04-26 16:51 | john

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 土默特左旗| 泰顺县| 平山县| 甘德县| 石门县| 甘南县| 莒南县| 达拉特旗| 会同县| 吉木萨尔县| 东丰县| 大冶市| 郑州市| 三台县| 大新县| 五华县| 开阳县| 罗甸县| 绥阳县| 孝感市| 闵行区| 宿迁市| 尚义县| 河北省| 巧家县| 邮箱| 东乡| 彰武县| 错那县| 济南市| 会泽县| 青海省| 新蔡县| 黄龙县| 略阳县| 泸西县| 昭觉县| 乌鲁木齐县| 沾化县| 洞口县| 黎平县|