<html> | |
<head> | |
<meta http-equiv=Content-Type content="text/html; charset=iso-8859-1"> | |
<meta name=Generator content="Microsoft Word 11 (filtered)"> | |
<title>Tutorial: Service and Provider</title> | |
<link rel=Stylesheet type="text/css" media=all href=technote.css> | |
<style> | |
<!-- | |
/* Style Definitions */ | |
p.MsoNormal, li.MsoNormal, div.MsoNormal | |
{margin:0in; | |
margin-bottom:.0001pt; | |
font-size:12.0pt; | |
font-family:"Times New Roman";} | |
h1 | |
{margin-right:0in; | |
margin-left:0in; | |
font-size:24.0pt; | |
font-family:"Times New Roman"; | |
font-weight:bold;} | |
h2 | |
{margin-right:0in; | |
margin-left:0in; | |
font-size:18.0pt; | |
font-family:"Times New Roman"; | |
font-weight:bold;} | |
h3 | |
{margin-right:0in; | |
margin-left:0in; | |
font-size:13.5pt; | |
font-family:"Times New Roman"; | |
font-style:italic;} | |
p.MsoCaption, li.MsoCaption, div.MsoCaption | |
{margin-top:6.0pt; | |
margin-right:0in; | |
margin-bottom:6.0pt; | |
margin-left:0in; | |
font-size:10.0pt; | |
font-family:"Times New Roman"; | |
font-weight:bold;} | |
a:link, span.MsoHyperlink | |
{color:blue; | |
text-decoration:underline;} | |
a:visited, span.MsoHyperlinkFollowed | |
{color:blue; | |
text-decoration:underline;} | |
p | |
{margin-right:0in; | |
font-size:12.0pt; | |
font-family:"Times New Roman";} | |
code | |
{font-family:"Courier New";} | |
pre | |
{margin-top:0in; | |
margin-right:0in; | |
margin-bottom:0in; | |
margin-left:24.0pt; | |
margin-bottom:.0001pt; | |
font-size:10.0pt; | |
font-family:"Courier New";} | |
p.notabene, li.notabene, div.notabene | |
{margin-right:48.0pt; | |
margin-left:48.0pt; | |
border:none; | |
padding:0in; | |
font-size:12.0pt; | |
font-family:"Times New Roman";} | |
p.question, li.question, div.question | |
{margin-right:48.0pt; | |
margin-left:48.0pt; | |
font-size:12.0pt; | |
font-family:"Times New Roman"; | |
font-style:italic;} | |
p.backto, li.backto, div.backto | |
{margin-right:0in; | |
margin-left:0in; | |
font-size:12.0pt; | |
font-family:"Times New Roman";} | |
@page Section1 | |
{size:8.5in 11.0in; | |
margin:1.0in 1.25in 1.0in 1.25in;} | |
div.Section1 | |
{page:Section1;} | |
/* List Definitions */ | |
ol | |
{margin-bottom:0in;} | |
ul | |
{margin-bottom:0in;} | |
--> | |
</style> | |
</head> | |
<body lang=EN-US link=blue vlink=blue> | |
<div class=Section1> | |
<p class=MsoNormal><a name=top></a><img width=347 height=134 src="../logo.gif" | |
border=0></p> | |
<h1 align=center style='text-align:center'>Tutorial: Service and Provider</h1> | |
<table class=MsoNormalTable border=0 cellspacing=8 cellpadding=0 | |
style='margin-left:24.0pt'> | |
<tr> | |
<td style='padding:.75pt .75pt .75pt .75pt'> | |
<p class=MsoNormal>Version: 0.1</p> | |
</td> | |
<td style='padding:.75pt .75pt .75pt .75pt'> | |
<p class=MsoNormal>Date: April 29, 2005</p> | |
</td> | |
</tr> | |
</table> | |
<h2>Contents</h2> | |
<p class=MsoNormal style='margin-left:48.0pt;text-indent:-.25in'><span | |
style='font-size:10.0pt;font-family:Symbol'>·<span style='font:7.0pt "Times New Roman"'> | |
</span></span><a href="#_Overview">Overview</a></p> | |
<p class=MsoNormal style='margin-left:48.0pt;text-indent:-.25in'><span | |
style='font-size:10.0pt;font-family:Symbol'>·<span style='font:7.0pt "Times New Roman"'> | |
</span></span><a href="#refs">References</a></p> | |
<p class=MsoNormal style='margin-left:48.0pt;text-indent:-.25in'><span | |
style='font-size:10.0pt;font-family:Symbol'>·<span style='font:7.0pt "Times New Roman"'> | |
</span></span><a href="#trace">Introduction</a></p> | |
<p class=MsoNormal style='margin-left:48.0pt;text-indent:-.25in'><span | |
style='font-size:10.0pt;font-family:Symbol'>·<span style='font:7.0pt "Times New Roman"'> | |
</span></span><a href="#reqs">Creating the Widget Service</a></p> | |
<p class=MsoNormal style='margin-left:48.0pt;text-indent:-.25in'><span | |
style='font-size:10.0pt;font-family:Symbol'>·<span style='font:7.0pt "Times New Roman"'> | |
</span></span><a href="#constraints">Creating the Widget Providers</a></p> | |
<p class=MsoNormal style='margin-left:48.0pt;text-indent:-.25in'><span | |
style='font-size:10.0pt;font-family:Symbol'>·<span style='font:7.0pt "Times New Roman"'> | |
</span></span><a href="#_Provider_Priorities">Provider Priorities</a></p> | |
<p class=MsoNormal style='margin-left:48.0pt;text-indent:-.25in'><span | |
style='font-size:10.0pt;font-family:Symbol'>·<span style='font:7.0pt "Times New Roman"'> | |
</span></span><a href="#_Execution_Strategies">Execution Strategies</a></p> | |
<p class=MsoNormal style='margin-left:48.0pt;text-indent:-.25in'><span | |
style='font-size:10.0pt;font-family:Symbol'>·<span style='font:7.0pt "Times New Roman"'> | |
</span></span><a href="#_Example">The Client</a></p> | |
<p class=MsoNormal style='margin-left:48.0pt;text-indent:-.25in'><span | |
style='font-size:10.0pt;font-family:Symbol'>·<span style='font:7.0pt "Times New Roman"'> | |
</span></span><a href="#models">Summary</a></p> | |
<div class=MsoNormal align=center style='text-align:center'> | |
<hr size=2 width="100%" align=center> | |
</div> | |
<h2><a name=intro></a><a name="_Overview"></a>Overview</h2> | |
<p class=backto><span style='font-size:10.0pt'>[<a href="#top">back to top</a>]</span></p> | |
<p>The GMF Service Provider infrastructure provides a framework for building | |
Services for clients to execute a unit of work. The Service depends on | |
Providers who actually perform the work on behalf of the Service. Providers | |
have a Priority and an optional Policy which dictate how the Service will determine | |
which Provider(s) to use when executing a request on behalf of a client.<a | |
name=refs></a> The Service may be optimized in some capacity.</p> | |
<h2>References</h2> | |
<p class=backto><span style='font-size:10.0pt'>[<a href="#top">back to top</a>]</span></p> | |
<p>This tutorial assumes the reader is familiar with Eclipse extension point architecture. | |
There is an abundance of on-line help in Eclipse for those unfamiliar with | |
extension points. For reference, the full source for this tutorial is | |
available <a href="service_provider_src.zip">here</a>.</p> | |
<h2><a name=trace></a>Introduction</h2> | |
<p class=backto><span style='font-size:10.0pt'>[<a href="#top">back to top</a>]</span></p> | |
<p>To demonstrate the Provider Service we will create a simple example Widget | |
Service and two Widget Provider. Then we will create a client to uses the | |
Widget Service to create Widgets. This tutorial requires only the | |
org.eclipse.gmf.runtime.common.core plugins and its dependencies to run.</p> | |
<h2><a name=reqs></a>Creating the Widget Service</h2> | |
<p class=backto><span style='font-size:10.0pt'>[<a href="#top">back to top</a>]</span></p> | |
<p>The first step in creating a Widget Service is defining the API for your | |
Widget Providers. This is done using a Java interfaces. The Service Provider | |
infrastructure defines an <code><span style='font-size:10.0pt'>IProvider</span></code> | |
interface that is used to define the base interface for clients. This interface | |
provides the call-backs to Providers via the <code><span style='font-size:10.0pt'>provides(IOperation) | |
</span></code>method. <code><span style='font-size:10.0pt'>IProvider</span></code> | |
also provides a mechanism for Providers to receive provider change events from | |
the Service. It is expected that new Providers extend this interface for their | |
own purposes. In order to keep this tutorial simple, the Providers created in | |
this tutorial do not listen to provider changes.</p> | |
<p>To support the creation of Widgets, we will create IWidgetProvider. The | |
IWidgetProvider extends the IProvider interface and also defines the | |
createWidget() method where Providers carry-out the actual work of creating | |
widgets when asked by the WidgetService. </p> | |
<div style='margin-left:24.0pt'> | |
<div style='border:solid windowtext 1.0pt;padding:4.0pt 4.0pt 4.0pt 4.0pt'><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'>public interface IWidgetProvider</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> extends IProvider {</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> </span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> Object createWidget(int orderSize); </span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> </span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'>}</span><span | |
Times New></pre></div> | |
</div> | |
<p></span> Next, create the actual WidgetService. This is done by extending | |
the abstract base class Service and implementing IWidgetProvider. Take a | |
minute to read the code before we go through it in more detail.</p> | |
<div style='margin-left:24.0pt'> | |
<div style='border:solid windowtext 1.0pt;padding:4.0pt 4.0pt 4.0pt 4.0pt'><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'>public class WidgetService</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> extends Service</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> implements IWidgetProvider {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> private final static WidgetService service = new WidgetService();</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> public static WidgetService getInstance() {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return service;</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> }</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> public Object createWidget(int orderSize) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return execute(new CreateWidgetOperation(orderSize));</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> } </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> public Object execute(IOperation operation) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> List results = execute(ExecutionStrategy.FIRST, operation);</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return results.isEmpty() ? null : results;</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> }</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> protected Service.ProviderDescriptor newProviderDescriptor(IConfigurationElement element) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return new WidgetProviderDescriptor(element);</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> } </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> protected static class WidgetProviderDescriptor</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> extends Service.ProviderDescriptor {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> private WidgetServiceProviderConfiguration providerConfiguration;</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> public WidgetProviderDescriptor(IConfigurationElement element) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> super(element);</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> this.providerConfiguration =</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> WidgetServiceProviderConfiguration.parse(element);</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> assert null != element : "NULL configuration element"; //$NON-NLS-1$</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> }</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> public boolean provides(IOperation operation) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> if (getPolicy() != null)</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return getPolicy().provides(operation);</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> if (provider == null) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> if (isSupportedInExtension(operation)) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> providerConfiguration = null;</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return getProvider().provides(operation);</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> }</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return false;</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> }</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return getProvider().provides(operation);</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> }</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> private boolean isSupportedInExtention(IOperation operation) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> if (operation instanceof CreateWidgetOperation) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return providerConfiguration.supports(((CreateWidgetOperation)operation).getOrderSize());</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> }</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return false;</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> }</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> } </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'>}</span></code></pre></div> | |
</div> | |
<p>First, notice that the WidgetService is a static instance. This is needed | |
to support the initialization of the Widget Providers, we will get to that in | |
more detail in a minute.</p> | |
<p>Next, notice that the WidgetService implements IWidgetProvider by delegating | |
the service request to the actual Service. This is done by calling the | |
Service’s execute(ExecutionStrategy, IOperation) method. Again, | |
don’t worry about the understanding the ExecutionStrategy, we explain the | |
ExecutionStrategies that later. At this point the Service will find Providers | |
for the given IOperation and delegate the work required in the IOperation to | |
them. Then return the results for the work done by the Providers back to the | |
client.</p> | |
<p>Now back to the Provider initialization. In order to know about potential | |
Providers for a given IOperation, the Service will find them by examining all | |
the extensions of widgetProvider extension-point. These widgetProviders are | |
registered with the Service as WidgetProviderDescriptors. Which are used by | |
the service to determine if a particular Provider provides for the operation | |
via provides(IOperation). Since the providers are registered this way we | |
don’t have to worry about a plugin not being loaded in order to | |
contribute to the Service. The service will load the Provider’s | |
corresponding plugin when required.</p> | |
<p>Registration of the Providers is done in the startup() method of the | |
WidgetService’s corresponding xxPlugin.java. The following code fragment | |
shows the mechanics of the static initialization of Providers.</p> | |
<div style='margin-left:24.0pt'> | |
<div style='border:solid windowtext 1.0pt;padding:4.0pt 4.0pt 4.0pt 4.0pt'><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> public static final String WIDGET_SERVICE_EXTENSION_POINT = “widgetProviders”;</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> </span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> public void startup() {</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> super.startup();</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> configureWidgetProviders();</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> }</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> </span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> public void configureWidgetProviders() {</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> WidgetService.getInstance().configureProviders(</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> Platform.getExtensionRegistry().getExtensionPoint(getPluginId(),</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> WIDGET_SERVICE_EXTENSION_POINT).getConfigurationElements()); </span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'> } </pre></div> | |
</div> | |
<p>Finally, define the “widgetProviders” extension-point for | |
Providers to extend in the plugin.xml.</p> | |
<div style='margin-left:24.0pt'> | |
<div style='border:solid windowtext 1.0pt;padding:4.0pt 4.0pt 4.0pt 4.0pt'><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'><extension-point id="widgetProviders" name="%extPoint.widgetProviders" schema="schema/widgetProviders.exsd"/></span></code></pre></div> | |
</div> | |
<p style='margin-left:0in'> </p> | |
<h2><a name=constraints></a>Creating the Providers</h2> | |
<p class=backto><span style='font-size:10.0pt'>[<a href="#top">back to top</a>]</span></p> | |
<p>Now we create the Providers that actually carry-out the requests on behalf | |
of the Service. The first step in creating a Provider is to create an | |
extension of the widgetProvider extension-point for the WidgetProvider. In the | |
extension, you also define what type of request the Provider can handle and the | |
Priority of the Provider. For our WidgetProvider, we have a low Priority | |
Provider that supports widget order sizes between 50 and 5000 widgets.</p> | |
<div style='margin-left:24.0pt'> | |
<div style='border:solid windowtext 1.0pt;padding:4.0pt 4.0pt 4.0pt 4.0pt'><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> <extension point="org.eclipse.gmf.examples.runtime.common.service.widgetProviders"></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> <widgetProvider class="org.eclipse.gmf.examples.runtime.common.service.providers.WidgetProvider"></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> <Priority name="Low"/></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> <orderSize max="5000" min="50"/></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> </widgetProvider></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> </extension></span></pre></div> | |
</div> | |
<p>Next we implement WidgetProvider.java as follows. The key point here is to | |
ensure that your XML based configuration matches the Provider itself. In this | |
case we are concerned with matching the order size.</p> | |
<div style='margin-left:24.0pt'> | |
<div style='border:solid windowtext 1.0pt;padding:4.0pt 4.0pt 4.0pt 4.0pt'><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> public boolean provides(IOperation operation) {</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> if (operation instanceof CreateWidgetOperation) {</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> int orderSize = ((CreateWidgetOperation)operation).getOrderSize();</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> return (orderSize >= 100 && orderSize <= 10000);</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> }</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> return false;</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> }</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> </span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> public Object createWidget(int orderSize) {</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> List widgets = new ArrayList(orderSize);</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> for (int i = 0; i < orderSize; i++) {</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> widgets.add(I, “widget”);</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> }</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> return widgets;</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> }</span></pre></div> | |
</div> | |
<p>To create the second provider follow the same steps are the first. However, | |
there are a few subtle differences. Change the Provider priority from Low to | |
High and change the order size to 100 <= order size <= 10000.</p> | |
<div style='margin-left:24.0pt'> | |
<div style='border:solid windowtext 1.0pt;padding:4.0pt 4.0pt 4.0pt 4.0pt'><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> <extension point="org.eclipse.gmf.examples.runtime.common.service.widgetProviders"></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> <widgetProvider class="org.eclipse.gmf.examples.runtime.common.service.providers.SuperWidgetProvider"></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> <Priority name="High"/></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> <orderSize max="10000" min="100"/> </span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> </widgetProvider> </span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> </extension> </span></pre></div> | |
</div> | |
<p>Again, create SuperWidgetProvider by implementing IWidgetProvider.</p> | |
<div style='margin-left:24.0pt'> | |
<div style='border:solid windowtext 1.0pt;padding:4.0pt 4.0pt 4.0pt 4.0pt'><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> public boolean provides(IOperation operation) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> if (operation instanceof CreateWidgetOperation) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> int orderSize = ((CreateWidgetOperation)operation).getOrderSize();</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return (orderSize >= 50 && orderSize <= 5000);</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> }</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return false;</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> }</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> public Object createWidget(int orderSize) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> List widgets = new ArrayList(orderSize);</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> for (int i = 0; I < orderSize; i++) {</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> widgets.add(i, “widget”);</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> }</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> return widgets;</span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> </span></code></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><code><span style='color:navy'> }</span></code></pre></div> | |
</div> | |
<h2><a name="_Provider_Priorities"></a>Provider Priorities</h2> | |
<p>[<a href="#top"><span style='font-size:10.0pt'>back to top</span></a>]</p> | |
<p>Provider Priorities are closely tied to ExecutionStrategies (described in | |
the next section). For now know that a Provider must have a Priority and that | |
Priority assigns an importance to the Provider. The following Priorities are | |
defined by GMF.</p> | |
<div style='margin-left:24.0pt'> | |
<div style='border:solid windowtext 1.0pt;padding:4.0pt 4.0pt 4.0pt 4.0pt'><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='font-size:12.0pt; | |
color:navy'> ProviderPriority.HIGHEST</span></pre><pre style='margin-left: | |
0in;border:none;padding:0in'><span style='font-size:12.0pt;color:navy'> ProviderPriority.HIGH</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='font-size:12.0pt; | |
color:navy'> ProviderPriority.MEDIUM</span></pre><pre style='margin-left: | |
0in;border:none;padding:0in'><span style='font-size:12.0pt;color:navy'> ProviderPriority.LOW</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='font-size:12.0pt; | |
color:navy'> ProviderPriority.LOWEST</span></pre></div> | |
</div> | |
<h2><a name="_Execution_Strategies"></a>Execution Strategies</h2> | |
<p>[<a href="#top"><span style='font-size:10.0pt'>back to top</span></a>]</p> | |
<p>When collecting Providers for a given IOperation the Service can be | |
instructed to find the Providers in a well-defined way. <span REF _Ref102967140>Table | |
1 Execution Strategies</span> below defines that ways in which the Service | |
finds Providers to carryout the unit of work.</p> | |
<div align=center> | |
<table class=MsoTableGrid border=1 cellspacing=0 cellpadding=0 | |
style='margin-left:30.2pt;border-collapse:collapse;border:none'> | |
<tr> | |
<td width=295 valign=top style='width:221.4pt;border:solid windowtext 1.0pt; | |
padding:0in 5.4pt 0in 5.4pt'> | |
<p style='margin-left:0in'><b>Strategy</b></p> | |
</td> | |
<td width=295 valign=top style='width:221.4pt;border:solid windowtext 1.0pt; | |
border-left:none;padding:0in 5.4pt 0in 5.4pt'> | |
<p style='margin-left:0in'><b>Description</b></p> | |
</td> | |
</tr> | |
<tr> | |
<td width=295 valign=top style='width:221.4pt;border:solid windowtext 1.0pt; | |
border-top:none;padding:0in 5.4pt 0in 5.4pt'><pre><span style='font-size: | |
12.0pt'>ExecutionStrategy.FIRST</span></pre></td> | |
<td width=295 valign=top style='width:221.4pt;border-top:none;border-left: | |
none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; | |
padding:0in 5.4pt 0in 5.4pt'> | |
<p style='margin-left:0in'>The Service will select the first Provider with | |
the highest Priority that is capable of the service request.</p> | |
</td> | |
</tr> | |
<tr> | |
<td width=295 valign=top style='width:221.4pt;border:solid windowtext 1.0pt; | |
border-top:none;padding:0in 5.4pt 0in 5.4pt'><pre><span style='font-size: | |
12.0pt'>ExecutionStrategy.LAST</span></pre></td> | |
<td width=295 valign=top style='width:221.4pt;border-top:none;border-left: | |
none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; | |
padding:0in 5.4pt 0in 5.4pt'> | |
<p style='margin-left:0in'>The Service will use the last Provider with the | |
lowest Priority that is capable of the service request.</p> | |
</td> | |
</tr> | |
<tr> | |
<td width=295 valign=top style='width:221.4pt;border:solid windowtext 1.0pt; | |
border-top:none;padding:0in 5.4pt 0in 5.4pt'><pre><span style='font-size: | |
12.0pt'>ExecutionStrategy.FORWARD</span></pre></td> | |
<td width=295 valign=top style='width:221.4pt;border-top:none;border-left: | |
none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; | |
padding:0in 5.4pt 0in 5.4pt'> | |
<p style='margin-left:0in'>The Services will use all the Providers in order | |
of highest Priority to the lowest that are capable of providing the service request. | |
The results from the Providers are placed in a List that matches the relative | |
descending order of the Provider priorities.</p> | |
</td> | |
</tr> | |
<tr> | |
<td width=295 valign=top style='width:221.4pt;border:solid windowtext 1.0pt; | |
border-top:none;padding:0in 5.4pt 0in 5.4pt'><pre><span style='font-size: | |
12.0pt'>ExecutionStrategy.REVERSE</span></pre></td> | |
<td width=295 valign=top style='width:221.4pt;border-top:none;border-left: | |
none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; | |
padding:0in 5.4pt 0in 5.4pt'> | |
<p style='margin-left:0in'>The Service will use all the Providers in order of | |
lowest Priority to the highest that are capable of providing the service | |
request. The results from the Providers are placed in a List that matches | |
the relative ascending order of the Provider priorities.</p> | |
</td> | |
</tr> | |
</table> | |
</div> | |
<p class=MsoCaption align=center style='text-align:center'><a | |
name="_Ref102967140">Table </a>1 Execution Strategies</p> | |
<h2><a name="_Example"></a>The Client</h2> | |
<p>[<a href="#top"><span style='font-size:10.0pt'>back to top</span></a>]</p> | |
<p>To use the WidgetService we’ll simply create a client in the form of a | |
Workbench action. Add the following to the plugin.xml.</p> | |
<div style='margin-left:24.0pt'> | |
<div style='border:solid windowtext 1.0pt;padding:4.0pt 4.0pt 4.0pt 4.0pt'><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> <extension point="org.eclipse.ui.actionSets"></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> <actionSet </span></pre><pre style='margin-left: | |
0in;border:none;padding:0in'><span style='color:navy;background:white'> label="Widget Serice ActionSet"</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> visible="true"</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> id="org.eclipse.gmf.examples.runtime.common.service.client.actionSet"></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> <menu id="org.eclipse.gmf.examples.runtime.menu"</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> label="Widget Service"</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> path="additions"></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> <separator name="group1"/></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> </menu></span></pre><pre style='margin-left: | |
0in;border:none;padding:0in'><span style='color:navy;background:white'> <action id="org.eclipse.gmf.examples.runtime.common.service.client.RunExampleAction"</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> label="Run Widget Example"</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> menubarPath="org.eclipse.gmf.examples.runtime.menu/group1"</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> class="org.eclipse.gmf.examples.runtime.common.service.client.RunExampleAction"></span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> </action> </span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'> </actionSet></span></pre><pre style='margin-left: | |
0in;border:none;padding:0in'><span style='color:navy;background:white'> </extension></span></pre></div> | |
</div> | |
<p>Next, implement the <span style='background:white'>RunExampleAction</span>’s | |
run() method with the following code snipet.</p> | |
<div style='margin-left:24.0pt'> | |
<div style='border:solid windowtext 1.0pt;padding:4.0pt 4.0pt 4.0pt 4.0pt'><pre | |
style='margin-left:0in;border:none;padding:0in'> public void run(IAction action) {</pre><pre | |
style='margin-left:0in;border:none;padding:0in'> Object widgets = WidgetService.getInstance().createWidget(1000);</pre><pre | |
style='margin-left:0in;border:none;padding:0in'> System.out.println(widgets == null ? "No widgets created" : "Created " + ((Object[])widgets).length + " widgets");//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$</pre><pre | |
style='margin-left:0in;border:none;padding:0in'> widgets = WidgetService.getInstance().createWidget(30);</pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy'> System.out.println(widgets == null ? "No widgets created" : "Created " + ((Object[])widgets).length + " widgets");//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'> widgets = WidgetService.getInstance().createWidget(76);</pre><pre | |
style='margin-left:0in;border:none;padding:0in'> System.out.println(widgets == null ? "No widgets created" : "Created " + ((Object[])widgets).length + " widgets");//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$</pre><pre | |
style='margin-left:0in;border:none;padding:0in'> </pre><pre | |
style='margin-left:0in;border:none;padding:0in'> }</pre></div> | |
</div> | |
<p>Run the workbench and execution the “Run Widget Action”. You | |
should see following in the Console view. Not very exciting, but enough to | |
demonstrate the Service Provider infrastructure. In all cases the | |
ExecutionStrategy.FIRST is used. The first client request for a 1000 widgets | |
is provided by SuperWidgetProvider since is has a higher Priority than the | |
WidgetProvider and it is capable of handling the order size. In the second | |
client request, no widgets were created since neither of the widgetProvider | |
handles the order size. Lastly, the small order is provided by the | |
WidgetProvider since the SuperWidgetProvider does not handle order smaller than | |
100 widgets.</p> | |
<div style='margin-left:24.0pt'> | |
<div style='border:solid windowtext 1.0pt;padding:4.0pt 4.0pt 4.0pt 4.0pt'><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'>Created 1000 widgets</span></pre><pre style='margin-left: | |
0in;border:none;padding:0in'><span style='color:navy;background:white'>No widgets created</span></pre><pre | |
style='margin-left:0in;border:none;padding:0in'><span style='color:navy; | |
background:white'>Created 76 widgets</span></pre></div> | |
</div> | |
<p>As a simple exercise change the ExecutionStrategy used by the WidgetService | |
to see the behavior change. You can also change the order sizes and Priority | |
of the Providers.</p> | |
<div class=MsoNormal align=center style='text-align:center'> | |
<hr size=2 width="100%" align=center> | |
</div> | |
<h2><a name=principles></a><a name=examples></a><a name=models></a><a name=api></a>Summary</h2> | |
<p><span style='font-size:10.0pt'>[<a href="#top">back to top</a>]</span></p> | |
<p>To create and demonstrate the Service Provider Infrastructure we:</p> | |
<p style='margin-left:1.0in;text-indent:-.25in'>1.<span style='font:7.0pt "Times New Roman"'> | |
</span>Defined the IWidgetProvider interface by extending the base IProvider | |
interface,</p> | |
<p style='margin-left:1.0in;text-indent:-.25in'>2.<span style='font:7.0pt "Times New Roman"'> | |
</span>Created the WidgetService by extending Service and implementing | |
IWidgetProvider,</p> | |
<p style='margin-left:1.0in;text-indent:-.25in'>3.<span style='font:7.0pt "Times New Roman"'> | |
</span>Create the WidgetDescriptor to load the WidgetProvider’s XML | |
descriptors,</p> | |
<p style='margin-left:1.0in;text-indent:-.25in'>4.<span style='font:7.0pt "Times New Roman"'> | |
</span>Created the widgetProvider extension-point,</p> | |
<p style='margin-left:1.0in;text-indent:-.25in'>5.<span style='font:7.0pt "Times New Roman"'> | |
</span>Add the widgetProvider extensions to the plugin.xml,</p> | |
<p style='margin-left:1.0in;text-indent:-.25in'>6.<span style='font:7.0pt "Times New Roman"'> | |
</span>Created a widget Provider by implementing IWidgetProvider, and </p> | |
<p style='margin-left:1.0in;text-indent:-.25in'>7.<span style='font:7.0pt "Times New Roman"'> | |
</span>Finally, created a simple client to use the Widget Service. </p> | |
<div class=MsoNormal align=center style='text-align:center'> | |
<hr size=2 width="100%" align=center> | |
</div> | |
<p class=MsoNormal style='margin-bottom:12.0pt'> </p> | |
<div class=MsoNormal align=center style='text-align:center'> | |
<hr size=2 width="100%" align=center> | |
</div> | |
<p><a href="http://www.eclipse.org/legal/epl-v10.html">Copyright (c) 2000,2005 | |
IBM Corporation and others. All Rights Reserved.</a></p> | |
</hr/></br/></br/></div> | |
</body> | |
</html> |