【Eclipse插件开发】基于WTP开发自定义的JSP编辑器(三) :WTP Structured Document

【Eclipse插件开发】基于WTP开发自定义的JSP编辑器(三) :WTP Structured Document

        上一篇中我们已经基于WTP的StructuredTextEditor建立了自己的JSPEditor,这篇将介绍对于我们Editor最重要的数据模型之一:IStructuredDocument(org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument),下一篇将介绍另外一个IStructuredModel。看一下IStructuredDocument的类型体系如下:
        
        上图中,我们看到了IStructuredDocument的身影,是JFace Text Framework中IDocument接口实现,选中的JobSafeStructureedDocument就是我们要面对的IStructuredDocument实现。
        PS:从类型名称就可以猜测的出来,BasicStructuredDocument应该是一个类似于Default Adapter的角色,具体呢? 自己去看一下^_^


        【IStructuredDocument结构--Composite】
          只要是我们观察一下JSP就知道,其他本质上是一个树状结构的文档,怎么来建立这种文档呢? 很自然的做法是底层用xml来描述JSP,然后建立起这种xml模型,同时建立起我们的Document实现(说明:提到的WTP XML模型会在下一篇中介绍--》 IStructuredModel)。既然是树状的,那一般而言接口会按照Composite模式来写。我们先看一下一张IStructuredDocument接口示意图吧:
           
            现在,我们暂且需要记住:在WTP世界中,一个页面资源(JSP、html等)可以被描述为一个IStrucuturedDocument,这个document是由若干个IStructuredDocumentRegion组成,每个IStructuredDocumentRegion又会由多个ITextRegion组成。拿一个真实JSP示意一把:
            
            
          提到Composite模式,现在我们就看一下谁是里面的节点(Node)、谁又是树枝节点(Container Node)。到目前我们猜测ITextRegion应该是普通节点,IStructuredDocumentRegion应该是树枝节点,我们看一下IStructuredDocumentRegion的sub type图:
        
        更准确说:ITextRegion是节点,ITextRegionCollection是树枝节点(我们认为IStructuredDocumentRegion是树枝节点问题也不大^_^)。

        【IStructuredDocument创建和获取方式】
            如何来自己创建IStructuredDocument呢?常用的如下几种:
            1、IModelManager(org.eclipse.wst.sse.core.internal.provisional.IModelManager)
                  createStructuredDocumentFor             
                  createNewStructuredDocumentFor     
            
            2、IStructuredModel(在已经存在strutured model的情况下,建议使用)
                  IStructuredModel.getStructuredDocument
                  或者IStructuredModel.getModelHandler().getDocumentLoader().createNewStructuredDocument  

            
3、IDocumentLoader.createNewStructuredDocument

                   
            4、通过IModelHandler()获取IDocumentLoader,然后创建Structured Document            
            5、。。。其他方式
            
            示例代码:   

 1  public   void  createStructuredDocument(IFile jspFile) {
 2           try  {
 3               // 获取org.eclipse.wst.sse.core.internal.provisional.IModelManager
 4              IModelManager manager  =  StructuredModelManager.getModelManager();
 5              manager.createNewStructuredDocumentFor(jspFile);
 6              manager.createStructuredDocumentFor(jspFile);  
 7              
 8               // 通过IStructuredModel.getStructuredDocument()
 9              IStructuredModel structuredModel  =  manager.getModelForRead(jspFile);
10              structuredModel.getStructuredDocument();
11              
12               // 根据文件类型计算对应的IModelHandler,然后获取IDocumentLoader
13              IModelHandler modelHandler  =  ModelHandlerRegistry.getInstance().getHandlerFor(jspFile);
14              IDocumentLoader documentLoader  =  modelHandler.getDocumentLoader();
15              documentLoader.createNewStructuredDocument(jspFile);
16              
17               // 直接调用对应的IModelManager实现(例如解析一般的jsp)
18               new  ModelHandlerForJSP().getDocumentLoader().createNewStructuredDocument(jspFile);
19              
20               // 直接调用对应的IDocumentLoader实现(例如解析一般的jsp)
21               new  JSPDocumentLoader().createNewStructuredDocument(jspFile);
22              
23               // 其他途径
24          }  catch  (Exception e) {
25               // TODO:log exception
26          }
27      }

        
        注意:
        1、IStructuredDocument是相对比较重量级的对象,如果对应的IStructuredModel已经存在,则可以利用IStructuredModel中缓存的IStructuredDocument。(这个在后面介绍IStructuredModel的时候会详细介绍^_^)
        2、StructuredModelManager定义在公共包中,IModelManager反而定义在internal包中,它要干吗???^_^

       【ITextRegion相关】
       说明:不要将JFace Text Framework的IRegion和WTP的ITextRegion混淆,但是作用是类似的,核心作用都是提供位置信息。
      
我们首先来关注一下这个ITextRegion(org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion),毕竟IStructuredDocument树中所有节点都是ITextRegion类型:
        
        我们看到,ITextRegion提供的最核心操作是:位置相关(start、text end、end),这里的所有位置信息是相对于其容器节点IStructuredDocumentRegion的,不是相对于IStructuredDocument(ITextRegionCollection)的;类型相关(getType()),返回region type。我们看到ITextRegion并没有提供获取文本的方法,有了相对于ITextRegionCollection的位置信息,借助于位置信息用ITextRegionCollection获取不就可以了~_~

        既然我们前面说过了,ITextRegion是节点顶级类型,ITextRegionCollection象征着树枝节点(例如IStructuredDocumentRegion),那么如果一种节点类型继承自ITextRegion同时又不是ITextRegionCollection的子类型,那么这种节点就是我们说的树叶节点了(没有孩子^_^):
        
        看一下上图,子类型名称已经清晰的告诉我们各个子类型是代表什么的了。我们拿几个实际的例子来看一下吧,例子干脆就取自上面图片中的JSP吧:
        示例:<html xmlns="http://www.w3.org/1999/xhtml">

        分析: TagOpenRegion          -->    "<"
                     TagNameRegion         -->    "html "
                     AttributeNameRegion  -->    "xmlns"
                     AttributeEqualsRegion -->    "="
                     AttributeValueRegion  -->    "http://www.w3.org/1999/xhtml"
                    TagOpenRegion          -->    ">"
        
        【分析ITextRegion具体子类的类型】
         看到上面的分析,我们可能会想,是否需要instanceof(例如 if (instanceof AttributeNameRegion ) .... )来判断具体叶子节点的类型呢?如果你喜欢,这当然可以;还有一种更方便的方法,那就是借助于ITextRegion.getType()返回接口来判断,示例分别如下:
 1  public   boolean  isTagNameRegion(ITextRegion region) {
 2           // 实现方式一:instanceof判断
 3           if  (region  instanceof  TagNameRegion)
 4               return   true ;
 5          
 6           // 实现方式二:type信息判断
 7           if  (DOMRegionContext.XML_TAG_NAME.equals(region.getType()))
 8               return   true ;
 9          
10           return   false ;
11      }
        
        DOMRegionContext(org.eclipse.wst.xml.core.internal.regions.DOMRegionContext)常量接口中枚举了所有的有关XML的text region类型常量: 
 1  package  org.eclipse.wst.xml.core.internal.regions;
 2 
 3  public   interface  DOMRegionContext {
 4 
 5       public   static   final  String BLOCK_TEXT  =   " BLOCK_TEXT " // $NON-NLS-1$
 6 
 7       public   static   final  String UNDEFINED  =   " UNDEFINED " // $NON-NLS-1$
 8 
 9       public   static   final  String WHITE_SPACE  =   " WHITE_SPACE " // $NON-NLS-1$
10       public   static   final  String XML_ATTLIST_DECL_CLOSE  =   " XML_ATTLIST_DECL_CLOSE " // $NON-NLS-1$
11       public   static   final  String XML_ATTLIST_DECL_CONTENT  =   " XML_ATTLIST_DECL_CONTENT " // $NON-NLS-1$
12       public   static   final  String XML_ATTLIST_DECL_NAME  =   " XML_ATTLIST_DECL_NAME " // $NON-NLS-1$
13 
14       public   static   final  String XML_ATTLIST_DECLARATION  =   " XML_ATTLIST_DECLARATION " // $NON-NLS-1$
15       public   static   final  String XML_CDATA_CLOSE  =   " XML_CDATA_CLOSE " // $NON-NLS-1$
16       public   static   final  String XML_CDATA_OPEN  =   " XML_CDATA_OPEN " // $NON-NLS-1$
17       public   static   final  String XML_CDATA_TEXT  =   " XML_CDATA_TEXT " // $NON-NLS-1$
18       public   static   final  String XML_CHAR_REFERENCE  =   " XML_CHAR_REFERENCE " // $NON-NLS-1$
19       public   static   final  String XML_COMMENT_CLOSE  =   " XML_COMMENT_CLOSE " // $NON-NLS-1$
20 
21       public   static   final  String XML_COMMENT_OPEN  =   " XML_COMMENT_OPEN " // $NON-NLS-1$
22       public   static   final  String XML_COMMENT_TEXT  =   " XML_COMMENT_TEXT " // $NON-NLS-1$
23 
24       public   static   final  String XML_CONTENT  =   " XML_CONTENT " // $NON-NLS-1$
25       public   static   final  String XML_DECLARATION_CLOSE  =   " XML_DECLARATION_CLOSE " // $NON-NLS-1$
26 
27       public   static   final  String XML_DECLARATION_OPEN  =   " XML_DECLARATION_OPEN " // $NON-NLS-1$
28 
29       public   static   final  String XML_DOCTYPE_DECLARATION  =   " XML_DOCTYPE_DECLARATION " // $NON-NLS-1$
30       public   static   final  String XML_DOCTYPE_DECLARATION_CLOSE  =   " XML_DOCTYPE_DECLARATION_CLOSE " // $NON-NLS-1$
31       public   static   final  String XML_DOCTYPE_EXTERNAL_ID_PUBLIC  =   " XML_DOCTYPE_EXTERNAL_ID_PUBLIC " // $NON-NLS-1$
32       public   static   final  String XML_DOCTYPE_EXTERNAL_ID_PUBREF  =   " XML_DOCTYPE_EXTERNAL_ID_PUBREF " // $NON-NLS-1$
33       public   static   final  String XML_DOCTYPE_EXTERNAL_ID_SYSREF  =   " XML_DOCTYPE_EXTERNAL_ID_SYSREF " // $NON-NLS-1$
34       public   static   final  String XML_DOCTYPE_EXTERNAL_ID_SYSTEM  =   " XML_DOCTYPE_EXTERNAL_ID_SYSTEM " // $NON-NLS-1$
35       public   static   final  String XML_DOCTYPE_INTERNAL_SUBSET  =   " XML_DOCTYPE_INTERNAL_SUBSET " // $NON-NLS-1$
36       public   static   final  String XML_DOCTYPE_NAME  =   " XML_DOCTYPE_NAME " // $NON-NLS-1$
37       public   static   final  String XML_ELEMENT_DECL_CLOSE  =   " XML_ELEMENT_DECL_CLOSE " // $NON-NLS-1$
38       public   static   final  String XML_ELEMENT_DECL_CONTENT  =   " XML_ELEMENT_DECL_CONTENT " // $NON-NLS-1$
39       public   static   final  String XML_ELEMENT_DECL_NAME  =   " XML_ELEMENT_DECL_NAME " // $NON-NLS-1$
40 
41       public   static   final  String XML_ELEMENT_DECLARATION  =   " XML_ELEMENT_DECLARATION " // $NON-NLS-1$
42       public   static   final  String XML_EMPTY_TAG_CLOSE  =   " XML_EMPTY_TAG_CLOSE " // $NON-NLS-1$
43       public   static   final  String XML_END_TAG_OPEN  =   " XML_END_TAG_OPEN " // $NON-NLS-1$
44       public   static   final  String XML_ENTITY_REFERENCE  =   " XML_ENTITY_REFERENCE " // $NON-NLS-1$
45 
46       public   static   final  String XML_PE_REFERENCE  =   " XML_PE_REFERENCE " // $NON-NLS-1$
47       public   static   final  String XML_PI_CLOSE  =   " XML_PI_CLOSE " // $NON-NLS-1$
48       public   static   final  String XML_PI_CONTENT  =   " XML_PI_CONTENT " // $NON-NLS-1$
49       public   static   final  String XML_PI_OPEN  =   " XML_PI_OPEN " // $NON-NLS-1$
50       public   static   final  String XML_TAG_ATTRIBUTE_EQUALS  =   " XML_TAG_ATTRIBUTE_EQUALS " // $NON-NLS-1$
51       public   static   final  String XML_TAG_ATTRIBUTE_NAME  =   " XML_TAG_ATTRIBUTE_NAME " // $NON-NLS-1$
52       public   static   final  String XML_TAG_ATTRIBUTE_VALUE  =   " XML_TAG_ATTRIBUTE_VALUE " // $NON-NLS-1$
53       public   static   final  String XML_TAG_CLOSE  =   " XML_TAG_CLOSE " // $NON-NLS-1$
54       public   static   final  String XML_TAG_NAME  =   " XML_TAG_NAME " // $NON-NLS-1$
55 
56       public   static   final  String XML_TAG_OPEN  =   " XML_TAG_OPEN " // $NON-NLS-1$
57  }
            
             DOMJSPRegionContexts(org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts)常量接口中枚举了所有的有关JSP的text region类型常量
 1  public   interface  DOMJSPRegionContexts  extends  DOMRegionContext {
 2       public   static   final  String JSP_CLOSE  =   " JSP_CLOSE " // $NON-NLS-1$
 3       public   static   final  String JSP_COMMENT_CLOSE  =   " JSP_COMMENT_CLOSE " // $NON-NLS-1$
 4 
 5       public   static   final  String JSP_COMMENT_OPEN  =   " JSP_COMMENT_OPEN " // $NON-NLS-1$
 6       public   static   final  String JSP_COMMENT_TEXT  =   " JSP_COMMENT_TEXT " // $NON-NLS-1$
 7 
 8       public   static   final  String JSP_CONTENT  =   " JSP_CONTENT " // $NON-NLS-1$
 9       public   static   final  String JSP_DECLARATION_OPEN  =   " JSP_DECLARATION_OPEN " // $NON-NLS-1$
10       public   static   final  String JSP_DIRECTIVE_CLOSE  =   " JSP_DIRECTIVE_CLOSE " // $NON-NLS-1$
11       public   static   final  String JSP_DIRECTIVE_NAME  =   " JSP_DIRECTIVE_NAME " // $NON-NLS-1$
12 
13       public   static   final  String JSP_DIRECTIVE_OPEN  =   " JSP_DIRECTIVE_OPEN " // $NON-NLS-1$
14       public   static   final  String JSP_EL_CLOSE  =   " JSP_EL_CLOSE " // $NON-NLS-1$
15       public   static   final  String JSP_EL_CONTENT  =   " JSP_EL_CONTENT " // $NON-NLS-1$
16       public   static   final  String JSP_EL_DQUOTE  =   " JSP_EL_DQUOTE " // $NON-NLS-1$
17 
18       public   static   final  String JSP_EL_OPEN  =   " JSP_EL_OPEN " // $NON-NLS-1$
19       public   static   final  String JSP_EL_QUOTED_CONTENT  =   " JSP_EL_QUOTED_CONTENT " // $NON-NLS-1$
20       public   static   final  String JSP_EL_SQUOTE  =   " JSP_EL_SQUOTE " // $NON-NLS-1$
21       public   static   final  String JSP_EXPRESSION_OPEN  =   " JSP_EXPRESSION_OPEN " // $NON-NLS-1$
22 
23       public   static   final  String JSP_ROOT_TAG_NAME  =   " JSP_ROOT_TAG_NAME " // $NON-NLS-1$
24 
25       public   static   final  String JSP_SCRIPTLET_OPEN  =   " JSP_SCRIPTLET_OPEN " // $NON-NLS-1$
26       public   static   final  String JSP_VBL_CLOSE  =   " JSP_VBL_CLOSE " // $NON-NLS-1$
27       public   static   final  String JSP_VBL_CONTENT  =   " JSP_VBL_CONTENT " // $NON-NLS-1$
28       public   static   final  String JSP_VBL_DQUOTE  =   " JSP_VBL_DQUOTE " // $NON-NLS-1$
29       public   static   final  String JSP_VBL_OPEN  =   " JSP_VBL_OPEN " // $NON-NLS-1$
30       public   static   final  String JSP_VBL_QUOTED_CONTENT  =   " JSP_VBL_QUOTED_CONTENT " // $NON-NLS-1$
31       public   static   final  String JSP_VBL_SQUOTE  =   " JSP_VBL_SQUOTE " // $NON-NLS-1$
32       public   static   final  String XML_TAG_ATTRIBUTE_VALUE_DQUOTE  =   " XML_TAG_ATTRIBUTE_VALUE_DQUOTE " // $NON-NLS-1$
33 
34       public   static   final  String XML_TAG_ATTRIBUTE_VALUE_SQUOTE  =   " XML_TAG_ATTRIBUTE_VALUE_SQUOTE " // $NON-NLS-1$
35  }
36 
            
            CSSRegionContexts(org.eclipse.wst.css.core.internal.parserz.CSSRegionContexts)常量接口中枚举了所有的有关CSS的text region类型常量: 
 1  public   interface  CSSRegionContexts {
 2       public   static   final  String CSS_COMMENT  =   " COMMENT " // $NON-NLS-1$
 3       public   static   final  String CSS_CDO  =   " CDO " // $NON-NLS-1$
 4       public   static   final  String CSS_CDC  =   " CDC " // $NON-NLS-1$
 5       public   static   final  String CSS_S  =   " S " // $NON-NLS-1$
 6 
 7       public   static   final  String CSS_DELIMITER  =   " DELIMITER " // $NON-NLS-1$
 8       public   static   final  String CSS_LBRACE  =   " LBRACE " // $NON-NLS-1$
 9       public   static   final  String CSS_RBRACE  =   " RBRACE " // $NON-NLS-1$
10 
11       public   static   final  String CSS_IMPORT  =   " IMPORT " // $NON-NLS-1$
12       public   static   final  String CSS_PAGE  =   " PAGE " // $NON-NLS-1$
13       public   static   final  String CSS_MEDIA  =   " MEDIA " // $NON-NLS-1$
14       public   static   final  String CSS_FONT_FACE  =   " FONT_FACE " // $NON-NLS-1$
15       public   static   final  String CSS_CHARSET  =   " CHARSET " // $NON-NLS-1$
16       public   static   final  String CSS_ATKEYWORD  =   " ATKEYWORD " // $NON-NLS-1$
17 
18       public   static   final  String CSS_STRING  =   " STRING " // $NON-NLS-1$
19       public   static   final  String CSS_URI  =   " URI " // $NON-NLS-1$
20       public   static   final  String CSS_MEDIUM  =   " MEDIUM " // $NON-NLS-1$
21       public   static   final  String CSS_MEDIA_SEPARATOR  =   " MEDIA_SEPARATOR " // $NON-NLS-1$
22 
23       public   static   final  String CSS_CHARSET_NAME  =   " CHARSET_NAME " // $NON-NLS-1$
24 
25       public   static   final  String CSS_PAGE_SELECTOR  =   " CSS_PAGE_SELECTOR " // $NON-NLS-1$
26 
27       public   static   final  String CSS_SELECTOR_ELEMENT_NAME  =   " SELECTOR_ELEMENT_NAME " // $NON-NLS-1$
28       public   static   final  String CSS_SELECTOR_UNIVERSAL  =   " SELECTOR_UNIVERSAL " // $NON-NLS-1$
29       public   static   final  String CSS_SELECTOR_PSEUDO  =   " SELECTOR_PSEUDO " // $NON-NLS-1$
30       public   static   final  String CSS_SELECTOR_CLASS  =   " SELECTOR_CLASS " // $NON-NLS-1$
31       public   static   final  String CSS_SELECTOR_ID  =   " SELECTOR_ID " // $NON-NLS-1$
32       public   static   final  String CSS_SELECTOR_COMBINATOR  =   " SELECTOR_COMBINATOR " // $NON-NLS-1$
33       public   static   final  String CSS_SELECTOR_SEPARATOR  =   " SELECTOR_SEPARATOR " // $NON-NLS-1$
34 
35       public   static   final  String CSS_SELECTOR_ATTRIBUTE_START  =   " SELECTOR_ATTRIBUTE_START " // $NON-NLS-1$
36       public   static   final  String CSS_SELECTOR_ATTRIBUTE_END  =   " SELECTOR_ATTRIBUTE_END " // $NON-NLS-1$
37       public   static   final  String CSS_SELECTOR_ATTRIBUTE_NAME  =   " SELECTOR_ATTRIBUTE_NAME " // $NON-NLS-1$
38       public   static   final  String CSS_SELECTOR_ATTRIBUTE_VALUE  =   " SELECTOR_ATTRIBUTE_VALUE " // $NON-NLS-1$
39       public   static   final  String CSS_SELECTOR_ATTRIBUTE_OPERATOR  =   " SELECTOR_ATTRIBUTE_OPERATOR " // $NON-NLS-1$
40 
41       public   static   final  String CSS_DECLARATION_PROPERTY  =   " DECLARATION_PROPERTY " // $NON-NLS-1$
42       public   static   final  String CSS_DECLARATION_SEPARATOR  =   " DECLARATION_SEPARATOR " // $NON-NLS-1$
43       public   static   final  String CSS_DECLARATION_DELIMITER  =   " DECLARATION_DELIMITER " // $NON-NLS-1$
44       public   static   final  String CSS_DECLARATION_VALUE_IDENT  =   " DECLARATION_VALUE_IDENT " // $NON-NLS-1$
45       public   static   final  String CSS_DECLARATION_VALUE_DIMENSION  =   " DECLARATION_VALUE_DIMENSION " // $NON-NLS-1$
46       public   static   final  String CSS_DECLARATION_VALUE_PERCENTAGE  =   " DECLARATION_VALUE_PERCENTAGE " // $NON-NLS-1$
47       public   static   final  String CSS_DECLARATION_VALUE_NUMBER  =   " DECLARATION_VALUE_NUMBER " // $NON-NLS-1$
48       public   static   final  String CSS_DECLARATION_VALUE_FUNCTION  =   " DECLARATION_VALUE_FUNCTION " // $NON-NLS-1$
49       public   static   final  String CSS_DECLARATION_VALUE_PARENTHESIS_CLOSE  =   " DECLARATION_VALUE_PARENTHESIS_CLOSE " // $NON-NLS-1$
50       public   static   final  String CSS_DECLARATION_VALUE_STRING  =   " DECLARATION_VALUE_STRING " // $NON-NLS-1$
51       public   static   final  String CSS_DECLARATION_VALUE_URI  =   " DECLARATION_VALUE_URI " // $NON-NLS-1$
52       public   static   final  String CSS_DECLARATION_VALUE_HASH  =   " DECLARATION_VALUE_HASH " // $NON-NLS-1$
53       public   static   final  String CSS_DECLARATION_VALUE_UNICODE_RANGE  =   " DECLARATION_VALUE_UNICODE_RANGE " // $NON-NLS-1$
54       public   static   final  String CSS_DECLARATION_VALUE_IMPORTANT  =   " CSS_DECLARATION_VALUE_IMPORTANT " // $NON-NLS-1$
55       public   static   final  String CSS_DECLARATION_VALUE_OPERATOR  =   " DECLARATION_VALUE_OPERATOR " // $NON-NLS-1$
56       public   static   final  String CSS_DECLARATION_VALUE_S  =   " DECLARATION_VALUE_S " // $NON-NLS-1$
57 
58       public   static   final  String CSS_UNKNOWN  =   " UNKNOWN " // $NON-NLS-1$
59 
60       //  For null object : CSSTokenizer never set this value
61       public   static   final  String CSS_UNDEFINED  =   " UNDEFINED " // $NON-NLS-1$
62       /**
63        * currently provided this field but may be removed in future.
64        */
65       public   static   final  String CSS_FOREIGN_ELEMENT  =   " FOREIGN_ELEMENT " // $NON-NLS-1$
66  }
            
            JSPedCSSRegionContexts(org.eclipse.jst.jsp.css.core.internal.parserz.JSPedCSSRegionContexts)常量接口中枚举了所有的有关JSP和CSS嵌套情况下的text region类型常量: 
 1  public   interface  JSPedCSSRegionContexts  extends  CSSRegionContexts {    
 2       public   static   final  String CSS_JSP_EXP  =   " CSS_JSP_EXP " // $NON-NLS-1$
 3       public   static   final  String CSS_JSP_EL  =  CSSRegionContexts.CSS_FOREIGN_ELEMENT;  // $NON-NLS-1$
 4       public   static   final  String CSS_JSP_SCRIPTLET  =   " CSS_JSP_SCRIPTLET " // $NON-NLS-1$
 5       public   static   final  String CSS_JSP_DIRECTIVE  =   " CSS_JSP_DIRECTIVE " // $NON-NLS-1$
 6       public   static   final  String CSS_JSP_DECL  =   " CSS_JSP_DECL " // $NON-NLS-1$
 7       public   static   final  String CSS_JSP_END  =   " CSS_JSP_END " // $NON-NLS-1$
 8       public   static   final  String CSS_EL_END  =   " CSS_EL_END " // $NON-NLS-1$
 9       public   static   final  String CSS_JSP_COMMENT_END  =   " CSS_JSP_COMMENT_END " // $NON-NLS-1$
10       public   static   final  String CSS_JSP_COMMENT  =   " CSS_JSP_COMMENT " // $NON-NLS-1$
11  }


            说明:建议使用ITextRegion.getType()和DOMRegionContext(DOMJSPRegionContexts、CSSRegionContexts、JSPedCSSRegionContexts)做text region的类型分析。为什么呢?像TagNameRegion...其实是ITextRegion的内部实现类型,不应该视为对外暴露的类型,基于接口编程的原则建议我们使用ITextRegion^_^;WTP在为每种ITextRegion的内部实现设定了一个型别码,这使得我们用ITextRegion超类型来判断其具体的实际实现类型成为可能^_^    (PS:有兴趣的哥们,可以看一下有关子类型和类型型别码的资料,这是一个我们经常要面对的东西,隐藏了设计技巧^_^)

        【IStructuredDocumentRegion相关】
            
             我们看到,IStructuredDocumentRegion继承自ITextRegionCollection,是一种特殊的树枝节点。上图中的XMLStructuredDocumentRegion是我们最常用的IStructuredDocumentRegion实现。
            
            首先看一下ITextRegionCollection提供的核心操作:
            
            看的出来,提供的核心操作基本上是围绕子text region展开的,具体请翻阅对应的wtp源码!!!常用的如下:
        1、getRegions():返回组成当前text region collection的text region列表
        2、getText(ITextRegion)、getFullText(ITextRegion):获取特定子text region的文本,前者不包含空格
        3、getRegionAtCharacterOffset(int):返回指定位置(相对于collection的位置)的子text region
            
            接着看一下,IStructuredDocumentRegion接口提供的操作:
            
            看的出来,IStructuredDocumentRegion提供了如下几类操作:
            1、遍历相关:getParentDocument()、getPrevious()、getNext(),非常常用!!!  对应set...
            2、修改内容操作:addRegion...

            【IStructuredDocument核心操作】
          IStructuredDocument提供的核心操作基本为三类类:
               1、定位IStructuredDocumentRegion:前面说过IStructuredDocument是由一系列IStructuredDocumentRegion组成,由树状结构的顶点获取一级节点这是很应该的^_^   常用操作如下:
                    IStructuredDocumentRegion[] getStructuredDocumentRegions();
                    IStructuredDocumentRegion getFirstStructuredDocumentRegion();
                    IStructuredDocumentRegion  getLastStructuredDocumentRegion();
                    IStructuredDocumentRegion getRegionAtCharacterOffset(int offset);
                    IStructuredDocumentRegion[] getStructuredDocumentRegions(int offset, int length);

               2、修改document文本内容:类似于JFace中IDocument.replace(int offset, int length, String text)。

               3、Document Listener相关:这个特性这边不做详细阐述,后面到我们进一步定制WTP JSP编辑器的时候再讨论如何使用它。很显然,和JFace中的IDocumentListener机制原理类似,是一个典型的Obsever实现,将Document自身核心逻辑和Document变化处理逻辑进行松耦合处理。

            【后记】
            在这篇随笔中,我们详细地讨论了WTP中的JFace IDocument实现 --》  IStructuredDocument!!!现在我们再看文章开头的两幅图,应该比较清楚了吧^_^    再回顾一下吧:
            1、IStructuredDocument结构分析,Composite实现,并着重分析里里面的节点、叶子节点、树枝节点
            2、如果创建和获取IStructuredDocument实例,并强调了其重量级对象的特性
            3、相关接口的核心操作说明,例如遍历,通过IStructuredDocument可以拿到你想要的IStructuredDocumentRegion,通过IStructuredDocumentRegion可以拿到你想要的ITextRegion,还说明了如何分析ITextRegion的类型。

            题目:给定一个工作区中的jsp文件,让你分析该jsp文件,然后打印出来里面涉及到的所有tag name
            办法:
            1、通过IFile构造对应的IStructuredDocument实例
            2、遍历IStructuredDocument, 获取IStructuredDocumentRegion列表
            3、分析IStructuredDocumentRegion,获取其含有的ITextRegion列表
            4、找出类型为DOMRegionContext.XML_TAG_NAME的text region,然后通过ITextRegionCollection.getText(ITextRegion containedRegion)获取标签名称

        ^_^,了解了WTP IStructuredDocument实现,是不是觉得看WTP中的页面资源文件更透彻些了呢?如果再了解一下后门的IStructuredModel,你会觉得更透彻^_^

        PS:在下一篇中,我们将开发一个Structured Document分析视图。有关WTP Editor定制的具体细节还要再放置到更后门的篇幅去讲,个人觉得如果对WTP IStructuredDocument和IStructuredModel这两个核心数据模型不够熟悉,你想定制WTP的已有功能....举步维艰!


本博客中的所有文章、随笔除了标题中含有引用或者转载字样的,其他均为原创。转载请注明出处,谢谢!

你可能感兴趣的:(【Eclipse插件开发】基于WTP开发自定义的JSP编辑器(三) :WTP Structured Document)