﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-精彩的人生-随笔分类-Eclipse</title><link>http://www.blogjava.net/hopeshared/category/5324.html</link><description>好好工作，好好生活</description><language>zh-cn</language><lastBuildDate>Tue, 25 Mar 2008 07:01:17 GMT</lastBuildDate><pubDate>Tue, 25 Mar 2008 07:01:17 GMT</pubDate><ttl>60</ttl><item><title>如何让Eclipse View中的TreeItem显示出error时的小红叉和warn时的感叹号?</title><link>http://www.blogjava.net/hopeshared/archive/2008/03/25/188493.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Tue, 25 Mar 2008 07:00:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2008/03/25/188493.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/188493.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2008/03/25/188493.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/188493.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/188493.html</trackback:ping><description><![CDATA[在做的项目里,需要一个这样的显示效果.<br />
以前从来没有做过,也不知道该用什么关键字来搜索.<br />
于是,只好用最原始的办法,看Eclipse的源代码.最后一些跟decorator相关的类引起了我的注意,还发现有一个相关的LabelProvider.于是我用这个词作为关键字搜索到了下面这篇文章,觉得十分有用,所以暂存到这里.<br />
<br />
<br />
原文标题: org.eclipse.ui.decorators得用法<br />
<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">extension&nbsp;</span><span style="color: #ff0000">point</span><span style="color: #0000ff">="org.eclipse.ui.decorators"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">decorator&nbsp;</span><span style="color: #ff0000">icon</span><span style="color: #0000ff">="icons/warning_small.gif"</span><span style="color: #ff0000">&nbsp;id</span><span style="color: #0000ff">="cnooc.rcp.decorator.node.warning"</span><span style="color: #ff0000">&nbsp;label</span><span style="color: #0000ff">="Data&nbsp;Warning&nbsp;Decorator"</span><span style="color: #ff0000">&nbsp;lightweight</span><span style="color: #0000ff">="true"</span><span style="color: #ff0000">&nbsp;location</span><span style="color: #0000ff">="BOTTOM_LEFT"</span><span style="color: #ff0000">&nbsp;state</span><span style="color: #0000ff">="true"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">enablement</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">and</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">objectClass&nbsp;</span><span style="color: #ff0000">"com.eplat.cnooc.rcp.node.INode"</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">objectState&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="hasWarning"</span><span style="color: #ff0000">&nbsp;value</span><span style="color: #0000ff">="true"</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">and</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">enablement</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">decorator</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">decorator&nbsp;</span><span style="color: #ff0000">icon</span><span style="color: #0000ff">="icons/error_small.gif"</span><span style="color: #ff0000">&nbsp;id</span><span style="color: #0000ff">="cnooc.rcp.decorator.node.error"</span><span style="color: #ff0000">&nbsp;label</span><span style="color: #0000ff">="Data&nbsp;Error&nbsp;Decorator"</span><span style="color: #ff0000">&nbsp;lightweight</span><span style="color: #0000ff">="true"</span><span style="color: #ff0000">&nbsp;location</span><span style="color: #0000ff">="BOTTOM_LEFT"</span><span style="color: #ff0000">&nbsp;state</span><span style="color: #0000ff">="true"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">enablement</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">and</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">objectClass&nbsp;</span><span style="color: #ff0000">"com.eplat.cnooc.rcp.node.INode"</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">objectState&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="hasError"</span><span style="color: #ff0000">&nbsp;value</span><span style="color: #0000ff">="true"</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">and</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">enablement</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">decorator</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">extension</span><span style="color: #0000ff">&gt;</span></div>
<br />
INode是TreeViewer里面节点得对象.<br />
Viewer设置LabelProvider时需要如下:<br />
<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">viewer.setLabelProvider(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;DecoratingLabelProvider(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ViewLabelProvider(),<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Activator.getDefault().getWorkbench().getDecoratorManager().getLabelDecorator()));</span></div>
<br />
写了这个以后还没完, 需要让INode实现IActionFilter接口. eclipse得API中说要么实现IActionFilter接口, 要么实现IAdapter接口, 如果实现后者得话, 系统会调用getAdapter()方法. 不过我还是选择前者.<br />
<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Codehighlighter1_4_151_Open_Image" onclick="this.style.display='none'; Codehighlighter1_4_151_Open_Text.style.display='none'; Codehighlighter1_4_151_Closed_Image.style.display='inline'; Codehighlighter1_4_151_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_4_151_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_4_151_Closed_Text.style.display='none'; Codehighlighter1_4_151_Open_Image.style.display='inline'; Codehighlighter1_4_151_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_4_151_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">/**&nbsp;*/</span><span id="Codehighlighter1_4_151_Open_Text"><span style="color: #008000">/**</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;(non-Javadoc)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080">@see</span><span style="color: #008000">&nbsp;org.eclipse.ui.IActionFilter#testAttribute(java.lang.Object,&nbsp;java.lang.String,java.lang.String)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">*/</span></span><span style="color: #000000"><br />
<img id="Codehighlighter1_227_471_Open_Image" onclick="this.style.display='none'; Codehighlighter1_227_471_Open_Text.style.display='none'; Codehighlighter1_227_471_Closed_Image.style.display='inline'; Codehighlighter1_227_471_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_227_471_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_227_471_Closed_Text.style.display='none'; Codehighlighter1_227_471_Open_Image.style.display='inline'; Codehighlighter1_227_471_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">boolean</span><span style="color: #000000">&nbsp;testAttribute(Object&nbsp;target,&nbsp;String&nbsp;name,&nbsp;String&nbsp;value)</span><span id="Codehighlighter1_227_471_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_227_471_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_267_353_Open_Image" onclick="this.style.display='none'; Codehighlighter1_267_353_Open_Text.style.display='none'; Codehighlighter1_267_353_Closed_Image.style.display='inline'; Codehighlighter1_267_353_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_267_353_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_267_353_Closed_Text.style.display='none'; Codehighlighter1_267_353_Open_Image.style.display='inline'; Codehighlighter1_267_353_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(name.equals(</span><span style="color: #000000">"</span><span style="color: #000000">hasWarning</span><span style="color: #000000">"</span><span style="color: #000000">))</span><span id="Codehighlighter1_267_353_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_267_353_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">!</span><span style="color: #000000">getProblems().hasError()&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;getProblems().hasWarning();<br />
<img id="Codehighlighter1_388_443_Open_Image" onclick="this.style.display='none'; Codehighlighter1_388_443_Open_Text.style.display='none'; Codehighlighter1_388_443_Closed_Image.style.display='inline'; Codehighlighter1_388_443_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_388_443_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_388_443_Closed_Text.style.display='none'; Codehighlighter1_388_443_Open_Image.style.display='inline'; Codehighlighter1_388_443_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(name.equals(</span><span style="color: #000000">"</span><span style="color: #000000">hasError</span><span style="color: #000000">"</span><span style="color: #000000">))</span><span id="Codehighlighter1_388_443_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_388_443_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;getProblems().hasError();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
<br />
意思应该比较明显得, 如果有warning并且没有error得时候warning得decorator生效. 如果有error则error得decorator生效. name参数对应得就是objectState得name参数. value参数对应得objectState得value参数. target参数就是viewer中得节点对象, 不过由于INode实现了IActionFilter接口, 因此这里得target就是this了.<br />
一般来说需要判断得就是根据name获取得值是否等于value, 等于返回true, 否则返回false. 不过这里我不需要判断这个了, 直接根据当前状态返回就好了.<br />
按照eclipse得原理, 理论上应该INode变化以后viewer就会跟着变化, 但是我实验下来有时候好有时候不好.<br />
因此在Editor得verify方法里增加了下面得逻辑:<br />
<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Codehighlighter1_4_49_Open_Image" onclick="this.style.display='none'; Codehighlighter1_4_49_Open_Text.style.display='none'; Codehighlighter1_4_49_Closed_Image.style.display='inline'; Codehighlighter1_4_49_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_4_49_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_4_49_Closed_Text.style.display='none'; Codehighlighter1_4_49_Open_Image.style.display='inline'; Codehighlighter1_4_49_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_4_49_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">/**&nbsp;*/</span><span id="Codehighlighter1_4_49_Open_Text"><span style="color: #008000">/**</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;校验数据<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080">@return</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">*/</span></span><span style="color: #000000"><br />
<img id="Codehighlighter1_79_318_Open_Image" onclick="this.style.display='none'; Codehighlighter1_79_318_Open_Text.style.display='none'; Codehighlighter1_79_318_Closed_Image.style.display='inline'; Codehighlighter1_79_318_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_79_318_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_79_318_Closed_Text.style.display='none'; Codehighlighter1_79_318_Open_Image.style.display='inline'; Codehighlighter1_79_318_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">boolean</span><span style="color: #000000">&nbsp;verify()</span><span id="Codehighlighter1_79_318_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_79_318_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">校验数据<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">不管是否有error或者warning都需要通知向导树刷新一下节点.</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExplorerView&nbsp;view&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(ExplorerView)&nbsp;getSite().getPage().findView(ExplorerView.</span><span style="color: #0000ff">class</span><span style="color: #000000">.getName());<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;view.refresh((INode)&nbsp;getEditorInput());<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
<br />
现在好了, 只要执行verify方法, viewer就会刷新对应得节点, 以达到显示左下方小图标得目的.<br />
<br />
<br />
原文地址: http://blog.csdn.net/bradwoo8621/archive/2007/05/11/1604738.aspx<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/hopeshared/aggbug/188493.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2008-03-25 15:00 <a href="http://www.blogjava.net/hopeshared/archive/2008/03/25/188493.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>插件制作过程记录（使用TreeViewer贡献视图）</title><link>http://www.blogjava.net/hopeshared/archive/2006/07/25/59983.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Tue, 25 Jul 2006 05:54:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/07/25/59983.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/59983.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/07/25/59983.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/59983.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/59983.html</trackback:ping><description><![CDATA[
		<span class="tpc_content">
				<font size="2">使用TreeViewer贡献视图(根据《Eclipse入门到精通》中的例子进行的改编)<br /><br /><br />作者：李红霞 2005-8-13<br /><br />本文章允许转载,但请要求注明文章作者及出处<br /><br /><br />一 创建插件项目<br />创建一个插件项目example.my.treeview，这个例子将向eclipse贡献一个视图，这个视图采用树（Treeviewer）来实现。<br /><br />下图是本例的文件清单<br />&lt;抱歉,图片传不上来&gt;<br />+ example.my.treeview<br />+ src<br />  + example.my.treeview<br />    - TreeviewPlugin.java<br />  + exampe.my.treeview.data<br />    - CityEntity.java<br />    - CountryEntity.java<br />    - DataFactory.java<br />    - PeopleEnrity.java<br />  + example.my.treeview.internal<br />    - ITreeEntry.java<br />    - TreeViewerContentProvider.java<br />    - TreeViewerLabelProvider.java<br />    - TreeViewPart.java<br />  + JRE System Library<br />  + Plug-in dependencies<br />  + META-INF<br />    - MENIFEST.MF<br />  - build.properties<br />  - plugin.xml<br /><br />二 准备数据模型<br />首先我们准备数据模型，这些数据模型都保存在example.my.treeview.data这个包中<br /><br />我们定义一个接口ItreeEntry，这个接口将定义树中每个节点共同特征（名称和子节点），代码如下<br /><br />package example.my.treeview.internal;<br />import java.util.List;<br />public interface ITreeEntry {<br />     public String getName();<br />     public void setName(String name);<br />     //设置得到子节点的集合<br />     public void setChildren(List children);<br />     public List getChildren();<br />}<br /><br />这里涉及的实体一共有3个，以下是他们的代码<br /><br />package example.my.treeview.data;<br />import java.util.List;<br />import example.my.treeview.internal.ITreeEntry;<br />public class CityEntity implements ITreeEntry{<br />     private Long id;//唯一识别码<br />     private String name;//城市名<br />     private List peoples;//城市中的人<br />     public CityEntity(){}<br />     public CityEntity(String name){this.name=name;}<br />     public Long getId() {return id;}<br />     public void setId(Long id) {this.id = id;}<br />     public String getName() {return name;}<br />     public void setName(String name) {this.name = name;}<br />     public List getChildren() {return peoples;}<br />     public void setChildren(List peoples) {<br />           this.peoples = peoples;<br />     }<br />}<br /><br /><br /><br /><br />package example.my.treeview.data;<br />import java.util.List;<br />import example.my.treeview.internal.ITreeEntry;<br />public class CountryEntity implements ITreeEntry{<br />  //唯一识别码，在数据库里常为自动递增的ID列<br />     private Long id;      <br />private String name;//国家名<br />//此国家所包含的城市的集合，集合元素为City对象<br />     private List cities;      <br />     //两个构造函数<br />     public CountryEntity(){}<br />     public CountryEntity(String name){this.name = name;}<br />  //相应的get和set方法<br />     public List getChildren() {return cities;}<br />     public void setChildren(List cities) {this.cities = cities;}<br />     public Long getId() {return id;}<br />     public void setId(Long id) {this.id = id;}<br />     public String getName() {return name;}<br />     public void setName(String name) {this.name = name;}<br />}<br /><br /><br /><br />package example.my.treeview.data;<br />import java.util.List;<br />import example.my.treeview.internal.ITreeEntry;<br />public class PeopleEntity implements ITreeEntry{<br />     private String name;<br />     public PeopleEntity(){}<br />     public PeopleEntity(String name){this.name=name;}<br />     public List getChildren(){return null;}<br />     public void setChildren(List children){}<br />     public String getName() {return name;}<br />     public void setName(String name) {this.name = name;}<br />}<br /><br /><br />三 创建树中的数据结构<br /><br />代码如下<br /><br />package example.my.treeview.data;<br />import java.util.ArrayList;<br />public class DataFactory {<br />     public static Object createTreeData(){<br />           //生成人的数据对象<br />           PeopleEntity p1 = new PeopleEntity("李红霞");<br />           PeopleEntity p2 = new PeopleEntity("金利军");<br />           PeopleEntity p3 = new PeopleEntity("何涛");<br />           //生成城市的数据对象<br />           CityEntity city1=new CityEntity("湖北");<br />           CityEntity city2=new CityEntity("北京");<br />           CityEntity city3=new CityEntity("湖南");<br />           //生成国家的数据对象<br />           CountryEntity c1 = new CountryEntity("美国");<br />           CountryEntity c2 = new CountryEntity("中国");<br />           //将数据对象连接起来<br />           //人和城市的关系<br />           {<br />                 ArrayList list = new ArrayList();<br />                 list.add(p1);<br />                 city1.setChildren(list);<br />           }<br />           {<br />                 ArrayList list = new ArrayList();<br />                 list.add(p2);<br />                 city2.setChildren(list);<br />           }<br />           {<br />                 ArrayList list = new ArrayList();<br />                 list.add(p3);<br />                 city3.setChildren(list);<br />           }<br />           //城市和国家的关系<br />           {<br />                 ArrayList list = new ArrayList();<br />                 list.add(city1);<br />                 c1.setChildren(list);<br />           }<br />           {<br />                 ArrayList list = new ArrayList();<br />                 list.add(city2);<br />                 list.add(city3);<br />                 c2.setChildren(list);<br />           }<br />           //将国家置于一个对象之下，<br />//这个对象可以是List也可以是数组<br />           {<br />                 ArrayList list = new ArrayList();<br />                 list.add(c1);<br />                 list.add(c2);<br />                 return list;<br />           }<br />     }<br />}<br /><br />四 标签器和内容器<br />TreeViewer和TableViewer一样，是用内容器和标签器来控制记录对象的显示，并且使用内容器和标签器的语句也是一样的。<br /><br />下面是标签器的代码<br /><br />package example.my.treeview.internal;<br />import org.eclipse.jface.viewers.ILabelProvider;<br />import org.eclipse.jface.viewers.ILabelProviderListener;<br />import org.eclipse.swt.graphics.Image;<br />/**<br />* @author hopeshared<br />* 标签提供器，控制纪录在树中显示的文字和图像等<br />*/<br />public class TreeViewerLabelProvider <br />implements ILabelProvider{<br />     //纪录显示 的文字，不能返回null<br />     public String getText(Object element){<br />           ITreeEntry entry = (ITreeEntry)element;<br />           return entry.getName();<br />     }<br />     //纪录显示的图像<br />     public Image getImage(Object element){<br />           return null;<br />     }<br />     //以下方法暂不用，空实现<br />     public void addListener(ILabelProviderListener listener){}<br />     public void dispose(){}<br />     public boolean isLabelProperty(Object e, String p){return false;}<br />     public void removeListener(ILabelProviderListener listen){}<br />}<br /><br /><br />下面是内容器的代码<br /><br />package example.my.treeview.internal;<br />import java.util.List;<br />import org.eclipse.jface.viewers.ITreeContentProvider;<br />import org.eclipse.jface.viewers.Viewer;<br />/**<br />* @author hopeshared<br />* 内容器，由它决定哪些对象应该输出在TreeViewer里显示<br />*/<br />public class TreeViewerContentProvider <br />implements ITreeContentProvider{<br />     //由这种方法决定树的哪一级显示哪些对象<br />     public Object[] getElements(Object inputElement)<br />     {<br />           if(inputElement instanceof List){<br />                 List list = (List)inputElement;<br />                 return list.toArray();<br />           }else{<br />                 return new Object[0];//生成一个空的数组<br />           }<br />     }<br />     //判断某节点是否有子节点，如果有子节点，<br />//这时节点前都有一个“+”号图标<br />     public boolean hasChildren(Object element){<br />           ITreeEntry entry = (ITreeEntry)element;<br />           List list = entry.getChildren();<br />           if(list==null||list.isEmpty()){return false;<br />           }else{return true;}<br />     }<br />     //由这个方法来决定父节点应该显示哪些子节点<br />     public Object[] getChildren(Object parentElement){<br />           ITreeEntry entry = (ITreeEntry)parentElement;<br />           List list = entry.getChildren();<br />           if(list==null || list.isEmpty()){return new Object[0];<br />           }else{return list.toArray();}            <br />     }<br />     //以下方法空实现<br />     public Object getParent(Object element){return null;}<br />     public void dispose(){}<br />     public void inputChanged(Viewer v, Object oldInput, Object newInput){}<br />}<br /><br />五 修改清单文件<br />下面给出的是plugin.xml文件代码<br /><br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;?eclipse version="3.0"?&gt;<br />&lt;plugin&gt;<br />  &lt;extension point="org.eclipse.ui.views"&gt;<br />    &lt;view<br />    class="example.my.treeview.internal.TreeViewPart"<br />id="example.my.treeview.treeview"<br />name="my first tree view plugin"/&gt;<br />  &lt;/extension&gt;<br />&lt;/plugin&gt;<br /><br />六 插件的实现<br />在清单文件中已经指出了这个视图的实现类是example.my.treeview.internal.TreeViewPart，下面给出这个文件的代码<br /><br />package example.my.treeview.internal;<br />import org.eclipse.jface.viewers.TreeViewer;<br />import org.eclipse.swt.SWT;<br />import org.eclipse.swt.layout.FillLayout;<br />import org.eclipse.swt.widgets.Composite;<br />import org.eclipse.ui.part.ViewPart;<br />import example.my.treeview.data.DataFactory;<br />public class TreeViewPart extends ViewPart{<br />     public void createPartControl(Composite parent){<br />           Composite topComp = new Composite(parent, SWT.NONE);<br />           topComp.setLayout(new FillLayout());<br />           TreeViewer tv = new TreeViewer(topComp, SWT.BORDER);<br />           tv.setContentProvider(new TreeViewerContentProvider());<br />           tv.setLabelProvider(new TreeViewerLabelProvider());<br />           Object inputObj = DataFactory.createTreeData();<br />           tv.setInput(inputObj);<br />     }<br />     public void setFocus(){}<br />}<br /><br />七 运行结果<br />&lt;抱歉,图片上传失败&gt;<br /><br /><br />八 给节点增加动作<br />增加一个ActionGroup类<br /><br />package example.my.treeview.internal;<br />import org.eclipse.jface.action.Action;<br />import org.eclipse.jface.action.IMenuManager;<br />import org.eclipse.jface.action.MenuManager;<br />import org.eclipse.jface.dialogs.MessageDialog;<br />import org.eclipse.jface.viewers.IStructuredSelection;<br />import org.eclipse.jface.viewers.TreeViewer;<br />import org.eclipse.swt.widgets.Menu;<br />import org.eclipse.swt.widgets.Tree;<br />import org.eclipse.ui.actions.ActionGroup;<br />/**<br />* @author hopeshared<br />* 生成菜单Menu，并将两个Action传入<br />*/<br />public class MyActionGroup extends ActionGroup{<br />     private TreeViewer tv;<br />     public MyActionGroup(TreeViewer treeViewer){<br />           this.tv = treeViewer;<br />     }<br />     //生成菜单Menu，并将两个Action传入<br />     public void fillContextMenu(IMenuManager mgr){<br />           //加入两个Action对象到菜单管理器<br />           MenuManager menuManager = (MenuManager)mgr;<br />           menuManager.add(new OpenAction());<br />           menuManager.add(new RefreshAction());<br />           //生成Menu并挂在树Tree上<br />           Tree tree = tv.getTree();<br />           Menu menu = menuManager.createContextMenu(tree);<br />           tree.setMenu(menu);<br />     }<br />     //打开Action类<br />     private class OpenAction extends Action{<br />           public OpenAction(){<br />                 setText("打开");<br />           }<br />           //继承自Action的方法，动作代码写在此方法中<br />           public void run(){<br />                 IStructuredSelection selection = (IStructuredSelection)tv.getSelection();<br />                 ITreeEntry obj = (ITreeEntry)(selection.getFirstElement());<br />                 if(obj != null){<br />                       MessageDialog.openInformation(null, null, obj.getName());<br />                 }<br />           }<br />     }<br />     //刷新的Action类<br />     private class RefreshAction extends Action{<br />           public RefreshAction(){<br />                 setText("刷新");<br />           }<br />           //继承自Action的方法，动作代码写在此方法中<br />           public void run(){<br />                 tv.refresh();<br />           }<br />     }<br />}<br /><br />接着，修改TreeViewPart.java，代码如下<br /><br />……<br />Object inputObj = DataFactory.createTreeData();<br />           //-------------加入动作开始<br />           MyActionGroup actionGroup = new MyActionGroup(tv);<br />           actionGroup.fillContextMenu(new MenuManager());<br />           //-------------加入动作结束<br />           tv.setInput(inputObj);<br />……<br /><br /><br />结果如下图所示<br />&lt;抱歉,图片上传不成功&gt;<br /><br /><br />九 自定义扩展点<br />我们想将这个视图的显示内容与视图框架分开，这样，我们需要修改视图显示内容的时候只要重新贡献一次显示内容就可以了。<br />9.1 添加shema文件<br />这个sheme文件是采用可视化编辑器进行编辑，然后pde自动生成的，代码如下<br /><br />&lt;?xml version='1.0' encoding='UTF-8'?&gt;<br />&lt;!-- Schema file written by PDE --&gt;<br />&lt;schema targetNamespace="example.my.treeview"&gt;<br />&lt;annotation&gt;<br />    &lt;appInfo&gt;<br />      &lt;meta.schema plugin="example.my.treeview" id="datafactory" name="Data Factory"/&gt;<br />    &lt;/appInfo&gt;<br />    &lt;documentation&gt;<br />      [Enter description of this extension point.]<br />    &lt;/documentation&gt;<br />  &lt;/annotation&gt;<br />&lt;element name="extension"&gt;<br />    &lt;complexType&gt;<br />      &lt;sequence&gt;&lt;element ref="factory"/&gt;&lt;/sequence&gt;<br />      &lt;attribute name="point" type="string" use="required"&gt;<br />        &lt;annotation&gt;&lt;documentation&gt;&lt;/documentation&gt;&lt;/annotation&gt;&lt;/attribute&gt;<br />      &lt;attribute name="id" type="string"&gt;<br />        &lt;annotation&gt;&lt;documentation&gt;&lt;/documentation&gt;&lt;/annotation&gt;&lt;/attribute&gt;<br />      &lt;attribute name="name" type="string"&gt;<br />        &lt;annotation&gt;&lt;documentation&gt;&lt;/documentation&gt;<br />          &lt;appInfo&gt;&lt;meta.attribute translatable="true"/&gt;&lt;/appInfo&gt;&lt;/annotation&gt;<br />      &lt;/attribute&gt;<br />    &lt;/complexType&gt;<br />  &lt;/element&gt;<br />  &lt;element name="factory"&gt;<br />    &lt;complexType&gt;<br />      &lt;attribute name="id" type="string"&gt;<br />        &lt;annotation&gt;&lt;documentation&gt;&lt;/documentation&gt;&lt;/annotation&gt;&lt;/attribute&gt;<br />      &lt;attribute name="name" type="string"&gt;<br />        &lt;annotation&gt;&lt;documentation&gt;&lt;/documentation&gt;&lt;/annotation&gt;&lt;/attribute&gt;<br />      &lt;attribute name="class" type="string" use="required"&gt;<br />        &lt;annotation&gt;&lt;documentation&gt;&lt;/documentation&gt;&lt;/annotation&gt;&lt;/attribute&gt;<br />    &lt;/complexType&gt;<br />  &lt;/element&gt;<br />  &lt;annotation&gt;<br />    &lt;appInfo&gt;&lt;meta.section type="since"/&gt;&lt;/appInfo&gt;<br />&lt;documentation&gt;[Enter the first release in which this extension point appears.]<br />&lt;/documentation&gt;<br />  &lt;/annotation&gt;<br />  &lt;annotation&gt;<br />    &lt;appInfo&gt;&lt;meta.section type="examples"/&gt;&lt;/appInfo&gt;<br />    &lt;documentation&gt;[Enter extension point usage example here.]&lt;/documentation&gt;<br />  &lt;/annotation&gt;<br />  &lt;annotation&gt;<br />    &lt;appInfo&gt;&lt;meta.section type="apiInfo"/&gt;&lt;/appInfo&gt;<br />    &lt;documentation&gt;[Enter API information here.]&lt;/documentation&gt;&lt;/annotation&gt;<br />  &lt;annotation&gt;<br />    &lt;appInfo&gt;&lt;meta.section type="implementation"/&gt;&lt;/appInfo&gt;<br />&lt;documentation&gt;<br />[Enter information about supplied implementation of this extension point.]<br />    &lt;/documentation&gt;&lt;/annotation&gt;<br />  &lt;annotation&gt;<br />    &lt;appInfo&gt;&lt;meta.section type="copyright"/&gt;&lt;/appInfo&gt;<br />    &lt;documentation&gt;&lt;/documentation&gt;&lt;/annotation&gt;<br />&lt;/schema&gt;<br /><br />9.2 创建接口文件<br />ItreeEntry.java之前就已经创建好了，不需要修改。现在添加另一个接口文件，代码如下：<br /><br />package example.my.treeview.internal;<br />public interface IDataFactory {<br />     public Object createTreeData();<br />}<br /><br /><br />于是我们修改DataFactory.java，使它实现这个接口。<br />9.3 修改清单文件<br />我们来修改清单文件，加入扩展点声明，并扩展它，代码如下<br /><br />……<br />&lt;extension-point id="datafactory" name="Data Factory" <br />schema="schema/datafactory.exsd"/&gt;<br />&lt;extension point="example.my.treeview.datafactory"&gt;<br />&lt;factoryclass="example.my.treeview.data.DataFactory"/&gt;<br />&lt;/extension&gt;<br />……<br /><br /><br />9.4 修改TreeviewPlugin.java<br />增加一个方法Object loadDataFactory()，代码如下<br /><br />……<br />public static Object loadDataFactory(){<br />       IPluginRegistry r=Platform. getPluginRegistry();<br />       String pluginID="example.my.treeview"; <br />       String extensionPointID="datafactory"; <br />       IExtensionPoint p=r.getExtensionPoint( pluginID, extensionPointID); <br />       IConfigurationElement[] c=p.getConfigurationElements(); <br />       if( c != null) { <br />             for( int i= 0; i &lt;c.length; i++) { <br />                   IDataFactory data = null;<br />                   try { data=( IDataFactory)c</font>
				<font size="2">
						<em>.createExecutableExtension("class"); <br />                         if( data != null){ return data.createTreeData(); }<br />                   } catch( CoreException x) { }}}<br />       return new Object();<br />  }<br />……<br /><br />9.5 修改TreeViewPart.java<br />将<br />Object inputObj = DataFactory.createTreeData();<br />替换为<br />Object inputObj = TreeviewPlugin.loadDataFactory();<br /><br />9.6 其他辅助文件<br />其实TreeViewerLabelProvider.java和TreeViewerContentProvider.java可以看成是对DataFactory这个扩展点的辅助文件<br /><br />9.7运行<br />跟之前的实现没有区别，但是我们向eclipse贡献了一个扩展点<br /><br /><br />十 参考资料<br />《Eclipse入门到精通》<br /></em>
				</font>
				<a href="http://www.sohozu.com/" target="_blank">
						<font color="#663366" size="2">
								<em>www.sohozu.com</em>
						</font>
				</a>
				<font size="2">
						<em> 《自己动手编写Eclipse扩展点》<br />EclipseCon2005_Tutorial1.pdf 《Contributing to Eclipse: Understanding and WritingPlug- ins》</em>
				</font>
		</span>
		<em>
				<br />
				<br />
		</em>图片： <br /><img onclick="if(this.width&gt;=700) window.open('http://www.eclipseworld.org/bbs/attachment/Mon_0511/76_266.jpg');" src="http://www.eclipseworld.org/bbs/attachment/Mon_0511/76_266.jpg" onload="if(this.width&gt;'700')this.width='700';" border="0" /> <br /><br />图片： <br /><img onclick="if(this.width&gt;=700) window.open('http://www.eclipseworld.org/bbs/attachment/Mon_0511/76_267.jpg');" src="http://www.eclipseworld.org/bbs/attachment/Mon_0511/76_267.jpg" onload="if(this.width&gt;'700')this.width='700';" border="0" /> <br /><br /><br /><span class="tpc_content"><font size="2">经过一个多小时的努力。。。（嘿嘿，以前没有仔细研究Property什么的，今天弄了一下）<br /><br />终于出现了property并且可以修改属性页中的值<br /><b></b><br /><img onclick="if(this.width&gt;=700) window.open('http://www.eclipseworld.org/bbs/attachment/Mon_0512/76_1032_ead87cd8c6fe5c6.jpg');" src="http://www.eclipseworld.org/bbs/attachment/Mon_0512/76_1032_ead87cd8c6fe5c6.jpg" onload="if(this.width&gt;'700')this.width='700';" border="0" /><br /><br /><br />代码<br /><br /></font><a href="http://www.eclipseworld.org/bbs/job.php?action=download&amp;pid=4058&amp;tid=168&amp;aid=463" target="_blank"><font color="#663366" size="2">example.my.treeview.rar</font></a></span><br /><br /><span class="tpc_content"><font size="2">哦，补充一下，由于模型（就是treeviewer中的初始数据）是写死的，改的property其实是修改了内存中的对象的值。假如用emf做模型持久化，就会保存修改。但是目前是不能保存修改的。</font></span><br /><br /><br />关于本文的讨论还是很多的，也有很多有用的信息。见<a href="http://www.eclipseworld.org/bbs/read.php?tid=168">http://www.eclipseworld.org/bbs/read.php?tid=168</a><br />本文第一次发表是在社区之中，本来也没觉得有转到blog的必要，但是后来发觉自己的记忆力越来越差，曾经作过的都忘记的差不多了，为了避免丢失，还是存在这里备份比较好。<img src ="http://www.blogjava.net/hopeshared/aggbug/59983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-07-25 13:54 <a href="http://www.blogjava.net/hopeshared/archive/2006/07/25/59983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse的BPEL</title><link>http://www.blogjava.net/hopeshared/archive/2006/04/24/42826.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Mon, 24 Apr 2006 06:19:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/04/24/42826.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/42826.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/04/24/42826.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/42826.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/42826.html</trackback:ping><description><![CDATA[做了几个web service之后,就需要做服务的集成<br /><br />eclipse上有一个SOA的项目，但是还没有第一个版本出来，尽管用cvs连上了服务器得到了源代码，可以握还是不会运行，呵呵，可能是我比较笨 <br /><br />机器上RSA和WAS都有了，但是还是不能开发BPEL，查了下资料，似乎可以用WSAD来创建BPEL，也可以用Rational XSD来从UML导出BPEL，然后在WPS中运行BPEL<br /><br />等我的机器装上上面的装备，估计就动不了了，于是我四处寻找更简单的开发BPEL的方式<br /><br />接下来就找到了Oracle的JDeveloper，这个工具看起来还挺清爽，但是可惜还是不能创建BPEL，原来它需要Oracle的BPEL编辑器插件。接着在Oracle的站点上找到了这个工具，却发现它居然也有Eclipse的插件，于是安装了一个Eclipse插件。<br /><br />这个BPEL编辑器运行的效果看起来还不错，但是只能编辑BPEL，运行的时候还需要装Oracle的BPEL Server， omg，我发现自己又差点上了“贼船”，这么装下去估计我还要把Oracle他们家的所有软件都装一遍，于是放弃，继续寻找<br /><br />最后不知道在哪里看到了这个链接: <a href="http://www.eclipse.org/bpel">http://www.eclipse.org/bpel</a>，这个链接挺眼生 ，没去过，这不，一上去就发现了新大陆<br /><br />从这个项目的介绍上看跟Oracle的BPEL编辑器能力差不多，不知道是否能运行BPEL。假如不行的话，还有STP的B2J项目可以运行BPEL<br /><br />看来还是有很多人致力于服务集成的，呵呵<img src ="http://www.blogjava.net/hopeshared/aggbug/42826.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-04-24 14:19 <a href="http://www.blogjava.net/hopeshared/archive/2006/04/24/42826.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何让View显示为最大化？</title><link>http://www.blogjava.net/hopeshared/archive/2006/03/27/37641.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Mon, 27 Mar 2006 09:10:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/03/27/37641.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/37641.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/03/27/37641.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/37641.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/37641.html</trackback:ping><description><![CDATA[
		<p>我找到的两种方法，希望大家补充<br /><br />第一种：利用Action<br /><font size="2">IWorkbenchWindow window = getViewSite().getWorkbenchWindow();<br />IWorkbenchAction max = ActionFactory.MAXIMIZE.create(window);<br />max.run();</font><br /><br />这段代码要放在何适的位置上才会起到合适的作用。<br /><br />第二种：利用Zoom<br />在ApplicationWorkbenchWindowAdvisor#postWindowOpen中做到<br />public void postWindowOpen() {<br />     IWorkbenchWindow window = Plugin.getDefault().getWorkbench().getActiveWorkbenchWindow();<br />     IViewPart part=null;<br />     try {<br />         part = window.getActivePage().showView(View.ID);<br />     } catch (PartInitException e) {<br />         e.printStackTrace();<br />     }<br />  <br />     if(part!=null){<br />        window.getActivePage().activate(part); <br />        window.getActivePage().bringToTop(part);<br />  <br />        WorkbenchPage realPage = (WorkbenchPage) window.getActivePage();</p>
		<p>        IWorkbenchPartReference partRef = window.getActivePage().getActivePartReference();</p>
		<p>        if (partRef != null) {<br />            ((WorkbenchPage) window.getActivePage()).toggleZoom(partRef);<br />        }else{<br />         System.out.println("partRef is null!");<br />        }<br />    }<br />}<br /><br /></p>
