Live a simple life

沉默(zhu_xing@live.cn)
随笔 - 48, 文章 - 0, 评论 - 132, 引用 - 0
数据加载中……

【Eclipse插件开发】基于WTP开发自定义的JSP编辑器(十一):TLD Content Model分析视图

            在上一节中我们分析了WTP TLD Content Model的关键特性,并简要介绍了WTP Content Model的整体结构。在本节中,我们将开发一个WTP TLD Content Model分析视图,帮助我们更直观的了解所谓的WTP TLD内容模型。本视图的开发和前面开发过的WTP StructuredDocument分析视图和WTP Structured Model分析视图非常类似,有些技术实现细节的分析可以参见前面相应的章节。

            【需求】
            1、提供一个TLD Content Model分析视图,以树状方式将当前编辑器中JSP文档对应的TLD内容模型显示出来,每个TLDDocument为一个独立节点,TLDDocument下面持有TLD Element和TLD Attribute两级子节点
            2、交互(编辑器 ---> TLD Content Model分析视图):
                  激活 JSP编辑器,即时更新TLD Content Model分析视图
                  当编辑器中的内容改变时,即时更新TLD Content Model分析视图
                  当前激活编辑器关闭时,清空TLD Content Model分析视图内容
            3、交互(TLD Content Model分析视图 ---> 编辑器)
                  双击视图中TLD Document节点时,打开对应的TLD定义文件

            4、进一步需求,当编辑器中的光标位置变化时,即时更新TLD Content Model分析视图。(说明:在上一节中我们分析过,一个TLD Document有位置相关的特性,获取光标位置相关的TLD Document列表,也就是光标位置之前可以被识别的TLD导入^_^)

            【效果预览】
            1、位置无关的TLD Content Model分析效果预览 
             如图所示,不管光标位于编辑器中的任何位置,都会列举出所有的TLD Content Document。

            2、位置相关的TLD Content Model分析效果预览

                如图所示,光标位于test1 tld和test2 tld之间,这时候分析视图中只列举除了当前位置可以识别的TLD信息。在此位置,test2 tld还不能够获取到,所以使用test2中的标签会得到WTP的一个错误提示:不能识别的标签。(我想,理解了TLD Content Document位置相关的特性,也就理解了WTP中对特定标签在特定位置是否可以被识别是怎么实现的了^_^)

            【实现摘要(文章后门会附上对应的源码)】

                说明:有关视图实现类创建、如何利用Eclipse工作台的selection service和part service等代码实现,请参照前面章节中的两个分析视图的实现:
                基于WTP开发自定义的JSP编辑器(四):Strucutured Document分析视图
                基于WTP开发自定义的JSP编辑器(六):IStructuredModel(DOM Document)分析视图

                
                1、位置无关场景下TLD Content Document列表的获取代码
/**
     * 获取指定文档对应的TLD Content Document列表
     * 
     * 
@param structuredDocument   jsp structured document
     * 
@return
     
*/
    
private TLDDocument[] getTLDDocuments(IStructuredDocument structuredDocument) {
        TLDCMDocumentManager tldDocumentManager 
= TaglibController.getTLDCMDocumentManager(structuredDocument);
        List taglibTrackers = tldDocumentManager.getTaglibTrackers();
        
        TLDDocument[] tldDocuments 
= new TLDDocument[taglibTrackers.size()];
        
for (int i = 0; i < tldDocuments.length; i++) {
            TaglibTracker taglibTracker 
= (TaglibTracker)taglibTrackers.get(i);
            tldDocuments[i] 
= (TLDDocument)taglibTracker.getDocument();
        }
        
return tldDocuments;
    }
                上一节中,我们阐述过taglib tracker的获取方式,TLDCMDocumentManager.getTaglibTrackers()就是位置无关的获取方式,具体细节请参见上一节中的内容。

                2、位置相关场景下TLD Content Document列表的获取代码
/**
     * 获取指定文档中特定位置对应的TLD Content Document列表 
     * 
     * 
@param structuredDocument  jsp structured document
     * 
@param offset    文档中的位置
     * 
@return
     
*/
    
private TLDDocument[] getTLDDocuments(IStructuredDocument structuredDocument, int offset) {
        TLDCMDocumentManager tldDocumentManager 
= TaglibController.getTLDCMDocumentManager(structuredDocument);
        List taglibTrackers = tldDocumentManager.getCMDocumentTrackers(offset);

        
        TLDDocument[] tldDocuments 
= new TLDDocument[taglibTrackers.size()];
        
for (int i = 0; i < tldDocuments.length; i++) {
            TaglibTracker taglibTracker 
= (TaglibTracker)taglibTrackers.get(i);
            tldDocuments[i] 
= (TLDDocument)taglibTracker.getDocument();
        }
        
return tldDocuments;
    }
                taglib tracker列表的获取方式:TLDCMDocumentManager.getCMDocumentTrackers(int offset),位置相关

                3、对用户选择事件的处理: 
/* (non-Javadoc)
     * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
     
*/
    
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
        
if (!(part instanceof TextEditor)) 
            
return ;
        
        IEditorInput editorInput 
= ((TextEditor)part).getEditorInput();
        IDocument document 
