Lines 15-22
Link Here
|
15 |
|
15 |
|
16 |
<table border="0" cellspacing="8" cellpadding="0"> |
16 |
<table border="0" cellspacing="8" cellpadding="0"> |
17 |
<tr> |
17 |
<tr> |
18 |
<td>Version: 0.1</td> |
18 |
<td>Version: 0.2</td> |
19 |
<td>Date: June 08, 2005</td> |
19 |
<td>Date: Dec. 28, 2005</td> |
|
|
20 |
<!-- Removed references to the Logical Resource API --> |
20 |
</tr> |
21 |
</tr> |
21 |
</table> |
22 |
</table> |
22 |
|
23 |
|
Lines 28-34
Link Here
|
28 |
<li><a href="#intro">Introduction</a></li> |
29 |
<li><a href="#intro">Introduction</a></li> |
29 |
<li><a href="#editing_domain">Creating and Using an MSL Editing Domain</a></li> |
30 |
<li><a href="#editing_domain">Creating and Using an MSL Editing Domain</a></li> |
30 |
<li><a href="#making_changes">Making Changes to Resources</a></li> |
31 |
<li><a href="#making_changes">Making Changes to Resources</a></li> |
31 |
<li><a href="#logical">Working with Logical Resources</a></li> |
|
|
32 |
<li><a href="#listeners">MSL Listeners</a></li> |
32 |
<li><a href="#listeners">MSL Listeners</a></li> |
33 |
<li><a href="#validation">Model Validation</a></li> |
33 |
<li><a href="#validation">Model Validation</a></li> |
34 |
<li><a href="#copy_paste">MSL Copy and Paste Support</a></li> |
34 |
<li><a href="#copy_paste">MSL Copy and Paste Support</a></li> |
Lines 44-50
Link Here
|
44 |
<p class="backto"><font size="-1">[<a href="#top">back to top</a>]</font></p> |
44 |
<p class="backto"><font size="-1">[<a href="#top">back to top</a>]</font></p> |
45 |
|
45 |
|
46 |
<p> |
46 |
<p> |
47 |
The Model Service Layer(MSL) provides a number of facilities to ease model management: |
47 |
The Model Service Layer (MSL) provides a number of facilities to ease model management: |
48 |
model modification semantics, uniform resource creation and loading, uniform listener |
48 |
model modification semantics, uniform resource creation and loading, uniform listener |
49 |
registration, batching of notifications, live validation with automatic modification |
49 |
registration, batching of notifications, live validation with automatic modification |
50 |
abandonment, copy/paste support, automated pathmap support and additional metamodel support. |
50 |
abandonment, copy/paste support, automated pathmap support and additional metamodel support. |
Lines 203-392
Link Here
|
203 |
editingDomain.saveResource(r1); |
203 |
editingDomain.saveResource(r1); |
204 |
</pre> |
204 |
</pre> |
205 |
|
205 |
|
206 |
<h2><a name="logical"></a>Working with Logical Resources</h2> |
|
|
207 |
|
208 |
<p class="backto"><font size="-1">[<a href="#top">back to top</a>]</font></p> |
209 |
|
210 |
<p> |
211 |
The MSL's default resource implementation conforms to the |
212 |
<a href="../../reference/api/common/org/eclipse/gmf/runtime/emf/core/resources/ILogicalResource.html"><code>ILogicalResource</code></a> |
213 |
interface. This resource creates an in-memory logical view of an EMF tree |
214 |
(or forest) structure that is persisted in multiple physical resources, all of |
215 |
which are XMI-compliant. The central concept in the logical-to-physical mapping |
216 |
of an MSL resource is the "separate" element. A separate elements is persisted |
217 |
in a different, or separate, physical resource than its container. |
218 |
</p><p> |
219 |
To obtain a logical resource, use the editing domain to create a resource as |
220 |
described <a href="#create_resource">above</a> and then get a view of it as |
221 |
an <code>ILogicalResource</code>. |
222 |
To store a model element in its own physical resource, just ask the logical |
223 |
resource to separate it into a new resource on a URI of your choosing. Don't |
224 |
forget to ask first whether it <i>can</i> be separated (the metamodel may |
225 |
implement rules restricting what can be separated; see below): |
226 |
</p> |
227 |
<pre class="snippet"> |
228 |
Resource r1 = |
229 |
editingDomain.createResource("file://c:/eclipse/workspace/aProject/test.rmplibrary", |
230 |
RMPLibraryPackage.eINSTANCE.getLibrary()); |
231 |
ILogicalResource logical = editingDomain.asLogicalResource(r1); |
232 |
|
233 |
// ... fill the resource with contents |
234 |
|
235 |
EObject element = // ... find an element to be separated |
236 |
|
237 |
if (logical.canSeparate(element)) { |
238 |
try { |
239 |
logical.separate( |
240 |
element, |
241 |
URI.createURI("file://c:/eclipse/workspace/aProject/test.sub1.rmplibrary")); |
242 |
} catch (CannotSeparateException e) { |
243 |
System.out.println("Could not separate the element: " + element); |
244 |
e.printStackTrace(); |
245 |
} |
246 |
} |
247 |
|
248 |
editingDomain.saveResource(logical); // or logical.save(Collections.EMPTY_MAP); |
249 |
</pre> |
250 |
<p> |
251 |
We now have one logical resource stored in two files. |
252 |
</p><p> |
253 |
Note the use of the <code>ILogicalResource MEditingDomain.asLogicalResource(Resource)</code> |
254 |
method to obtain a view of an arbitrary resource as a logical resource. This is |
255 |
necessary because the editing domain might actually instantiate any resource |
256 |
implementation, not necessarily a logical resource, depending on the registered |
257 |
resource factories. If the resource is not actually a logical resource, then |
258 |
this method creates a wrapper that provides compatibility with the logical |
259 |
resource API. |
260 |
</p><p> |
261 |
In the snippet above, we catch <code>CannotSeparateException</code> despite |
262 |
being informed that the separation would be permitted because there may be |
263 |
unexpected conditions that prevent the separation from succeeding (such as |
264 |
incorrect file permissions). No attempt is made to actually persist the new |
265 |
physical resource until the logical resource is saved, but a metamodel extension |
266 |
might be proactive in checking even at this point whether certain I/O limitations |
267 |
would be exceeded. |
268 |
</p><p> |
269 |
To do the inverse of a separation operation, we can <i>absorb</i> an element |
270 |
from a separate resource into the same resource as its container: |
271 |
</p> |
272 |
|
273 |
<pre class="snippet"> |
274 |
if (logical.isSeparate(element)) { |
275 |
try { |
276 |
logical.absorb(element); |
277 |
} catch (CannotAbsorbException e) { |
278 |
System.out.println("Could not absorb the element: " + element); |
279 |
e.printStackTrace(); |
280 |
} |
281 |
} |
282 |
|
283 |
editingDomain.saveResource(logical); |
284 |
</pre> |
285 |
<p> |
286 |
Now, our logical resource is again stored in a single file. Note that the |
287 |
<tt>test.sub1.rmplibrary</tt> file is not deleted, though it will be empty. |
288 |
This simplifies comparing and merging changes with a source control repository. |
289 |
Note also that, like separation, absorption can fail unexpectedly. |
290 |
</p><p> |
291 |
How does the MSL framework determine whether an element can be separated? By |
292 |
default, any element of any EMF metamodel can be separated, unless it is a |
293 |
root of the logical resource or has already been separated. However, a metamodel |
294 |
provider or an application may for some reason want to restrict the elements |
295 |
that may be separated. This is accomplished by registering a policy on the |
296 |
<a href="../../reference/extension-points/org_eclipse_gmf_runtime_emf_core_resourcePolicies.html"><code>org.eclipse.gmf.runtime.emf.core.resourcePolicies</code></a> |
297 |
extension point: |
298 |
</p> |
299 |
<pre class="snippet"> |
300 |
<extension |
301 |
point="org.eclipse.gmf.runtime.emf.core.resourcePolicies"> |
302 |
<policy |
303 |
class="org.eclipse.gmf.examples.runtime.emf.resources.LibraryResourcePolicy" |
304 |
nsURI="http:///com/ibm/xtools/emf/metamodel/example/pde/rmplibrary.ecore/1.0.0"/> |
305 |
</extension> |
306 |
</pre> |
307 |
<p> |
308 |
The policy implements the |
309 |
<a href="../../reference/api/common/org/eclipse/gmf/runtime/emf/core/resources/ILogicalResourcePolicy.html"><code>ILogicalResourcePolicy</code></a> |
310 |
interface, usually by extending the <code>AbstractLogicalResourcePolicy</code> |
311 |
class. Our example allows only libraries to be separated: |
312 |
</p> |
313 |
<pre class="snippet"> |
314 |
public class LibraryResourcePolicy |
315 |
extends AbstractLogicalResourcePolicy { |
316 |
|
317 |
public boolean canSeparate(ILogicalResource resource, EObject eObject) { |
318 |
return eObject instanceof Library; |
319 |
} |
320 |
} |
321 |
</pre> |
322 |
<p> |
323 |
Policies can also suggest default URIs for new physical resources according to |
324 |
some application-specific naming system, implement extra checks when clients |
325 |
perform separations or absorptions, etc. |
326 |
</p><p> |
327 |
By default, logical resources initially load only the root resource (corresponding |
328 |
to the logical URI) and automatically load other resources as they are needed |
329 |
by access of containment references or proxy resolution. The <code>ILogicalResource</code> |
330 |
interface defines load options to disable incremental loading or to initially |
331 |
load the entire logical resource contents. Automatic incremental loading of |
332 |
separate objects from containment references requires a custom <code>EList</code> |
333 |
that loads the necessary resources on demand. Two convenient implementations |
334 |
are provided by the MSL for metamodels to use in place of the |
335 |
<code>EObjectContainmentEList</code> and <code>EObjectContainmentWithInverseEList</code> |
336 |
classes. However, it may be necessary for a metamodel to be deployable without |
337 |
the MSL, in a "pure EMF" configuration. To address this need, the |
338 |
<code>resourcePolicies</code> extension point allows the registration of |
339 |
an <code>EFactory</code> that creates alternative <code>*Impl</code> classes |
340 |
that use these special lists, to be deployed only in MSL configurations: |
341 |
</p> |
342 |
<pre class="snippet"> |
343 |
<extension |
344 |
point="org.eclipse.gmf.runtime.emf.core.resourcePolicies"> |
345 |
<efactory |
346 |
class="org.eclipse.gmf.examples.runtime.emf.resources.LoadingRMPLibraryFactoryImpl" |
347 |
nsURI="http:///com/ibm/xtools/emf/metamodel/example/pde/rmplibrary.ecore/1.0.0"/> |
348 |
</extension> |
349 |
</pre> |
350 |
<p> |
351 |
The MSL framework will use this factory instead of the default when loading |
352 |
a logical resource; it does not need to be used by clients to create new objects. |
353 |
In our example, only libraries can be separated and only libraries can contain |
354 |
other libraries, so our factory simply creates a specialization of the default |
355 |
<code>LibraryImpl</code> class: |
356 |
</p> |
357 |
<pre class="snippet"> |
358 |
public class LoadingRMPLibraryFactoryImpl |
359 |
extends RMPLibraryFactoryImpl { |
360 |
|
361 |
public Library createLibrary() { |
362 |
return new LoadingLibraryImpl(); |
363 |
} |
364 |
|
365 |
public EPackage getEPackage() { |
366 |
return RMPLibraryPackage.eINSTANCE; |
367 |
} |
368 |
} |
369 |
|
370 |
class LoadingLibraryImpl |
371 |
extends LibraryImpl { |
372 |
|
373 |
public LoadingLibraryImpl() { |
374 |
super(); |
375 |
|
376 |
// use the custom containment-with-inverse list to perform automatic |
377 |
// loading of contained elements in this feature. This pre-empts |
378 |
// the superclass's lazy initialization of this list |
379 |
branches = new EObjectContainmentWithInverseLoadingEList( |
380 |
Library.class, this, RMPLibraryPackage.LIBRARY__BRANCHES, |
381 |
RMPLibraryPackage.LIBRARY__PARENT_BRANCH); |
382 |
} |
383 |
} |
384 |
</pre> |
385 |
<p> |
386 |
Note how we only concern ourselves here with overriding the implementation of |
387 |
those features that will be able to contain separate elements. |
388 |
</p> |
389 |
|
390 |
<h2><a name="listeners"></a>MSL Listeners</h2> |
206 |
<h2><a name="listeners"></a>MSL Listeners</h2> |
391 |
|
207 |
|
392 |
<p class="backto"><font size="-1">[<a href="#top">back to top</a>]</font></p> |
208 |
<p class="backto"><font size="-1">[<a href="#top">back to top</a>]</font></p> |
Lines 755-762
Link Here
|
755 |
<li>Registered the MSL resource factory for the .rmplibrary file extension</li> |
571 |
<li>Registered the MSL resource factory for the .rmplibrary file extension</li> |
756 |
<li>Made changes to MSL resources using an undo interval and a write action</li> |
572 |
<li>Made changes to MSL resources using an undo interval and a write action</li> |
757 |
<li>Undid and redid the changes made during an undo interval</li> |
573 |
<li>Undid and redid the changes made during an undo interval</li> |
758 |
<li>Created logical resources consisting of multiple files</li> |
|
|
759 |
<li>Customized the management of logical resources for library models</li> |
760 |
<li>Registerd an MSL listener that informed us whenever a resource was dirtied</li> |
574 |
<li>Registerd an MSL listener that informed us whenever a resource was dirtied</li> |
761 |
<li>Learned how live validation can be used to enforce resource integrity during write actions</li> |
575 |
<li>Learned how live validation can be used to enforce resource integrity during write actions</li> |
762 |
<li>Learned how to perform batch validation when using MSL</li> |
576 |
<li>Learned how to perform batch validation when using MSL</li> |