<img src ="http://www.blogjava.net/hopeshared/aggbug/37641.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-03-27 17:10 <a href="http://www.blogjava.net/hopeshared/archive/2006/03/27/37641.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何在Eclipse/RCP中动态加载我的插件？？</title><link>http://www.blogjava.net/hopeshared/archive/2006/03/23/37000.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Thu, 23 Mar 2006 03:16:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/03/23/37000.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/37000.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/03/23/37000.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/37000.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/37000.html</trackback:ping><description><![CDATA[其实很多人都问到了这个问题。目前插件的安装是需要重启的，但是很多情况下是有不重启而安装插件的需求。我找到的一点资料，应该会有帮助<br /><br /><br /><br /><h1 class="firstHeading">FAQ How do I make my plug-in dynamic aware?</h1><div id="bodyContent"><h3 id="siteSub">From Eclipsepedia</h3><div id="contentSub"></div><!-- start content --><p><i></i></p><p><br /></p><p><br /></p><p><br /></p><p>Dynamic awareness requires extra steps that were not required prior to the introduction of dynamic plug-ins. Dynamic awareness requires that you remove all references to classes defined in other plug-ins when those plug-ins are removed from the system. In particular, if your plug-in defines extension points that load classes from other plug-ins—executable extensions—you need to discard those references when other plug-ins are dynamically removed. The extension registry allows you to add a listener that notifies you when extensions are being added or removed from the system. If your plug-in maintains its own cache of extensions that are installed on your extension point, your listener should update this cache for each added or removed extension. </p><p><br /></p><p><br />The following is an example of a simple class that maintains its own cache of the set of extensions installed for a given extension point. This example is a bit contrived as simply caching the extension objects has no value. Typically, your plug-in will process the extensions to extract useful information and possibly load one or more classes associated with that extension. The basic structure of this cache example is as follows: </p><pre>   public class ExtCache implements IRegistryChangeListener {
      private static final String PID = "my.plugin";
      private static final String PT_ID = 
         PID + "." + "extension.point";
      private final HashSet extensions = new HashSet();
      ...
   }
</pre><p>The <tt>extensions</tt> field stores the set of installed extensions for a particular extension point. </p><p><br /></p><p><br />The cache has a <tt>startup</tt> method that loads the initial set of extensions and then adds an extension registry listener in order to be notified of future changes: </p><pre>   public void startup() {
      IExtensionRegistry reg = Platform.getExtensionRegistry();
      IExtensionPoint pt = reg.getExtensionPoint(PT_ID);
      IExtension[] ext = pt.getExtensions();
      for (int i = 0; i &lt; ext.length; i++)
         extensions.add(ext[i]);
      reg.addRegistryChangeListener(this);
   }
</pre><p>The class implements the <tt>IRegistryChangeListener</tt> interface, which has a single method that is called whenever the registry changes: </p><pre>   public void registryChanged(IRegistryChangeEvent event) {
      IExtensionDelta[] deltas = 
                          event.getExtensionDeltas(PID, PT_ID);
      for (int i = 0; i &lt; deltas.length; i++) {
         if (deltas[i].getKind() == IExtensionDelta.ADDED)
            extensions.add(deltas[i].getExtension());
         else
            extensions.remove(deltas[i].getExtension());
      }
   }
</pre><p>This class is now dynamic aware but is not yet dynamic enabled; that is, the class does not yet support itself being dynamically removed. The final step is to implement a <tt>shutdown</tt> method that clears all values from the cache and removes the listener from the extension registry: </p><pre>   public void shutdown() {
      extensions.clear();
      IExtensionRegistry reg = Platform.getExtensionRegistry();
      reg.removeRegistryChangeListener(this);
   }
</pre><p>This <tt>shutdown</tt> method must be called from the <tt>shutdown</tt> method of the plug-in that defines the cache. For the complete source code of this example, see the <tt>ExtCache</tt> class in the FAQ Examples plug-in. </p><p><br /></p><p><br />Note that not only extensions points acquire and maintain references to classes defined in other plug-ins. You need to be especially aware of static fields and caches that contain references to objects whose class is defined in other plug-ins. </p><p>If you hold onto classes defined in other plug-ins through different mechanisms, you also need to discard those references when those other plug-ins are removed. <br /><br /><br />原文地址：<a href="http://wiki.eclipse.org/index.php/FAQ_How_do_I_make_my_plug-in_dynamic_aware%3F">http://wiki.eclipse.org/index.php/FAQ_How_do_I_make_my_plug-in_dynamic_aware%3F</a></p></div><img src ="http://www.blogjava.net/hopeshared/aggbug/37000.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-03-23 11:16 <a href="http://www.blogjava.net/hopeshared/archive/2006/03/23/37000.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>RCP的外观</title><link>http://www.blogjava.net/hopeshared/archive/2006/03/16/35677.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Thu, 16 Mar 2006 08:34:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/03/16/35677.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/35677.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/03/16/35677.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/35677.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/35677.html</trackback:ping><description><![CDATA[以前做的RCP没有注意如何将外观作漂亮，都作为遗留问题保存了下来<BR><BR>今天在<A href="http://www.eclipseworld.org/bbs/?u=1032">Eclipse社区</A>找到了答案，贴上来做个备份.<BR><BR>原文地址：<A href="http://www.eclipseworld.org/bbs/read.php?tid=2689&amp;keyword">http://www.eclipseworld.org/bbs/read.php?tid=2689&amp;keyword</A>=<BR><BR><BR>问题：<BR><SPAN class=tpc_content><FONT size=2>不好意思，刚开始看RCP，有个小问题，怎么样才能把外观设置为和<BR><IMG height=474 alt="" hspace=0 src="http://www.eclipseworld.org/bbs/attachment/Mon_0512/91_4643_a110dbf32b286d3.jpg" width=660 align=baseline border=0><BR><BR>上图中，‘系统主菜单’这里的tab一样，带有圆弧形，而不是rcp默认的方的那种样式呢？<BR><BR>答：<BR><BR></FONT>
<P><SPAN class=tpc_content><FONT size=2>得把org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS=false加在plugin_customization.ini里头</FONT></SPAN></P>
<P><SPAN class=tpc_content><FONT size=2>plugin_customization.ini还可以定制不少东西，</FONT><SPAN class=tpc_content><FONT size=2>这个文件要自己创建的吧，RCP程序里面没有<BR><BR>在plugin.xml，org.eclipse.core.runtime.products下的产品加上一个属性。<BR>name: preferenceCustomization<BR>value: plugin_customization.ini<BR><BR>然后在工程中加上plugin_customization.ini 这文件。内容是：<BR>org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS=false</FONT></SPAN></SPAN><BR></SPAN></P><img src ="http://www.blogjava.net/hopeshared/aggbug/35677.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-03-16 16:34 <a href="http://www.blogjava.net/hopeshared/archive/2006/03/16/35677.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>How can I change the default UI settings for the perspective bar location, fast view bar location, etc?</title><link>http://www.blogjava.net/hopeshared/archive/2006/02/15/30813.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Wed, 15 Feb 2006 07:12:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/02/15/30813.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/30813.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/02/15/30813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/30813.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/30813.html</trackback:ping><description><![CDATA[<H2>&nbsp;</H2>
<DL>
<DD>Several UI settings such as the perspective bar location, fast view bar location, traditional vs. curvy tabs, etc., are controlled by preferences on the UI plug-in. These have default values defined by the generic workbench. However, the product can override these default values using the product preference customization mechanism. 
<DD><A class="external text" title="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/guide/product def.htm" href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/guide/product_def.htm" rel=nofollow>Define a product</A> via the <A class="external text" title="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/guide/product def extpt.htm" href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/guide/product_def_extpt.htm" rel=nofollow>products extension point</A> and add the following property: </DD></DL><PRE>&lt;property
  name="preferenceCustomization"
  value="plugin_customization.ini"/&gt;
</PRE>
<DL>
<DD>Then create a file called <CODE>plugin_customization.ini</CODE>, in the same directory as the <CODE>plugin.xml</CODE> file, with contents of the form: </DD></DL><PRE>&lt;pluginId&gt;/&lt;preferenceName&gt;=&lt;preferenceValue&gt;
</PRE>
<DL>
<DD>For example, to show the perspective bar and fast view bar on the left, and to use curvy tabs, add the following to the <CODE>plugin_customization.ini</CODE> file: </DD></DL><PRE>org.eclipse.ui/DOCK_PERSPECTIVE_BAR=left
org.eclipse.ui/SHOW_TEXT_ON_PERSPECTIVE_BAR=false
org.eclipse.ui/initialFastViewBarLocation=left
org.eclipse.ui/SHOW_TRADITIONAL_STYLE_TABS=false
</PRE>
<DL>
<DD>For a list of public preferences available on the UI plug-in and their valid values, see the interface <A class="external text" title=http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/IWorkbenchPreferenceConstants.html href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/IWorkbenchPreferenceConstants.html" rel=nofollow>org.eclipse.ui.IWorkbenchPreferenceConstants</A>. 
<DD>For more details, see the <A class="external text" title=http://eclipse.org/articles/Article-Branding/branding-your-application.html href="http://eclipse.org/articles/Article-Branding/branding-your-application.html" rel=nofollow>Branding Your Application</A> article and the <A class="external text" title="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/guide/product configproduct.htm" href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/guide/product_configproduct.htm" rel=nofollow>Customizing a product</A> section in Help. <BR><BR><BR><A href="http://wiki.eclipse.org/index.php/RCP_FAQ#How_can_I_change_the_default_UI_settings_for_the_perspective_bar_location.2C_fast_view_bar_location.2C_etc.3F">http://wiki.eclipse.org/index.php/RCP_FAQ</A></DD></DL><img src ="http://www.blogjava.net/hopeshared/aggbug/30813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-02-15 15:12 <a href="http://www.blogjava.net/hopeshared/archive/2006/02/15/30813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从插件/RCP中取得文件路径的方法</title><link>http://www.blogjava.net/hopeshared/archive/2005/12/20/24798.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Tue, 20 Dec 2005 07:37:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2005/12/20/24798.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/24798.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2005/12/20/24798.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/24798.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/24798.html</trackback:ping><description><![CDATA[最近<A href="http://bbs.rcp.cn/?u=1032">社区</A>里问这个问题的人特别多，所以在这里将自己用到的几个方法写出来。假如以后还有其他的方法，会进行更新。<BR><BR>从插件中获得绝对路径：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">AaaaPlugin.getDefault().getStateLocation().makeAbsolute().toFile().getAbsolutePath());</SPAN></DIV>
<P><BR><BR>通过文件得到Project：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">IProject&nbsp;project&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;((IFile)o).getProject();</SPAN></DIV>
<P><BR><BR>通过文件得到全路径：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">String&nbsp;path&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;((IFile)o).getLocation().makeAbsolute().toFile().getAbsolutePath();<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></DIV>
<P><BR><BR>得到整个Workspace的根：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">IWorkspaceRoot&nbsp;root&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;ResourcesPlugin.getWorkspace().getRoot();</SPAN></DIV>
<P><BR><BR>从根来查找资源：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">IResource&nbsp;resource&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;root.findMember(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Path(containerName));</SPAN></DIV>
<P><BR>从Bundle来查找资源：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">Bundle&nbsp;bundle&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Platform.getBundle(pluginId);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>URL&nbsp;fullPathString&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;BundleUtility.find(bundle,&nbsp;filePath);<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></DIV><BR>
<P><SPAN class=tpc_content><BR><BR>得到Appliaction workspace：</P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">Platform.asLocalURL(PRODUCT_BUNDLE.getEntry(</SPAN><SPAN style="COLOR: #000000">""</SPAN><SPAN style="COLOR: #000000">)).getPath()).getAbsolutePath();</SPAN></DIV><BR><BR>得到runtimeworkspace：<BR>&nbsp; 
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">Platform.getInstanceLocation().getURL().getPath();</SPAN></DIV></SPAN><BR><BR>从编辑器来获得编辑文件<BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">IEditorPart&nbsp;editor&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;((DefaultEditDomain)(parent.getViewer().getEditDomain())).getEditorPart();<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>IEditorInput&nbsp;input&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;editor.getEditorInput();<BR><IMG id=Codehighlighter1_179_233_Open_Image onclick="this.style.display='none'; Codehighlighter1_179_233_Open_Text.style.display='none'; Codehighlighter1_179_233_Closed_Image.style.display='inline'; Codehighlighter1_179_233_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_179_233_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_179_233_Closed_Text.style.display='none'; Codehighlighter1_179_233_Open_Image.style.display='inline'; Codehighlighter1_179_233_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">(input&nbsp;</SPAN><SPAN style="COLOR: #0000ff">instanceof</SPAN><SPAN style="COLOR: #000000">&nbsp;IFileEditorInput)</SPAN><SPAN id=Codehighlighter1_179_233_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_179_233_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;IFile&nbsp;file&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;((IFileEditorInput)input).getFile();<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV><img src ="http://www.blogjava.net/hopeshared/aggbug/24798.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2005-12-20 15:37 <a href="http://www.blogjava.net/hopeshared/archive/2005/12/20/24798.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转一篇好文:Dissect Eclipse Plugin Framework</title><link>http://www.blogjava.net/hopeshared/archive/2005/12/15/24000.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Thu, 15 Dec 2005 03:55:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2005/12/15/24000.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/24000.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2005/12/15/24000.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/24000.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/24000.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在讨论Xerdoc DSearch的架构的时候，我们就讨论决定采用Eclipse Plugin Framework，可惜那时Eclipse Plugin Framework和SWT以及其它耦合比较大，因此，决定借鉴Eclipse Plugin Framework的思想，来实现一个自己的轻量级的Plugin Framework。一晃已经过去快一年了，其实非常早就想把自己研究Eclipse Plu...&nbsp;&nbsp;<a href='http://www.blogjava.net/hopeshared/archive/2005/12/15/24000.html'>阅读全文</a><img src ="http://www.blogjava.net/hopeshared/aggbug/24000.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2005-12-15 11:55 <a href="http://www.blogjava.net/hopeshared/archive/2005/12/15/24000.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转: 服务数据对象简介</title><link>http://www.blogjava.net/hopeshared/archive/2005/12/14/23901.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Wed, 14 Dec 2005 08:51:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2005/12/14/23901.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/23901.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2005/12/14/23901.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/23901.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/23901.html</trackback:ping><description><![CDATA[<SPAN id=LblContent>&nbsp;
<P>简单地说，SDO是一种数据应用程序开发框架，它包括一个体系结构和相应的 API。SDO 能够实现以下操作：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>简化 J2EE 数据编程模型。 
<LI>抽象面向服务体系结构（SOA）中的数据。 
<LI>统一数据应用程序的开发。 
<LI>支持和集成 XML。 
<LI>结合 J2EE 模式和最佳实践。 </LI></UL>
<P>在这篇介绍 SDO 框架的文章中，我们将尝试着解释 SDO 背后的动机，以及 SDO 与其他规范的区别，然后描述 SDO 的组成，最后，通过一个示例 SDO 应用程序说明 SDO 的用法。</P>
<P><A name=N10073><SPAN class=atitle2>为什么要使用 SDO？</SPAN></A><BR>对于服务数据对象（SDO），大多数开发人员要问的第一个问题就是为什么要使用 SDO。难道 J2EE 本身还不够庞大、不够复杂（而且难以掌握）吗？Java 环境中不是已经有其他支持 XML 的框架了吗？所幸的是，该问题的答案能够让我们多数人感到满意：SDO 是作为简化 J2EE 数据编程模型的方法出现的，它能够让 J2EE 开发人员把更多的时间用于应用程序的业务逻辑。</P>
<P>服务数据对象框架为数据应用程序开发提供了统一的框架。通过 SDO，您不需要熟悉特定于技术的 API，就能访问和利用数据。您只需要知道一种 API，即 SDO API，它允许您处理来自多种数据源的数据，其中包括关系数据库、实体 EJB 组件、XML 页面、Web 服务、Java Connector Architecture、JavaServer Pages 页面等。</P>
<P>注意，我们使用了 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">框架</I>这一词。这是比照 Eclipse 框架的说法。由于设计的基础坚固而且可以扩展，所以 Eclipse 能够集成各种工具。与此类似，对于采用 SDO 的应用程序，SDO 也是一种框架，这类应用程序在 SDO 模型上是一致的。 </P>
<P>与其他某些数据集成模型不同的是，SDO 没有停留在数据抽象上。SDO 框架还结合了很多 J2EE 模式和最佳实践，从而使应用程序很容易结合经过验证的体系结构和设计。比方说，今天的多数 Web 应用程序百分之百的时间没有（或不能）连接到后端系统，因此 SDO 支持不连接的编程模型。同样的，今天的应用程序往往非常复杂，包含很多层次。如何存储数据、如何发送数据、如何在 GUI 框架中将它们提供给终端用户？SDO 编程模型提供的应用模式能够清晰地划分不同的问题。</P>
<P>XML 在分布式应用程序中日渐普及。比如，XML Schema (XSD) 被用来定义应用程序数据格式中的业务规则。XML 本身也可以用于改进交互性：Web 服务使用基于 XML 的 SOAP 作为消息格式。XML 是推动 SDO 的一个重要原因，SDO 框架支持并集成了 XML。</P>
<P><A name=N1008B><SPAN class=atitle2>各种技术的比较</SPAN></A><BR>前面已经提到，SDO 并不是提出解决分布式应用程序中数据集成问题的惟一技术。下面将分别讨论 SDO 和类似的编程框架 JDO、JAXB 和 EMF 的优劣。</P>
<P><A name=N10094><SPAN class=atitle3>SDO 和 WDO</SPAN></A><BR>Web 数据对象（或 WDO）是随着 IBM WebSphere® Application Server 5.1 和 IBM WebSphere Studio Application Developer 5.1.2 发布的 SDO 早期版本的名称。如果使用过 WebSphere Studio 5.1.2，那么您对 SDO 可能已经有所了解，虽然您可能习惯看到将它标记为 WDO，比如在数据库的名字中。忘掉 WDO 吧，它现在的名字是 SDO！</P>
<P><A name=N1009D><SPAN class=atitle3>SDO 和 JDO</SPAN></A><BR>JDO 代表 Java Data Object（Java 数据对象）。JDO 已经通过 Java 社区进程（JCP）标准化了 1.0 版，2003 年 5 月推出了维护版 1.0.1，现在已经为 2.0 版成立了 JCP 专家组。JDO 针对 Java 环境中的数据编程提供了一种通用 API，用于访问存储在不同数据源中的数据，如数据库、文件系统或者事务处理系统。JDO 保持了 Java 对象（图）之间的关系，同时允许对数据的并发访问。</P>
<P>JDO 希望简化和统一 Java 数据编程，以便开发人员能够专注于业务逻辑，而不是底层的技术，从这一点上说，其目标和 SDO 是相同的。但主要的区别在于，JDO 仅考虑持久性问题（J2EE 数据层或者企业信息系统（EIS）层），而 SDO 更具一般性，关注的是不同 J2EE 层次间数据流的表示，比如表示层和业务层。</P>
<P>有趣的是，SDO 可以结合 JDO 一起使用，JDO 作为数据源，SDO 来访问它，这就是 Data Transfer Object（数据传输对象，DTO）设计模式的具体运用。同样，SDO 也可以结合实体 EJB 组件和 Java Connector Architecture（Java 连接器体系结构，JCA）使用，目的是提供统一的数据访问。</P>
<P><A name=N100AC><SPAN class=atitle3>SDO 和 EMF</SPAN></A><BR>EMF 代表 Eclipse Modeling Framework（Eclipse 建模框架）。EMF 根据使用 Java 接口、XML Schema 或者 UML 类图定义的数据模型生成统一的元模型（称为 Ecore），可以将元模型与框架结合在一起使用，创建高质量的模型实现。EMF 提供了持久性、一个有效的反射类属对象操纵 API 和一个变更通知框架。EMF 还包括用来构建 EMF 模型编辑器的一般的重用类。</P>
<P>EMF 和 SDO 都可以处理数据表示。事实上，IBM 的 SDO 参考实现就是一种 SDO 的 EMF 实现，后面我们还要用到该实现。还可以根据 UML 模型定义或者 SDO 本身，用 EMF 代码生成来创建 SDO 实现的某些部分。SDO 实现基本上是 EMF 中的一小层（方面），它是作为 EMF 项目的一部分打包和提供的。关于 EMF 的更多信息，请参阅 <A href="http://kb.csdn.net/java/Articles/200509/adf06e7d-6585-4df5-b7be-f658302fed50.html#resources" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">参考资料</A>。 </P>
<P><A name=N100BC><SPAN class=atitle3>SDO 和 JAXB</SPAN></A><BR>JAXB 代表 Java API for XML Data Binding（XML 数据绑定 Java API）。JAXB 1.0 在 2003 年 1 月由 JCP 发布。JCP 专家组已经制定了 2.0 版的初步草案。JAXB 是关于 XML 数据绑定的，也就是说，将 XML 数据表示成内存中的 Java 对象。作为 Java 语言的 XML 绑定框架，JAXB 可以节约解析和创建 XML 文档的时间。（事实上，通过它，您完全不需要和 XML 打交道。）JAXB 为您执行编组/序列化（Java 到 XML）和解组/并行化（XML 到 Java）。</P>
<P>SDO 定义了自己的 Java 绑定框架，但是走得还要远一些。JAXB 仅关注 Java 到 XML 的绑定，而绑定到 SDO 的不仅仅是 XML 数据。如前所述，SDO 提供了对不同类型数据的统一访问，XML 仅是其中的一种数据类型。SDO 还提供了静态和动态 API <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">*</B>，而 JAXB 仅提供了静态绑定。 </P>
<P><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">*</B> <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">注意，本文中示例应用程序仅使用了动态 SDO，虽然 EMF 代码生成器也为数据对象的静态代码生成提供了完整的支持。</I> </P>
<P><A name=N100D4><SPAN class=atitle3>SDO 和 ADO .NET</SPAN></A><BR>ADO 代表 ActiveX Data Objects（ActiveX 数据对象），但是在 .NET 上下文中，其含义已经发生了变化。ADO .NET 提供了 .NET 框架下不同层次间的统一数据访问机制。</P>
<P>ADO .NET 和 SDO 具有相同的动机，都是用来支持 XML 和分布在多个层上的应用程序。除了技术性的差异外，这两项技术主要的不同在于：ADO .NET 用于 Microsoft .NET 平台，是一种私有的技术；而 SDO 用于 Java (J2EE) 平台，通过 Java 社区进程实现标准化。</P>
<P><A name=N100E0><SPAN class=atitle2>SDO 的组成部分</SPAN></A><BR>这一节将介绍 SDO 的体系结构。我们将介绍组成框架的不同组成部分和它们之间的协作。首先要讨论的三个组成部分之一是 SDO 的“概念性”特征，API 中没有对应的接口。</P>
<P><A name=N100E9><SPAN class=atitle3>SDO 客户机</SPAN></A><BR>SDO 客户机使用 SDO 框架处理数据。SDO 客户机使用的不是特定于技术的 API 和框架，而是 SDO 编程模型和 API。SDO 客户机处理 SDO 数据图（参见 <A href="http://kb.csdn.net/java/Articles/200509/adf06e7d-6585-4df5-b7be-f658302fed50.html#fig1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 1</A>），不需要了解所处理的数据是如何持久保存或者序列化的。 </P>
<P><A name=N100F6><SPAN class=atitle3>Data 中介服务</SPAN></A><BR>数据中介服务（DMS）负责从数据源创建数据图、依据数据图的变化更新数据源。数据中介框架不属于 SDO 1.0 规范，换句话说，SDO 1.0 没有涉及具体的 DMS。常见的 DMS 有 JDBC DMS、实体 EJB DMS 和 XML DMS 等。</P>
<P><A name=N100FF><SPAN class=atitle3>数据源</SPAN></A><BR>数据源不限于后端数据源（如持久存储数据库）。数据源以自己的格式保存数据。只有 DMS 访问数据源，SDO 应用程序不访问数据源。SDO 应用程序可能只使用数据图中的数据对象。</P>
<P>下面介绍的每个组件对应于 SDO 编程模型的一个 Java 接口。SDO 参考实现（请参阅 <A href="http://kb.csdn.net/java/Articles/200509/adf06e7d-6585-4df5-b7be-f658302fed50.html#resources" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">参考资料</A>）提供了这些接口基于 EMF 的实现。 </P>
<P><A name=N1010F><SPAN class=atitle3>数据对象</SPAN></A><BR>数据对象是 SDO 的基本组件。事实上，它们是规范名称中的 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">服务数据对象</I>。数据对象是结构化数据的 SDO 表示。数据对象是通用的，它们提供了 DMS 创建的结构化数据的公共视图。比方说，虽然 JDBC DMS 需要知道持久性技术（比如关系数据库），以及如何配置和访问数据，SDO 客户机不需要了解这些细节。数据对象在属性中保存它们的“数据”（稍后还要讨论属性）。数据对象提供了易于使用的创建和删除方法（带有不同签名的 <CODE>createDataObject()</CODE> 和 <CODE>delete()</CODE> ），获得自身类型（实例类、名称、属性和名称空间）的反射方法。数据对象都链接在一起，包含在数据图中。 </P>
<P><A name=N10123><SPAN class=atitle3>数据图</SPAN></A><BR>数据图提供了数据对象树的容器。数据图由 DMS 生成，供 SDO 客户机使用。修改后，数据图被回传给 DMS 更新数据源。SDO 客户机可以遍历数据图，读取和修改数据图中的数据对象。SDO 是一种 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">无连接的体系机构</I>，因为 SDO 客户机与 DMS 和数据源没有连接，所以 SDO 客户机看到的只有数据图。此外，数据图可以包含表示不同数据源中数据的对象。数据图包含一个根数据对象、与根关联的所有数据对象和变更摘要（change summary，参见本文后面的叙述）。当在应用程序组件（比如服务调用期间的 Web 服务请求者和提供者）之间进行传输、组件到 DMS 的传输（或者保存到磁盘）的时候，数据图被序列化为 XML。SDO 规范提供了序列化的 XML Schema。图 1 显示了一个 SDO 数据图。 </P>
<P><A name=fig1><B>图 1. SDO 数据图</B></A><BR><IMG height=234 alt="SDO 数据图" src="http://www.ibm.com/developerworks/cn/java/j-sdo/DataGraph.gif" width=315 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=changesum><SPAN class=atitle3>变更摘要</SPAN></A><BR>变更摘要包含在数据图中，表示对 DMS 返回的数据图的修改。变更摘要最初是空的（数据图刚返回客户机的时候），随着数据图的变化逐渐填充。在后台更新时，DMS 使用变更摘要将修改应用于数据源。变更摘要提供了数据图中被修改的属性（包括原来的值）、新增和删除的数据对象的列表，从而使 DMS 以递增方式高效地更新数据源。只有当变更摘要日志功能被激活时，才会将信息添加到数据图的变更摘要中。变更摘要提供了让 DMS 打开和关闭日志功能的方法，后面的例子中还将详细对其进行介绍。</P>
<P><A name=N10149><SPAN class=atitle3>属性、类型和序列</SPAN></A><BR>数据对象用一系列属性保存其内容。每个属性都有一个类型，该类型既可以是基本类型（如 <CODE>int</CODE> ）这样的属性类型，也可以是通用数据类型（如 <CODE>Date</CODE> ），如果引用的话，还可以是其他数据对象类型。每个数据对象都为属性提供了访问和设置方法（getter 和 setter）。这些访问器方法有不同的重载版本，可以通过传递属性名（ <CODE>String</CODE> ）、编号（ <CODE>int</CODE> ）或者属性元对象本身来访问属性。String 访问器还允许使用类 XPath 的语法访问属性。比如，可以对公司数据对象调用 <CODE>get("department[number=123]")</CODE> 来访问编号为 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">123</I>的第一个部门。序列更加高级，可以保持不同种类的属性-值对列表的顺序。 </P>
<P><A name=N10169><SPAN class=atitle2>SDO 和示例安装</SPAN></A><BR>我们已经讲了很多的概念和理论，现在要进行一些实际操作了。好消息是您马上就能使用 SDO，而且是免费的。这一节将介绍一个 SDO 示例应用程序，它将在 SDO 的 IBM 参考实现上运行，这个参考实现是 Eclipse Modeling Framework (EMF) 的一部分。我们首先将说明如何安装 EMF 2.0.1（包括 SDO），然后将介绍如何设置本文提供的示例应用程序。</P>
<P><A name=N10172><SPAN class=atitle3>安装 EMF 2.0.1</SPAN></A><BR>如果已经安装了 EMF 2.0.1，或者知道怎么安装，那么请跳过这一节，直接阅读下一节。</P>
<P>IBM SDO 1.0 实现和 EMF 2.0.1 一起打包。要使用 SDO，则需要安装 EMF 2.0.1 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">*</B>。您可以按照 EMF 站点上的说明使用 Eclpise 更新管理器，也可以按照下面的步骤操作。 </P>
<P><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B>*</B>EMF 2.0.0 中也包含 SDO 1.0 的实现。 </I></P>
<P>在 <A href="http://www.eclipse.org/emf" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">EMF 主页</A>中的“快速导航”部分可以找到下载链接页面，选择下载“v2.x: EMF 和 SDO”。安装 EMF 之前一定要阅读安装要求。安装 EMF 2.0.1 之前至少要安装了 Eclipse 3.0.1 和 Java Development Kit (JDK) 1.4。一定要选择 EMF 2.0.1 发行版本。打包类型建议选择“All”：emf-sdo-xsd-SDK-2.0.1.zip，这样，就可以在一个文件中找到源代码、运行文件和文档。如果愿意，还可以下载 SDO 的最小安装包“EMF &amp; SDO RT”：emf-sdo-runtime-2.0.1.zip。 </P>
<P>在解压 Eclipse 的目录中解压 zip 文件（压缩包中的文件组织结构为 eclipse/plugins/...）。启动 Eclipse，然后选择 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Help&gt;About the Eclipse Platform</B>，检查 EMF 是否安装成功。单击 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Plug-in Details</B>按钮，确保 org.eclipse.emf.* 插件在 2.0.1 层次上。有 6 个与 SDO 有关的插件： </P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>org.eclipse.emf.commonj.sdo 
<LI>org.eclipse.emf.ecore.sdo 
<LI>org.eclipse.emf.ecore.sdo.doc 
<LI>org.eclipse.emf.ecore.sdo.edit 
<LI>org.eclipse.emf.ecore.sdo.editor 
<LI>org.eclipse.emf.ecore.sdo.source </LI></UL>
<P>运行时只需要两个插件： <CODE>org.eclipse.emf.commonj.sdo</CODE> 和 <CODE>org.eclipse.emf.ecore.sdo</CODE> ，如果选择仅安装运行时插件，那么您只能看到这两个插件。这样就完成了 EMF 的安装。 </P>
<P><A name=N101BA><SPAN class=atitle3>安装示例 SDO 应用程序</SPAN></A><BR>下一步是在工作区中添加本文所用的 SDO 示例应用程序，步骤如下：</P>
<OL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>启动 Eclipse 并创建一个新的 Plug-In Project。 
<LI>将项目命名为 <B>SDOSample</B>，选择源文件夹 <I>src</I>和输出文件夹 <I>bin</I>，建立 Java 源代码。 
<LI>单击 <B>Next</B>。 
<LI>取消选择“Generate the Java class that controls the plug-in's life cycle（生成控制插件生命期的 Java 类）”选项并单击 <B>Finish</B>。 </LI></OL>
<P>然后，单击本文顶端或底端的 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Code</B>图标（或者参阅 <A href="http://kb.csdn.net/java/Articles/200509/adf06e7d-6585-4df5-b7be-f658302fed50.html#download" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">下载</A>部分）下载 j-sdoSample.zip，并将其解压缩到 SDOSample 目录中（在 Eclipse 窗口中选择 Import... &gt;Zip file）。一定要保留文件夹结构并覆盖原来的文件，这样，就可以用 j-sdoSample.zip 中的文件代替 SDOSample 项目。 </P>
<P><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B>注意：</B>SDOSample 是作为 Eclipse 插件项目打包的，因此不需要自己设置库依赖关系。但是，在本例中，只包含 Java 代码，如果在 CLASSPATH 中包含 EMF 和 SDO 库（JAR 文件），也可将 SDOSample 作为独立的应用程序运行。 </I></P>
<P>环境设置应该与下面截屏图中的类似。</P>
<P><A name=N101F9><B>图 2. Eclipse 环境</B></A><BR><IMG height=401 alt="Eclipse 环境" src="http://www.ibm.com/developerworks/cn/java/j-sdo/EclipseEnvironment.jpg" width=600 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>现在开始使用这个示例 SDO 应用程序。</P>
<P><A name=N1020B><SPAN class=atitle2>一个简单的 SDO 应用程序</SPAN></A><BR>本文后面将使用的示例应用程序从功能上说很有限，但它可以帮助您更好地理解 SDO。该应用程序包括两部分，分别放在两个包中：dms 和 client。</P>
<P>SDO 1.0 没有规定标准 DMS API。因此我们为这个例子设计了自己的 DMS 接口，它包含两个方法，如清单 1 所示。</P><A name=N10217><B>清单 1. DMS 接口</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
/**
 * A simple Data Mediator Service (DMS) that builds
 * SDO Data Graphs of Employees and updates
 * a backend data source according to a Data Graph. 
 */
public interface EmployeeDMS
{
  /**
   * @param employeeName the name of the employee.
   * @return an SDO Data Graph with Data Objects for
   * that employee's manager, that employee,
   * and that employee's "employees".
   */
  DataGraph get(String employeeName);

  /**
   * updates backend data source according to dataGraph.
   * @param dataGraph Data Graph used to update data source.
   */
  void update(DataGraph dataGraph);
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>客户机将实例化 DMS，并调用 <CODE>get()</CODE> 方法访问特定的雇员：Big Boss、Wayne Blanchard 和 Terence Shorter。它以用户友好的方式在控制台中打印这些雇员的信息，然后更新 Terence Shorter 及其雇员的部门信息。最后调用 DMS 的 <CODE>update()</CODE> 方法，传递更新的 Terence Shorter 数据图。 </P>
<P>注意，为了便于示范，我们没有实现数据源组件，但在 DMS 中，有一些如何根据查询构建数据图的“硬编码”知识。图 3 显示了 DMS 正在使用的雇员层次结构。</P>
<P><A name=N10231><B>图 3. Big Boss 公司的雇员</B></A><BR><IMG height=213 alt="Big Boss 公司的雇员" src="http://www.ibm.com/developerworks/cn/java/j-sdo/MrBigBoss.gif" width=233 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>图中可以看出，DMS 背后的虚拟公司有 4 个雇员，层次结构如下：</P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI>Big Boss 没有上司，Terence Shorter 是其下属。 
<LI>Terence Shorter 以 Big Boss 作为自己的上司，John Datrane 和 Miles Colvis 是其下属。 
<LI>John Datrane 的上司是 Terence Shorter，没有下属。 
<LI>Miles Colvis 的上司是 Terence Shorter，没有下属。 </LI></UL>
<P><A name=N10252><SPAN class=atitle3>运行示例应用程序</SPAN></A><BR>右击 SDOClient.java，然后选择 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Run&gt;Java application</B>运行上述示例应用程序，结果如下： </P><A name=N1025E><B>清单 2. 应用程序的控制台输出</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
********* EMPLOYEE INFORMATION *********

Name: John Datrane
Number: 4
Title: Mr.
Department: Procurement
Is manager?: no

DIRECT MANAGER:

Name: Terence Shorter
Number: 2
Title: Mr.
Department: Financing
Is manager?: yes

****************************************

NO INFORMATION AVAILABLE ON EMPLOYEE Wayne Blanchard

********* EMPLOYEE INFORMATION *********

Name: Terence Shorter
Number: 2
Title: Mr.
Department: Financing
Is manager?: yes

DIRECT MANAGER:

Name: The Big Boss
Number: 1
Title: Mr.
Department: Board
Is manager?: yes

DIRECT EMPLOYEES:

Name: Miles Colvis
Number: 3
Title: Mr.
Department: Accounting
Is manager?: no

Name: John Datrane
Number: 4
Title: Mr.
Department: Procurement
Is manager?: no

[Total: 2]
****************************************

DMS updating Terence Shorter
 (changed department from "Financing" to "The new department")
DMS updating Miles Colvis
 (changed department from "Accounting" to "The new department")
DMS updating John Datrane
 (changed department from "Procurement" to "The new department")
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>现在我们来分析应用程序的各个组成部分是如何工作的。</P>
<P><A name=N1026B><SPAN class=atitle2>客户机</SPAN></A><BR>SDO 客户机例示了 DMS，并从中获得不同雇员的数据图。得到数据图后，通过根对象（使用 SDO 动态 API）遍历和访问数据对象，如下所示：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
// Get the SDO DataGraph from the DMS.
DataGraph employeeGraph = mediator.get(employeeName);
...
// Get the root object
DataObject root = employeeGraph.getRootObject();
...
// get the employee under the manager
employee = theManager.getDataObject("employees.0");
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>客户机调用动态 SDO 访问器 API，从数据对象中获得信息，并将其显示到控制台上：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
System.out.println("Name: " + employee.getString("name"));
System.out.println ("Number: " + employee.getInt("number"));
...
System.out.println ("Is manager?: " + 
  (employee.getBoolean("manager") ? "yes" : "no") + "\n");
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>我们已经看到客户机是如何获取信息（读）的，但是如何写入信息呢？更准确地说，客户机如何修改对象？SDO 客户机一般使用 <CODE>DataObject</CODE> 写访问器方法更新数据对象。比如，下面的代码修改从雇员 Terence Shorter 获得的数据图： </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
employee.setString("department", newDepartmentName);
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>注意，客户机没有调用日志方法。DMS 负责对数据图的变更摘要调用 <CODE>beginLogging()</CODE> 和 <CODE>endLogging()</CODE> 记录日志。 </P>
<P><A name=N10295><SPAN class=atitle2>数据图</SPAN></A><BR>可以将数据图的数据格式（模型）看作 DMS 与客户机之间的抽象。客户机期望从 DMS 得到数据图，DMS 也知道如何创建数据读（包括从后端数据源中读取和更新数据）。如果熟悉 XML 或者 Web 服务，那么可以将数据图模型看作定义数据对象 XML Schema（XSD）。数据图本身就类似 XML 实例文档。事实上，XML Schema 也是定义 SDO 模型的一种方法。</P>
<P>注意，数据图及其模型总是能够序列化为 XML。在 SDOClient.java 中将 <CODE>debug</CODE> 变量设为 <CODE>true</CODE> ，就可以看到运行时在控制台中显示的数据图的序列化版本，与清单 3 类似。 </P><A name=N102A9><B>清单 3. 数据图的序列化版本</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;sdo:datagraph xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:company="http://com.example.company.ecore"
  xmlns:sdo="commonj.sdo"
  xmlns:sdo_1="http://www.eclipse.org/emf/2003/SDO"&gt;
  &lt;changeSummary&gt;
    &lt;objectChanges key="#//@eRootObject"&gt;
      &lt;value xsi:type="sdo_1:EChangeSummarySetting"
        featureName="department" dataValue="Board"/&gt;
    &lt;/objectChanges&gt;
  &lt;/changeSummary&gt;
  &lt;company:Employee name="The Big Boss"
    number="1" department="The new department" title="Mr."
    manager="true"&gt;
    &lt;employees name="Terence Shorter" number="2"
      department="The new department" title="Mr." manager="true"&gt;
      &lt;employees name="Miles Colvis" number="3"
        department="The new department" title="Mr."/&gt;
      &lt;employees name="John Datrane" number="4"
        department="The new department" title="Mr."/&gt;
    &lt;/employees&gt;
  &lt;/company:Employee&gt;
&lt;/sdo:datagraph&gt;
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>在本例中，数据图由 <CODE>Employee</CODE> 数据对象（以及变更摘要）组成。 <CODE>Employee</CODE> 包含姓名、编号、部门、职务、上司（管理该雇员的另一位雇员）和下属（该雇员管理的其他雇员）等属性。该例中，雇员已经位于硬编码的数据源中时，DMS 返回的数据图的格式总是雇员的上司（如果有的话）、雇员及其直接下属（如果有的话）。 </P>
<P><A name=N102BE><SPAN class=atitle2>DMS 构建数据图</SPAN></A><BR>SDO 1.0 没有规定 DMS API，API 应该包含数据图模型本身的设计和创建。因为建立对数据源的访问要考虑很多种情况，设计数据图本身可以作为另一篇文章的主题。</P>
<P>对这个例子，我们将采用 DMS 通过动态 EMF API 定义的雇员模型。示例数据图没有 XSD 这样的模型文档。实际上，因为对象是动态生成的，所以这意味着没有生成 <CODE>Employee</CODE> Java 类。如果使用静态方法，就会生成这样的类。 </P>
<P>DMS 使用不同的数据访问 API（JDBC、SQL 等）从不同数据源获取的信息。但是，一旦从后端（该例中是硬编码的知识）检索到信息，DMS 就转而使用 EMF API（eSet、eGet）而非 SDO API 来创建数据对象的数据图。这种方法能得到较好的性能，但缺点是不能跨 SDO 实现移植。</P>
<P>对于主要关注性能，同样的 DMS 设计也可使用 SDO API 实现。在这种情况下，DMS 类（ <CODE>employeeClass</CODE> 、 <CODE>employeeNameFeature</CODE> 等）中缓冲的元对象，将代替 EMF 类型 <CODE>EClass</CODE> 、 <CODE>EAttribute</CODE> 和 <CODE>EReference</CODE> 等），成为 <CODE>commonj.sdo.Type</CODE> 和 <CODE>commonj.sdo.Property</CODE> 的类型。此外，如果性能不重要，那么可以方便地使用基于 String 的 SDO API（如 <CODE>setBoolean(String path, boolean value)</CODE> ），因此不需要缓冲元对象。不幸的是，这种解决方案虽然更方便，但运行起来也更慢。 </P>
<P>下面的代码片段说明了 SimpleEmployeeDataMediatorImpl.java 中 Employee 模型的定义。但这些代码并没有构建 SDO 对象，构建的仅仅是 SDO 对象的模型：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
protected EClass employeeClass;
protected EAttribute employeeNameFeature;
protected EReference employeeEmployeesFeature;
...

employeeClass = ecoreFactory.createEClass();
employeeClass.setName("Employee");

EAttribute employeeNameFeature = ecoreFactory.createEAttribute();
...
    
// employees (that the employee manages)
employeeEmployeesFeature = ecoreFactory.createEReference();
employeeEmployeesFeature.setContainment(true);
...

EPackage employeePackage = ecoreFactory.createEPackage();
employeePackage.getEClassifiers().add(employeeClass);
...
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>注意，我们使用值 <CODE>true</CODE> 对 <CODE>employees EReference</CODE> 调用 <CODE>setContainment</CODE> ，因此每个雇员都“包含”他或她的下属。否则，嵌套的雇员就不会（即被包含）在数据图中，变更摘要也只能包含根对象的修改，而不能包含其他雇员的修改。 </P>
<P><A name=N1030A><SPAN class=atitle3>建模 SDO</SPAN></A><BR>您可能想“很有趣，但是这样只能得到 EMF 对象而不是 SDO 对象，还有什么窍门吗？”当然有，而且很简单。 <CODE>Employee EClass</CODE> 属于 <CODE>employeePackage EPackage</CODE> ，并且包含下面的调用： </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
// Have the factory for this package build SDO Objects
employeePackage.setEFactoryInstance(
  new DynamicEDataObjectImpl.FactoryImpl());
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>运行时，这个工厂将创建 <CODE>DynamicEDataObjectImpl</CODE> 类型的对象，该对象实现了 <CODE>DataObject</CODE> 接口（即它是一个 SDO 数据对象），而不是默认的 <CODE>DynamicEObjectImpl</CODE> 接口，并且可以智能地创建普通的 EMF 对象。SDO 和 EMF 对象之间的关系就很清楚了：SDO 对象就是同时实现了 SDO <CODE>DataObject</CODE> 接口的 EMF 对象。事实上，这些附加方法的实现是委派给核心 EMF 方法实现的。 </P>
<P><A name=N10332><SPAN class=atitle3>创建 SDO 实例</SPAN></A><BR>现在，已经拥有了我们的数据对象，就可以建立 <CODE>Employee</CODE> 的实例并设置不同的属性了。如前所述，我们将使用 EMF API 来最大程度地提高性能。 </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
EObject eObject = EcoreUtil.create(employeeClass);

// Note: we could cast the object to DataObject,
// but chose to use EObject APIs instead.
eObject.eSet(employeeNameFeature, name);
eObject.eSet(employeeNumberFeature, new Integer(number));
... ...
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>可以使用“employees”引用把雇员“链接”在一起，比如：</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
((List)bigBoss.eGet(employeeEmployeesFeature)).add(terence);
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>一旦创建了数据对象，还需要将其连接到数据图中。我们首先要调用数据图的 <CODE>setRootObject()</CODE> 方法，传递希望用作根的数据对象，这里使用 <CODE>Employee The Boss</CODE> 。 </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
EDataGraph employeeGraph = SDOFactory.eINSTANCE.createEDataGraph();
... ...
employeeGraph.setERootObject(rootObject);
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>继续讨论数据图之前，要先开始记录日志。如果希望使用 SDO，那么在改动数据图之前，要先调用其变更摘要的 <CODE>beginLogging()</CODE> 方法。基本的原理就是清除以前的变化，开始监听新的修改。 </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
// Call beginLogging() so that the Change Summary is
// populated when changes are applied to the Data Graph.
// The DMS should call beginLogging() and endLogging(),
// not the client.
employeeGraph.getChangeSummary().beginLogging();
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>DMS 的另一项任务（按照 <CODE>EmployeeDataMediator</CODE> 接口的定义）是根据 SDO 客户机提供的数据图更新后端数据源。 </P>
<P><A name=N1036B><SPAN class=atitle2>DMS：更新数据源</SPAN></A><BR>DMS 应该使用 SDO 的强大特性更新后端数据源，具体地说，就是要使用其变更摘要。使用数据图的变更摘要有许多不同的方法。该例中，我们将考察变更摘要树中引用的所有数据对象，并从中获得新的数据对象。</P><A name=N10374><B>清单 4. DMS 根据数据图更新后端数据源</B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
/**
 * Update the DMS's backend data to reflect changes
 * in the data graph.
 * Since this DMS has no actual backend data and therefore
 * has nothing to update, we will just navigate
 * the change summary and report (print) what's changed.
 */
public void update(DataGraph dataGraph)
{
  ChangeSummary changeSummary = dataGraph.getChangeSummary();
 
  // Call endLogging to summarize changes.
  // The DMS should call beginLogging() and endLogging(),
  // not the client.
  changeSummary.endLogging();
 
  // Use SDO ChangeSummary's getChangedDataObjects() method.
  List changes = changeSummary.getChangedDataObjects();
  for (Iterator iter = changes.iterator(); iter.hasNext();)
  {
    DataObject changedObject = (DataObject)iter.next();
    System.out.print("DMS updating " +
      changedObject.getString("name"));

    for (Iterator settingIter = changeSummary.getOldValues(
      changedObject).iterator(); settingIter.hasNext();)
    {
      ChangeSummary.Setting changeSetting =
        (ChangeSummary.Setting)settingIter.next();
      Property changedProperty = changeSetting.getProperty();
      Object oldValue = changeSetting.getValue();
      Object newValue = changedObject.get(changedProperty);

      System.out.print(" (changed: " + changedProperty.getName() +
        " from \"" + oldValue + "\" to \"" + newValue + "\")");
      // If not a simple example, we could update the backend here.
    }

    System.out.println();
  }
}
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>该例中根本没有后端更新。但在实际应用时，后端更新应该在这个方法中完成。</P>
<P>DMS 首先要对数据图的更新摘要调用 <CODE>endLogging()</CODE> ，从客户机取回数据图，以便进行后端更新。这样将关闭变更记录，从而提供自 <CODE>beginLogging()</CODE> 调用以来（通常在创建之后调用）对数据图所做修改的摘要。这种格式支持 DMS 高效、递增地更新后端数据源。变更摘要中的修改分为三种类型： </P>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI><B>对象变更</B>包含数据图中属性已经被修改的那些数据对象的引用、被修改的属性和修改之前的属性值。DMS 可以使用原来的属性值确保后端数据在此期间没有被别的人修改。 <BR><BR>
<LI><B>对象创建</B>包含添加到数据图中的数据对象。将这些对象表示了需要添加到后端数据结构中的新数据。 <BR><BR>
<LI><B>对象删除</B>包含从数据图中删除的数据对象。这些对象表示了需要从后端数据结构中删除的数据。 </LI></UL>
<P>注意，我们使用标准的 SDO API 检查数据图的变化，虽然也可以使用 EMF ChangeDescription API（而不是 SDO 的 ChangeSummary）。该例中仅仅更新简单的属性值，对性能的影响不是很明显。但在其他情况下，比方说要更新大量的属性，使用 EMF API 可以显著地提高性能。比如，假设要从数百个雇员的列表中删除一个雇员。在这种情况下，ChangeSummary 只能提供对原有数百个雇员列表中的原有值的访问。 而 EMF 的 ChangeDescription 接口还可以提供更具体的信息，如“删除某个索引位置的雇员”，这就有用得多。</P>
<P>还要注意的是，该变更摘要中只修改了一个对象，没有删除或者添加对象。如果使用 SDO 实现从数据图中删除对象，还要注意类型为 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">objectsToAttach</I> 的元素。该名称实际上是对象删除的 EMF ChangeDescription 名。这些元素是那些已经删除但是在回滚时需要放回图中的数据对象，这就是变更的 EMF 视图。总而言之， <CODE>objectsToAttach == deleted objects（删除的对象）</CODE> 。 </P>
<P><A name=N103B6><SPAN class=atitle2>调试应用程序</SPAN></A><BR>如果在示例应用程序中将 <CODE>debug</CODE> 变量设为 <CODE>true</CODE> ，那么就可以执行以下调用，查看数据图的序列化版本。 </P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
((EDataGraph) dataGraph).getDataGraphResource().save(System.out, null);
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>还可以使用 Eclipse 调试环境。比如，我们建议在 SDOClient.java 第 100 行设置一个断点，并调试 <CODE>SDOClient</CODE> （像在 Java 应用程序中那样）。然后，在调试窗口中就可以看到内存中的数据图（在 Variables 下）和它的数据对象（Boss、Terrence Shorter 等），如图 4 所示。 </P>
<P><A name=N103D4><B>图 4. 在调试模式下观察数据对象</B></A><BR><IMG height=762 alt=调试 src="http://www.ibm.com/developerworks/cn/java/j-sdo/Debugging1.jpg" width=600 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>还可以用这种方法查看变更摘要，如图 5 所示。</P>
<P><A name=N103E8><B>图 5. 在调试模式下观察变更摘要</B></A><BR><IMG height=643 alt=调试 src="http://www.ibm.com/developerworks/cn/java/j-sdo/Debugging2.jpg" width=600 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>上面的截屏图看起来很复杂，现在看来用处也不大，但是当您调试自己的 SDO 应用程序并查看数据对象和变更摘要的内容时，就会用到它。</P>
<P><A name=N103FA><SPAN class=atitle2>结束语</SPAN></A><BR>本文简要描述了 SDO 及其功能。我们通过一个示例应用程序说明了 SDO 的一些功能。更多参考信息，请参阅 Eclipse 帮助系统下的 SDO API 文档。该规范仍在发展和改进之中。比如，SDO 1.0 强调了 SDO 的客户机方面，而没有指定一个 DMS API。SDO 目前正通过 JCP 实现标准化，请关注有关的进展情况。因为 SDO 非常灵活，设计 SDO 应用程序时需要做很多决策。这些决策将影响程序的重用性和性能。因此，在编码之前，应该认真考虑应用模式和应用程序数据的特征。</P>
<P><A name=resources><SPAN class=atitle2>参考资料 </SPAN></A>
<UL>
<LI>您可以参阅本文在 developerWorks 全球站点上的 <A href="http://www.ibm.com/developerworks/java/library/j-sdo/" target=_blank xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">英文原文</A>。 <BR><BR>
<LI>单击本文上端或底端的 <B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">代码</B>图标，下载文中用到的源代码（或者参阅 <A href="http://kb.csdn.net/java/Articles/200509/adf06e7d-6585-4df5-b7be-f658302fed50.html#download" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">下载</A>部分）。 <BR><BR>
<LI><A href="http://www.ibm.com/developerworks/java/jdk/eclipse/index.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">IBM Development Package for Eclipse</A>将 Eclipse 与 IBM 最新的 Java 运行库（Linux 和 Windows 版）捆绑在一起。 <BR><BR>
<LI>IBM 的 SDO 1.0 参考实现和 Eclipse Modeling Framework (EMF) 被打包在一起。您可以在 <A href="http://www.eclipse.org/emf" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">EMF 主页</A>上找到一些文章、FAQ 和 新闻组。 <BR><BR>
<LI>参阅 <A href="http://www.ibm.com/developerworks/library/j-commonj-sdowmt/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">SDO 1.0</A>规范。 <BR><BR>
<LI>了解 JCP 网站上的 SDO 标准 <A href="http://www.jcp.org/en/jsr/detail?id=235" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">JSR-235</A>。 <BR><BR>
<LI>“ <A href="http://www.ibm.com/developerworks/db2/library/techarticle/dm-0407saracco/index.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Using Service Data Objects with Enterprise Information Integration technology</A>”（ <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">developerWorks</I>，2004 年 7 月）提供了使用 SDO 的一个例子。 <BR><BR>
<LI>“ <A href="http://www.ibm.com/developerworks/websphere/techjournal/0403_barcia/0403_barcia.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Creating JSF applications that access data using Web Data Objects</A>”（ <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">developerWorks</I>，2004 年 3 月）提供了另一个例子。 <BR><BR>
<LI>“ <A href="http://www.ibm.com/developerworks/edu/x-dw-xxpath-i.html?S_TACT=104AHW02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Get started with XPath</A>”（ <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">developerWorks</I>，2004 年 5 月）可以帮助您掌握 XPath。 <BR><BR>
<LI>F. Budinsky、D. Steinberg、E. Merks、R. Ellersick、T.J.Grose 合著的 <A href="http://devworks.krcinfo.com/WebForms/ProductDetails.aspx?ProductID=0131425420" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><I>Eclipse Modeling Framework</I> </A>(Addison-Wesley; 2003) 是关于 EMF 的完全参考。 <BR><BR>
<LI>在 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">developerWorks</I> <A href="http://kb.csdn.net/developerworks/cn/java/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Java 技术专区</A>中，可以找到关于 Java 编程方面的文章。 <BR><BR>
<LI><A href="http://devworks.krcinfo.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Developer Bookstore</A>提供了完备的技术书籍清单，其中包括数百本 <A href="http://devworks.krcinfo.com/WebForms/ProductList.aspx?Search=Category&amp;id=1200" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">与 Java 相关的主题</A>的书籍。 <BR></LI></UL>
<P></P><A name=download></A><SPAN class=atitle2>下载</SPAN><BR>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR vAlign=top>
<TD width=1 height=8><IMG height=8 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width=1 border=0></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR vAlign=top>
<TD class=lgray width=4 height=18><NBSP></NBSP></TD>
<TD class=lgray height=18><B>Name</B></TD>
<TD class=lgray width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD class=lgray width=4 height=18><NBSP></NBSP></TD>
<TD class=lgray height=18><B>Size</B></TD>
<TD class=lgray width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD class=lgray width=4 height=18><NBSP></NBSP></TD>
<TD class=lgray height=18><B>Download method</B></TD>
<TD class=lgray width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width=2 border=0></TD></TR>
<TR vAlign=top>
<TD width=4 height=18><NBSP></NBSP></TD>
<TD height=18>j-sdoSample.zip</TD>
<TD width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD width=4 height=18><NBSP></NBSP></TD>
<TD height=18></TD>
<TD width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD width=4 height=18><NBSP></NBSP></TD>
<TD noWrap height=18><A class=fbox href="ftp://www6.software.ibm.com/software/developer/library/j-sdoSample.zip"><B>FTP</B></A></TD>
<TD width=8 height=18><NBSP></NBSP></TD>
<TD width=2 height=18><IMG alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width=2 border=0></TD></TR>
<TR vAlign=top>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD width=2 height=1><IMG height=1 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD width=2 height=1><IMG height=1 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width=2 border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD class=lgray height=1><IMG height=1 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width="100%" border=0></TD>
<TD width=2 height=1><IMG height=1 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width=2 border=0></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR vAlign=top>
<TD><IMG height=12 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width=12 border=0></TD></TR>
<TR>
<TD><IMG height=11 alt=* src="http://www.ibm.com/developerworks/cn/i/fprtarrow.gif" width=12 border=0><A href="http://kb.csdn.net/developerworks/cn/whichmethod.html">关于下载方法的信息</A><BR><IMG height=30 alt="" src="http://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.comhttp://www.ibm.com//www.ibm.com/i/c.gif" width=10 border=0></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><A name=author1></A><SPAN class=atitle2>作者简介</SPAN><BR>Bertrand Portier 是 IBM 的软件开发人员，他是在 Eclipse.org 上开发 SDO 参考实现的 EMF 开发小组的主要成员。他拥有使用 J2EE 的丰富经验，曾经参与过 IBM 产品和 Web 服务领域的开发，并帮助 IBM 客户开发自己的分布式应用程序。 </TD></TR>
<TR>
<TD>
<P><A name=author2><BR></A>Frank Budinsky 是 Eclipse.org 的 Eclipse Modeling Framework 项目经理，参与了 EMF 框架的架构和实现，其中包括 SDO 的参考实现。他是 IBM Software Group 的工程师，有多年框架和生成器设计方面的经验。Frank 是权威的 EMF 参考书 <A href="http://devworks.krcinfo.com/WebForms/ProductDetails.aspx?ProductID=0131425420" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><I>Eclipse Modeling Framework, A Developer's Guide</I> </A>的主要作者。 </P></TD></TR></TBODY></TABLE></SPAN><BR><BR>原文地址:http://www-128.ibm.com/developerworks/cn/java/j-sdo/<BR><img src ="http://www.blogjava.net/hopeshared/aggbug/23901.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2005-12-14 16:51 <a href="http://www.blogjava.net/hopeshared/archive/2005/12/14/23901.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从扩展点中load class</title><link>http://www.blogjava.net/hopeshared/archive/2005/12/14/23862.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Wed, 14 Dec 2005 06:04:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2005/12/14/23862.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/23862.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2005/12/14/23862.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/23862.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/23862.html</trackback:ping><description><![CDATA[<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 好像利用Eclipse自定义扩展点的人不多。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在我以前做的项目中，用了自定义扩展点，但是使用这个扩展点的文件也在这个项目中，整个项目就是一个插件。所以，加载扩展点的方式很简单：<BR></P>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #008080">&nbsp;1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">IExtensionRegistry&nbsp;registry&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Platform.getExtensionRegistry();<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;2</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>IExtensionPoint&nbsp;point&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;registry.getExtensionPoint(“org.eclipse.ui.popupMenus”);<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;3</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>IExtension[]&nbsp;extensions&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;point.getExtensions();<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;4</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_236_578_Open_Image onclick="this.style.display='none'; Codehighlighter1_236_578_Open_Text.style.display='none'; Codehighlighter1_236_578_Closed_Image.style.display='inline'; Codehighlighter1_236_578_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_236_578_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_236_578_Closed_Text.style.display='none'; Codehighlighter1_236_578_Open_Image.style.display='inline'; Codehighlighter1_236_578_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;extensions.length;&nbsp;i</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN id=Codehighlighter1_236_578_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_236_578_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;5</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;IConfigurationElement[]&nbsp;elements&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;extensions.getConfigurationElements();<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;6</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_367_576_Open_Image onclick="this.style.display='none'; Codehighlighter1_367_576_Open_Text.style.display='none'; Codehighlighter1_367_576_Closed_Image.style.display='inline'; Codehighlighter1_367_576_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_367_576_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_367_576_Closed_Text.style.display='none'; Codehighlighter1_367_576_Open_Image.style.display='inline'; Codehighlighter1_367_576_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;j&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;&nbsp;j&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;elements.length;&nbsp;j</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">)</SPAN><SPAN id=Codehighlighter1_367_576_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_367_576_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;7</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;eleType&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;elements[j].getName();<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;8</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;importantClass&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Class.forName(element[j].getAttribute(MyConstants.ATTR_MODELCLASS)).newInstance();<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;9</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;……<BR></SPAN><SPAN style="COLOR: #008080">10</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">11</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在一个插件项目中，这样的代码一点问题都没有。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但是，我现在的项目分为几个插件，扩展点的定义放在了插件项目A中，相关的接口和扩展点实现收集器（这是我自己取的名字）也在A中，但是扩展点的实现是其他的插件，比如插件B就实现了A中定义的扩展点。那么他们之间的依赖关系是 <BR><BR>A&nbsp; &lt;----------&nbsp; B<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 换句话说，在A中看不到B中的代码，那么问题就来了：上面那段代码的第8行将会报出class not found的异常。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如何解决这个问题？<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可能是我对Eclipse的核心代码太不熟悉了，所以这个问题困扰了我很久。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 解决的方法是，将第8行替换为<BR><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">WorkbenchPlugin.createExtension(element,&nbsp;MyConstants.ATTR_MODELCLASS);</SPAN></DIV><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个方法将激活本次实现所在的插件项目的Bundle，问题就解决了。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src ="http://www.blogjava.net/hopeshared/aggbug/23862.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2005-12-14 14:04 <a href="http://www.blogjava.net/hopeshared/archive/2005/12/14/23862.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Eclipse中获取文件的几个方法</title><link>http://www.blogjava.net/hopeshared/archive/2005/12/13/23621.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Tue, 13 Dec 2005 03:51:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2005/12/13/23621.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/23621.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2005/12/13/23621.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/23621.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/23621.html</trackback:ping><description><![CDATA[<BR>在rcp中获取文件：<BR>
<P><SPAN class=tpc_content>&nbsp;&nbsp;&nbsp; 得到Appliaction workspace, Platform.asLocalURL(PRODUCT_BUNDLE.getEntry("")).getPath()).getAbsolutePath();<BR>&nbsp;&nbsp;&nbsp; 得到runtimeworkspace, Platform.getInstanceLocation().getURL().getPath();<BR><BR>通过EditorInput来得到工程的绝对路径：<BR><BR>&nbsp;&nbsp;&nbsp; ((IFileEditorInput)input).getFile().getLocation().makeAbsolute().toFile().getAbsoluteFile().getParentFile();<BR><BR>通过父EditPart得到编辑器的方法（GEF）：<BR><BR>&nbsp;&nbsp;&nbsp; IEditorPart editor = ((DefaultEditDomain)(parent.getViewer().getEditDomain())).getEditorPart();</SPAN></P><img src ="http://www.blogjava.net/hopeshared/aggbug/23621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2005-12-13 11:51 <a href="http://www.blogjava.net/hopeshared/archive/2005/12/13/23621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转:Eclipse插件FatJar安装与使用</title><link>http://www.blogjava.net/hopeshared/archive/2005/11/30/21902.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Wed, 30 Nov 2005 01:39:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2005/11/30/21902.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/21902.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2005/11/30/21902.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/21902.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/21902.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT color=#808080>由于工作需要,要做一个项目打包的功能. 原则上,项目打包应该写一个ant脚本,然后在代码中执行它,反正很复杂.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一个朋友推荐我用fatjar试试, 我上网搜到了这篇文章,转过来保存.</FONT><BR><BR><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 今天启动tomcat发现特别慢，得等1分多钟才启动完，这才想起来，我把WEB-INFO/lib/struts.jar , pager-tag.jar都删除了，取而代之的是他们的源码，tomcat启动的时候因为找不到jar文件就要重新编译，所以特别地慢。因此，我把struts.jar拷贝到WEB-INFO/lib下了，现在缺pager-tag.jar了。（其实pager-tag的源码编译不慢，主要是struts源码编译比较慢）我找了一下把程序打包的工具，其实eclipse自己带了一个export工具可以打包，你的项目=〉export=&gt;jar file=&gt;然后挨个选择你需要的包=〉写好目标jar文件名=〉写好目标目录=〉就生成新jar了。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其实这样已经能够满足我的要求了，查看Eclipse如何打包的过程中我发现有个fatjar插件功能更强些，可以把需要的资源打进一个jar里。所以下载了一个，下载地址：<A href="http://sourceforge.net/project/showfiles.php?group_id=115990&amp;package_id=125924" target=_blank>http://sourceforge.net/project/showfiles.php?group_id=115990&amp;package_id=125924</A> 解压缩后是一个.../plugins/(net...)把plugins下面的(net..)文件夹拷贝到eclipse的plugins下，重新启动Eclipse3.1,Windows=&gt;prefernce=&gt;fat jar preference看到他就说明已经安装成功了。如果没有看到，没有关系，删除D:\eclipse310\configuration\org.eclipse.update\platform.xml文件（此文件可以自动生成）不用担心以前的插件会因此而消失，没事。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 刚开始找不到如何使用它，后来看到你的项目=〉Export..=&gt;向导里有fat jar =&gt;使用起来真的很方便。<BR><BR>总结：<BR>一般把src打包export=&gt;Jar File 即可。<BR>想把src附属的资源一起打包，必须使用FatJar =&gt; export..=&gt;FatJar.<BR><BR><BR><FONT color=#deb887>原文引用通告地址： </FONT><A href="http://blog.csdn.net/srx/services/trackbacks/492760.aspx" target=_blank><FONT color=#deb887>http://blog.csdn.net/srx/services/trackbacks/492760.aspx</FONT></A><BR><img src ="http://www.blogjava.net/hopeshared/aggbug/21902.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2005-11-30 09:39 <a href="http://www.blogjava.net/hopeshared/archive/2005/11/30/21902.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>