= ((TextEditor)part).getDocumentProvider().getDocument(editorInput);
        
if (!(document instanceof IStructuredDocument)) {
            
this.viewer.setInput(null);
            
return ;
        }
        
        
//记录source part和source document
        this.sourcePart = part;
        
this.sourceDocument = document;
        
        
//注册对应的document change listener
        document.addDocumentListener(this.documentListener);
        
//        //获取TLD Content Document列表(位置无关方式),并更新tree viewer输入
//        TLDDocument[] tldDocuments = this.getTLDDocuments((IStructuredDocument)document);
//        this.viewer.setInput(tldDocuments);
//        this.viewer.expandToLevel(2);
        
        
//获取TLD Content Document列表(位置相关方式),并更新tree viewer输入
        int offset = ((ITextSelection)selection).getOffset();
        TLDDocument[] tldDocuments 
= this.getTLDDocuments((IStructuredDocument)document, offset);
        
this.viewer.setInput(tldDocuments);
        
this.viewer.expandToLevel(2);
    }
                在处理用户选择事件时候,根据只需要调用不同的TLD Content Document获取方式(1、2点中阐述的)就可以了^_^。
            
                4、视图中TLD Document节点的双击事件的处理
//添加双击支持
        this.viewer.addDoubleClickListener(new IDoubleClickListener() {
            
public void doubleClick(DoubleClickEvent event) {
                ITreeSelection treeSelection 
= (ITreeSelection)event.getSelection();
                Object selectedElement 
= treeSelection.getFirstElement();
                
if (!(selectedElement instanceof TLDDocument))
                    
return ;
                
                
//获取TLD Document对应的TLD文件
                String baseLocation = ((TLDDocument)selectedElement).getBaseLocation();
                IFile file 
= ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(baseLocation));
                
if (!file.exists()) 
                    
return ;
                
                
//打开TLD定义文件
                try {
                    IWorkbenchPage page 
= PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
                    IDE.openEditor(page, file);
                } 
catch (PartInitException e) {
                    IStatus status 
= new Status(IStatus.ERROR, "wtp.tldcontentdocument"1111"打开TLD定义文件失败", e);
                    Activator.getDefault().getLog().log(status);
                }
            }
        });
                主要步骤如下:
                 1、利用TLDDocument接口中的getBaseLocation获取该TLDDocument对应的页面资源的绝对路径信息
                 2、定位工作区中对应的TLD资源文件,打开

                5、视图tree viewer对应的content provider
                
/* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
     
*/
    
public Object[] getChildren(Object parentElement) {
        
if (parentElement == null)
            
return new Object[0];
        
        
if (parentElement instanceof TLDDocument[])
            
return (TLDDocument[])parentElement;
        
        
//如果是tld content document, 则获取对应的tld element列表
        if (parentElement instanceof TLDDocument) {
            CMNamedNodeMap tagMap 
= ((TLDDocument)parentElement).getElements();
            
            Object[] children 
= new Object[tagMap.getLength()];
            
for (int i = 0; i < children.length; i++) {
                children[i] 
= tagMap.item(i);
            }
            
return children;
        }
        
        
//如果是tld element(tag),则获取对应的attrbute列表
        if (parentElement instanceof TLDElementDeclaration) {
            CMNamedNodeMap attributeMap 
= ((TLDElementDeclaration)parentElement).getAttributes();
            
            Object[] children 
= new Object[attributeMap.getLength()];
            
for (int i = 0; i < children.length; i++) {
                children[i] 
= attributeMap.item(i);
            }
            
return children;
        }
        
        
return new Object[0];
    }
                如果输入是tld content document(TLDDocument),则获取对应的tld element列表,也就是tld中定义的tag列表;如果输入是tld element(TLDElementDeclaration),则获取对应的tld attribute列表,也就是特定tag下面定义的标签属性列表。
                
                其他具体代码实现细节,参见附件中的源码。^_^


            【后记】
               本插件工程需要依赖的插件列表为:
                 org.eclipse.ui,
                 org.eclipse.core.runtime,
                 org.eclipse.jface.text,
                 org.eclipse.ui.editors,
                 org.eclipse.ui.workbench.texteditor,
                 org.eclipse.wst.sse.core,
                 org.eclipse.jst.jsp.core,
                 org.eclipse.wst.xml.core,
                 org.eclipse.core.resources,
                 org.eclipse.ui.ide
               
                源码为实际工程以Export ---> Archive File方式导出的,下载链接TLD Content Model分析视图源码


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

posted on 2008-10-16 18:05 zhuxing 阅读(1183) 评论(1)  编辑  收藏 所属分类: Eclipse Plug-in & OSGIWTP(Web Tools Platform)

评论

# re: 【Eclipse插件开发】基于WTP开发自定义的JSP编辑器(十一):TLD Content Model分析视图  回复  更多评论   

朱兴,能不能再介绍一下wtp 是如何 基于 xml 的 dtd 来对 xml 进行校验和语法提示的?是不是类似于tld的这种方式?我现在要开发一个特定xml的编辑器,需要根据一定的业务规则来进行校验和提示,请问该怎么做比较好?
2008-10-16 19:36 | 飞扬的麦子

只有注册用户登录后才能发表评论。


网站导航: