File: EMF.Edit.html

package info (click to toggle)
eclipse-emf 2.42.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 73,344 kB
  • sloc: java: 711,198; xml: 12,829; makefile: 5
file content (858 lines) | stat: -rw-r--r-- 35,521 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" href="images/../../../css/book.css" type="text/css"/>
<link rel="stylesheet" href="images/../../../css/emf-book.css" type="text/css"/>
<title>EMF.Edit Overview</title>
</head>
<body lang="EN-US" xml:lang="EN-US">
<h1>EMF.Edit Overview</h1>

<p>Last updated: June 1, 2004</p>

<p>This document assumes familiarity with basic EMF (Eclipse Modeling Framework)
concepts. For more information on EMF, refer to the
<a href="../../references/overview/EMF.html">EMF Overview</a>.</p>


<h2>Contents</h2>
<p><a href="#introduction">Introduction</a><br/>
<a href="#jface">Displaying EMF Objects in JFace Viewers</a><br/>
<a href="#providers">Item Provider Implementation Classes</a><br/>
<a href="#commands">Modifying EMF Models Using Commands</a><br/>
<a href="#generator">Using the EMF.Edit Code Generator</a></p>

<h2><a name="introduction">Introduction</a></h2>

<p>If you have an EMF-based model that you've generated code for using the EMF
generator, and you are now ready to add user interfaces to your model and code,
you can use the EMF.Edit framework to make your job easier.</p>

<p>EMF.Edit is an Eclipse framework that includes generic reusable classes for
building editors for EMF models. It provides:</p>

<ul>
<li>Content and label provider classes, property source support, and other
convenience classes that allow EMF models to be displayed using standard desktop
(JFace) viewers and property sheets.</li>
<li>A command framework, including a set of generic command implementation
classes for building editors that support fully automatic undo and redo.</li>
<li>A code generator capable of generating everything needed to build a complete
editor plug-in for your EMF model. It produces a properly structured editor that
conforms to the recommended style for Eclipse EMF model editors. You can then
customize the code however you like, without losing your connection to the
model.</li>
</ul>

<p>This paper gives an overview of the basic concepts of the EMF.Edit frameowrk
and generator tool. For more in-depth information, you can refer to the
documentation for the framework classes, which covers in detail their specific
behaviors and capabilities.</p>

<h2><a name="jface">Displaying EMF Objects in JFace Viewers</a></h2>

<h3>What's a content provider?</h3>

<p>The Eclipse user interface framework (JFace) includes a set of reusable
viewer classes (for example TreeViewer, TableViewer) for displaying structured
models. Rather than requiring the model objects being viewed to adhere to some
specific protocol (that is, implement some specific interface), JFace viewers
work with any kind of object (that is, any java.lang.Object subclass). This is
possible because the viewers, instead of navigating the model objects directly,
access the model objects through an adapter object called a <dfn>content
provider</dfn>.</p>

<p>Each viewer class uses a content provider that implements a specific provider
interface. For example, a TreeViewer uses a content provider that implements the
following interface:</p>

<pre>
  public interface ITreeContentProvider ...
  {
    public Object[] getChildren(Object object);
    public Object getParent(Object object);
    ...
  }
</pre>

<p>The basic structure is shown in the following diagram:</p>

<img src="images/EMF.Edit/image001.gif" border="0" width="481" height="207" alt="JFace content provider"/>

<p>As far as the TreeViewer is concerned it is displaying a tree of objects (it
calls them items) on the screen, all of which, except the input (root) object,
are provided to it by calling getChildren() on its content provider.</p>

<p>Other kinds of viewers are handled similarly, although each viewer requires
the content provider to implement its specific interface. Although all of the
viewer interfaces are different, a content provider can often implement several
of them at once, allowing the same content provider class to be used for many
kinds of viewers.</p>

<h3>Providing content for an EMF model</h3>

<p>The EMF.Edit framework provides a generic content provider implementation
class that can be used to provide content for EMF models. Class
AdapterFactoryContentProvider implements the content provider interfaces by
delegating to EMF adapters that know how to navigate the model objects (items)
for the viewers. For example, the EMF adapter class used to support a tree
viewer would implement the following EMF.Edit interface:</p>

<pre>
  public interface ITreeItemProvider
  {
    public Collection getChildren(Object object);
    public Object getParent(Object object);
    ...
  }
</pre>

<p>Notice the similarity of this interface to the content provider interface
ITreeContentProvider described above. The AdapterFactoryContentProvider
implements the content provider interface by locating and then delegating to an
adapter (implementing the item provider interface) for the required item. The
shift in terminology from objects to items is deliberate: from the viewer's
point of view, they are items, not objects.</p>

<p>The EMF picture looks like this:</p>

<img src="images/EMF.Edit/image002.gif" border="0" width="607" height="231" alt="AdapterFactoryContentProvider delegation to item providers"/>

<p class="Note">Note: you can automatically generate an
ItemProviderAdapterFactory and ItemProvider classes for a given EMF model using
the generator provided with the EMF.Edit framework. More about this later.</p>

<p>The AdapterFactoryContentProvider is constructed with an adapter factory
which, like any other EMF adapter factory, serves to create and locate adapters
of a specific type (ItemProviders in this case). The content provider services a
request like getChildren() by calling adapt(item) on the
ItemProviderAdapterFactory, which will create or return the ItemProvider
(adapter) for the specified item. It then simply delegates to the getChildren()
method of the required interface (in this case, ITreeItemProvider).</p>

<p>The getChildren() method in AdapterFactoryContentProvider looks something
like this:</p>

<pre>
  public Object[] getChildren(Object object)
  {
    ITreeItemContentProvider adapter =
      (ITreeItemContentProvider)
        adapterFactory.adapt(object, ITreeItemContentProvider.class);
    return adapter.getChildren(object).toArray();
  }
</pre>

<p>This same pattern is used for all of the content provider methods. As stated
previously, the AdapterFactoryContentProvider does nothing more than simply
delegate content provider methods to the specific item provider (adapter) that
knows how to service the request.</p>

<p>In the getChildren() method above, the object being passed to
adapterFactory.adapt() is a simple java.lang.Object (not an
org.eclipse.emf.ecore.EObject). This is an important feature of the EMF.Edit
framework. The framework has been carefully designed to accommodate views on EMF
models that may be different from the model itself (that is, views that suppress
objects or include additional, phantom, objects). To allow this mixture of EMF
and non-EMF objects, the framework base class for adapter factories provides an
implementation of adapt() that works something like this:</p>

<pre>
  public Object adapt(Object object, Object type)
  {
    if (object instanceof Notifier)
      return this.adapt((Notifier)object, type);
    else
      return object;
  }
</pre>

<p>If the specified object is not an EMF
Notifier<sup><a class="footnote" href="#fn1">[1]</a><a name="ref1">&nbsp;</a></sup>,
it returns the object itself. With this design, an item provider that wants to
add non-EMF items to a view can simply return (for example, from its
getChildren() method) any non-EMF object it wants. As long as the returned
object implements the viewer's required item provider interface (for example,
ITreeItemProvider) it will be treated like all the other EMF items.</p>

<p>This aspect of the design highlights why we prefer to call the
provider/adapter classes item providers instead of adapters. In nontrivial
applications, the view model (that is, the one provided by the viewer's content
provider) will often be a mixture of &quot;real&quot; (EMF) model objects whose
item providers also happen to be (EMF) adapters, and &quot;phantom&quot; objects
whose item providers are the objects themselves. So, while all of the adapters
are also item providers, the reverse is not necessarily true.</p>

<h3>JFace label providers</h3>

<p>In the previous sections we described how JFace viewers use a content
provider to get their content items. A similar approach is used for getting the
label image and text for the items being displayed by a viewer. Instead of
asking the items themselves for their labels, a viewer uses another object
called a label provider (similar to a content provider). A TreeViewer, for
example, delegates to an object implementing the ILabelProvider interface to get
the labels of the items in the tree.</p>

<h3>Providing labels for EMF objects</h3>

<p>The EMF.Edit framework uses the same mechanism for implementing label
providers for EMF models as it uses for providing the content. A generic label
provider implementation class, AdapterFactoryLabelProvider (working exactly like
AdapterFactoryContentProvider), delegates the ILabelProvider interface to the
item providers for the model (the same item providers that provide the content).
The expanded picture looks like this:</p>

<img src="images/EMF.Edit/image003.gif" border="0" width="608" height="326" alt="AdapterFactoryLabelProvider delegation to item providers"/>

<p>The content and label provider can (and usually will) delegate to the same
adapter factory and, consequently, the same item providers. Just as for the
content provider, the item providers are where the work actually gets done.</p>

<p>Using the EMF.Edit provider classes, a user might construct a TreeViewer for
some EMF model as follows:</p>

<pre>
  myAdapterFactory = ...

  treeViewer = new TreeViewer();

  treeViewer.setContentProvider(new AdapterFactoryContentProvider(myAdapterFactory));
  treeViewer.setLabelProvider(new AdapterFactoryLabelProvider(myAdapterFactory));
</pre>

<p>This TreeViewer can then be displayed in, for example, an editor window in
the usual (JFace prescribed) way.</p>

<p>You might be thinking this all seems quite trivial so far, but only because
all we've shown is how to delegate to somebody else (that is, the adapter
factory). We haven't implemented any of the methods yet, we've just delegated
them away. However, the method implementation is supported by EMF.Edit, which
includes a code generator that generates most of the item provider and factory
code for you. Before we get into that, we'll first take a look at how item
providers do their job.</p>

<h2><a name="providers">Item Provider Implementation Classes</a></h2>

<p>As shown in the previous section, the real work of providing content for EMF
models is done by the item provider adapters attached to the model. The number
and types of ItemProvider adapters in the previous diagram was left
intentionally vague. This is because the EMF.Edit framework supports two
different patterns for the item provider adapters:</p>

<ol>
<li>Stateful adapters - one adapter object for every object in the model</li>
<li>Singleton adapters - one adapter object for every type of object in the
model (recommended when possible)</li>
</ol>

<p>The item providers for a given model can be implemented with either of these
patterns or with a mixture of them both.</p>

<h3>Stateful item provider adapters</h3>

<p>With the first pattern, every object in a model has a one-to-one
correspondence with its adapter. Each adapter has a pointer (called target) to
the one-and-only object it's adapting.</p>

<p>The picture looks like this:</p>

<img src="images/EMF.Edit/image004.gif" border="0" width="615" height="257" alt="Stateful item provider adapters"/>

<p>As shown, this pattern doubles the number of objects in the application, and
therefore only makes sense in applications where the instances are needed to
carry additional state. That's why we call it the Stateful pattern.</p>

<h3>Singleton item provider adapters</h3>

<p>A better approach, that avoids most of the extra objects, is the Singleton
pattern. With this pattern we use a single item provider adapter for all the
items of the same type. It looks like this:</p>

<img src="images/EMF.Edit/image005.gif" border="0" width="615" height="257" alt="Singleton item provider adapters"/>

<p>In this picture, the objects have adapter pointers, as usual, but the item
providers (which are shared) have no pointers back to the objects. If you
remember the tree item provider interface that we looked at previously in the
content provider section, you may have noticed that all the methods took an
extra argument (an object):</p>

<pre>
  public interface ITreeItemProvider
  {
    public Collection getChildren(Object object);
    public Object getParent(Object object);
    ...
  }
</pre>

<p>The object argument was added to each item provider interface specifically to
support this pattern. In the Stateful case, this object will always be the same
as the adapter's target.</p>

<p>Another question you may be asking yourself, is why don't we support a
&quot;true&quot; Singleton adapter pattern - that is, exactly one adapter for
all the objects? The answer is simply that while it is another possible pattern
(compatible with the EMF.Edit
framework)<sup><a class="footnote" href="#fn2">[2]</a><a name="ref2">&nbsp;</a></sup>,
we discourage it because a completely dynamic implementation, although simple,
is difficult to customize (without lots of messy instanceof() checks). The
alternative of having typed item provider classes, whose inheritance hierarchy
mirrors the model's, provides a convenient dispatch point for implementing nice
clean object-oriented view code for a model.</p>

<h2><a name="commands">Modifying EMF Models Using Commands</a></h2>

<p>So far we've only shown how to view EMF models using content and label
providers. Another feature of the EMF.Edit framework is its support for
command-based editing of a model. We use the term &quot;editing&quot; to mean
undoable modification, as opposed to simple &quot;writing&quot; of a model.</p>

<h3>Editing domains</h3>

<p>The EMF.Edit interface EditingDomain is used to provide editing access to an
EMF model. Another EMF.Edit implementation class, AdapterFactoryEditingDomain,
works like the content and label providers by delegating its implementation to
the item providers (through the ItemProviderAdapterFactory):</p>

<img src="images/EMF.Edit/image006.gif" border="0" width="608" height="249" alt="Editing domain"/>

<p>As shown, it also provides access to a command stack through which all
modifications to the model will be made. The editing domain provides two
fundamental services:</p>

<ul>
<li>A factory for commands</li>
<li>A provider of model-specific details for generic EMF.Edit commands (like
Add, Remove, Copy, and so on).</li>
</ul>

<p>The best way to think about an editing domain is as the modification or write
provider to the model, while the content and label providers are the viewing or
read provider. Here's the big picture:</p>

<img src="images/EMF.Edit/image007.gif" border="0" width="607" height="331" alt="Read and write providers"/>

<h3>Modifying a model</h3>

<p>Let's look at a simple example of modifying a model.</p>

<p>Assume class Company has a one-to-many reference, named departments, to class
Department. To remove a department from the company (to implement, for example,
an editor delete action) we could simply write the following code:</p>

<pre>
  Department d = ...
  Company c = ...
  c.getDepartments().remove(d);
</pre>

<p>Although simple, this code does nothing more than simply make the
modification.</p>

<p>If instead, we use the EMF.Edit remove command
(org.eclipse.emf.edit.command.RemoveCommand) to remove the department, we would
write the following:</p>

<pre>
  Department d = ...
  Company c = ...
  EditingDomain ed = ...
  RemoveCommand cmd = 
    new RemoveCommand(ed, c, CompanyPackage.eINSTANCE.getCompany_Departments(), d);
  ed.getCommandStack().execute(cmd);
</pre>

<p>Deleting the department this way has several advantages:</p>

<ol>
<li>The deletion can be undone by calling ed.getCommandStack().undo().</li>
<li>We can find out if a model is dirty (to enable a save menu, for example) by
checking if there are commands on the command stack, assuming all modifications
are done using commands (which is what the EMF.Edit framework advocates).
</li>
<li>We could have checked if the command is valid (to enable a delete menu, for
example) before executing it by calling cmd.canExecute();</li>
</ol>

<p>Using commands this way, pervasively, is the way to enable all kinds of
function that the EMF.Edit framework can give you.</p>

<h3>Creating commands using the editing domain</h3>

<p>In the previous example we created a RemoveCommand using a simple new call.
This worked fine, but is not very reusable; the code fragment is doing a very
specific thing, removing a department from a company. If instead we want to
write, for example, a reusable delete action capable of deleting any kind of
object, we can do that by using the EditingDomain to help with the job.</p>

<p>The EditingDomain interface contains (among other things) a command factory
method, createCommand(), that can be used, instead of new, to create
commands:</p>

<pre>
  public interface EditingDomain
  {
    ...
    Command createCommand(Class commandClass, CommandParameter commandParameter);
    ...
  }
</pre>

<p>To use this method to create a command you would first need to create a
CommandParameter object, set command parameters into it, and then call the
create method, passing it the desired command class (for example,
RemoveCommand.class) and the parameters.</p>

<p>Rather then making clients go through all that, we use a convention of
providing static convenience create() methods in every command class. Using the
static create() method, you can create and execute a RemoveCommand like this:
</p>

<pre>
  Department d = ...
  EditingDomain ed = ...
  Command cmd = RemoveCommand.create(ed, d);
  ed.getCommandStack().execute(cmd);
</pre>

<p>As you can see, this is just a small syntactic change (RemoveCommand.create()
instead of new RemoveCommand). But there are fundamental differences. We only
passed one argument (that is, the object being removed), aside from the editing
domain, instead of the three arguments previously. Notice how this piece of code
can now be used to remove any kind of object. By delegating the creation of the
command to the editing domain, we're letting it fill in the missing
arguments.</p>

<h3>How does an Editing Domain handle a createCommand() request?</h3>

<p>To understand how it all works, let's follow through with the
RemoveCommand.create() call. As stated previously, the static create() method is
just a convenience method that delegates to the editing domain something like
this:</p>

<pre>
  public static Command create(EditingDomain domain, Object value) 
  {
    return domain.createCommand(
      RemoveCommand.class,
      new CommandParameter(null, null, Collections.singleton(value)));
  }
</pre>

<p>The AdapterFactoryEditingDomain then takes the request and passes it along to
an item provider using the standard delegation pattern (as
AdapterFactorContentProvider delegated getChildren() earlier):</p>

<pre>
  public Command createCommand(Class commandClass, CommandParameter commandParameter)
  {
    Object owner = ...  // get the owner object for the command
    IEditingDomainItemProvider adapter = 
      (IEditingDomainItemProvider)
        adapterFactory.adapt(owner, IEditingDomainItemProvider.class);
    return adapter.createCommand(owner, this, commandClass, commandParameter);
  }
</pre>

<p class="Note">Note: if you look at the actual createCommand() method you will
notice that it's actually considerably more complicated. That's because it's
designed to also handle, among other things, deleting collections of objects at
once. This is, nevertheless, all it's doing conceptually.</p>

<p>The createCommand() method uses an owner object to access the item provider
to delegate to (that is, the owner is used in the adapterFactory.adapt() call).
The owner in our example will be the company object (that is, the parent of the
department being removed). The editing domain determines the owner by calling
the getParent() method on the item provider of the object being deleted.</p>

<p>The effect of all this is that the method createCommand() is finally called
on the item provider of the parent of the object being removed (that is, the
CompanyItemProvider for company c in the original code fragment). So, the
CompanyItemProvider could implement createCommand() by doing something like
this:</p>

<pre>
  public class CompanyItemProvider ...
  {
    ...

    public Command createCommand(final Object object, ..., Class commandClass, ...)
    {
      if (commandClass == RemoveCommand.class)
      {
        return new RemoveCommand(object,
                                 CompanyPackage.eINSTANCE.getCompany_Departments(),
                                 commandParameter.getCollection()); 
      }
    ...
   }
  }
</pre>

<p>This would get the job done, but there is a better way.</p>

<p>Every item provider class (that is also an EMF adapter) extends from an
EMF.Edit convenience base class, ItemProviderAdapter, which provides a default
implementation of, among other things, createCommand(). It implements
createCommand() for all the standard commands provided by the EMF.Edit framework
by calling out to a few simple methods (which are used for more than just this
purpose) that are implemented in the item provider subclasses. This is an
example of the Template Method design pattern.</p>

<p>To make our RemoveCommand example work, CompanyItemProvider only needs
to implement the following method:</p>

<pre>
  public Collection getChildrenFeatures(Object object)
  {
    return Collections.singleton(CompanyPackage.eINSTANCE.getCompany_Departments());
  }
</pre>

<p>As shown, this method returns the one or more features (in this case, only
the deparments reference) that are used for referencing children of the object.
After calling this method, the default implementation of createCommand() will
then figure out which feature to use (if more than one is returned) and create
the RemoveCommand with the right one.</p>

<h3>Overriding commands</h3>

<p>Another advantage of creating commands through an editing domain is that it
allows us to plug in different subclasses or completely different
implementations of standard commands and have standard editors just pick them
up. For example, assume that we want to do some extra cleanup whenever we remove
a department from a company. The simplest way to achieve that might be to create
a subclassof RemoveCommand  called RemoveDepartmentCommand like this:</p>

<pre>
  public class RemoveDepartmentCommand extends RemoveCommand
  {
    public void execute()
    {
      super.execute();
      // do extra stuff ...
    }
  }
</pre>

<p>That part's easy enough.</p>

<p>Now, if our editor uses the static RemoveCommand.create() method (which calls
editingDomain.createCommand()) instead of new RemoveCommand(), then we can
easily substitute our RemoveDepartmentCommand for the standard RemoveCommand by
overriding createCommand() in the item provider like this:</p>

<pre>
  public class CompanyItemProvider ...
  {
    ...

    public Command createCommand(final Object object, ...)
    {
      if (commandClass == RemoveCommand.class)
      {
        return new RemoveDepartmentCommand(...); 
      }
      return super.createCommand(...);
    }
  }
</pre>

<p>Actually, if the command we want to specialize is one of the predefined ones
(like RemoveCommand), the substitution is even easier because the default
implementation of createCommand() dispatches the creation of each command to
command-specific convenience methods, something like this:</p>

<pre>
  public Command createCommand(final Object object, ...
  {
    ...
    if (commandClass == RemoveCommand.class)
      return createRemoveCommand(...); 
    else if (commandClass == AddCommand.class)
      return createAddCommand(...);
    else ...
  }
</pre>

<p>So, we could have created our RemoveDepartmentCommand more simply by just
overriding createRemoveCommand(), instead of the createCommand() method itself:
</p>

<pre>
  protected Command createRemoveCommand(...) 
  {
    return new RemoveDepartmentCommand(...);
  }
</pre>

<p>To summarize, the key point is that the editing domain is our hook to adjust
command parameters, including the command class itself, so we can easily control
the behavior of any editing command on our model.</p>

<h3>Model change notification</h3>

<p>One thing we haven't talked about yet is change notification. How do we get
the viewers to refresh after a command changes something in the model? The
answer is that it works using a combination of standard EMF adapter notification
and a viewer refresh mechanism provided by EMF.Edit.</p>

<p>When constructed, an AdapterFactoryContentProvider registers itself as a
listener (i.e. org.eclipse.emf.edit.provider.INotifyChangedListener) of its
adapter factory (which implements the
org.eclipse.emf.edit.provider.IChangeNotifier interface). The adapter factory in
turn passes itself to every item provider it creates so it can be the central
change notifier for the model. The AdapterFactoryContentProvider also records
(in the inputChanged() method) the viewer for which it is providing content, so
that it can update its viewer when it receives a change notification.</p>

<p>The following diagram shows how a change in an EMF model object (for example,
changing a company name) will make its way, through the adapter factory, back to
the viewers of the model.</p>

<img src="images/EMF.Edit/image008.gif" border="0" width="607" height="251" alt="Model change notification"/>

<p>Whenever an EMF object changes state, the method notifyChanged() is called on
all the object's adapters, including the item providers (in this case,
CompanyItemProvider). The notifyChanged() method in the item provider is
responsible for determining whether each event notification should be passed on
to the viewer, and if so, what type of update it should result in.</p>

<p>To do so, it wraps interesting notifications in a ViewerNotification, a
simple implementation of interface IViewerNotification. This interface extends
the basic Notification interface like this:</p>

<pre>
  public interface IViewerNotification extends Notification
  {
    Object getElement();
    boolean isContentRefresh();
    boolean isLabelUpdate();
  }
</pre>

<p>These methods specify which item in the viewer to update, whether to refresh
the content under that element, and whether to update the label of that element.
Since the item provider determines the children and label for an object, it must
also determine how to efficiently update the viewer.</p>

<p>The notifyChanged() method in class CompanyItemProvider looks like this:</p>

<pre>
  public void notifyChanged(Notification notification)
  {
    ...
    switch (notification.getFeatureID(Company.class))
    {
      case CompanyPackage.COMPANY__NAME:
        fireNotifyChanged(new ViewerNotification(notification, ..., false, true));
        return;
      case CompanyPackage.COMPANY__DEPARTMENT:
        fireNotifyChanged(new ViewerNotification(notification, ..., true, false));
        return;
    }
    super.notifyChanged(notification);
  }
</pre>

<p>In this implementation, a change to the name attribute results in a label
update, and a change to the department reference causes a content refresh. Any
other change notifications have no effect on the viewer.</p>

<p>The fireNotifyChanged() method is a convenience method in class
ItemProviderAdapter (the base class of all the item provider adapters) which
simply forwards the notification to the adapter
factory<sup><a class="footnote" href="#fn3">[3]</a><a name="ref3">&nbsp;</a></sup>.
The adapter factory (change notifier) proceeds to dispatch the notification to
all its listeners (in this example, just the tree viewer's content provider).
Finally, the content provider updates the viewer, as directed by the
notification.</p>

<h3>Composed adapter factories</h3>

<p>EMF models are often tied together by cross-model references. Whenever you
need to build an application to edit or display objects that span more than one
EMF model, you'll need an adapter factory capable of adapting the union of the
objects from the two (or more) models.</p>

<p>Often, you already have adapter factories for the individual models and all
that you need is to glue them together. Another EMF.Edit convenience class,
ComposedAdapterFactory, can be used for this purpose:</p>

<img src="images/EMF.Edit/image009.gif" border="0" width="607" height="250" alt="Adapter factory composition"/>

<p>A ComposedAdapterFactory is used to provide a common interface to other
adapter factories, to which it simply delegates its implementation.</p>

<p>To set up a composed adapter factory, you would write something like this:
</p>

<pre>
  model1AdapterFactory = ...
  model2AdapterFactory = ...

  ComposedAdapterFactory myAdapterFactory = new ComposedAdapterFactory();
  myAdapterFactory.addAdapterFactory(model1AdapterFactory);
  myAdapterFActory.addAdapterFActory(model2AdapterFactory);

  myContentProvider = new AdapterFactoryContentProvider(myAdapterFactory);
  ...
</pre>

<h2><a name="generator">Using the EMF.Edit Code Generator</a></h2>

<p class="Note">Note: a step-by-step tutorial for generating an EMF model, as
well as an EMF.Edit editor, can be found in
<a href="../../tutorials/clibmod/clibmod.html">Tutorial: Generating an EMF
Model</a>.</p>

<p>Given an EMF model definition, the EMF.Edit code generator can produce a
fully functional editor tool that will allow you to view instances of the model
using several common viewers and to add, remove, cut, copy, and paste model
objects, or modify the objects in a standard property sheet, all with full
undo/redo support.</p>

<p>The EMF.Edit generator produces complete working plug-ins that include the
following:</p>

<ol>
<li>ItemProviderAdapterFactory</li>
<li>ItemProviders (one per model class)</li>
<li>Editor</li>
<li>ModelWizard</li>
<li>ActionBarContributor</li>
<li>Plugin</li>
<li>plugin.xml</li>
<li>Icons</li>
</ol>

<p>Once generated, the editor should run. It will come up, but it may or may not
be working as you expected (that is, the default choices that the generator made
may have been inappropriate for your model). It should, however, be pretty easy
to tweak the generated code in a few places to quickly get a basic working
editor up and running.</p>

<p>The following takes a closer look at some of the more interesting generated
classes.</p>

<h3>ItemProviderAdapterFactory</h3>

<p>The generated ItemProviderAdapterFactory is a simple subclass of the
generated AdapterFactory class that you got when you generated your EMF model.
</p>

<p class="Note">Note: the generated EMF adapter factory creates adapters by
dispatching to a type-specific create() method that subclasses (like
ItemProviderAdapterFactory) are required to override. The EMF adapter factory
(for example, ABCAdapterFactory) uses another generated class, (ABCSwitch), to
implement the dispatch efficiently.</p>

<p>When using the Stateful pattern, the adapter factory create methods simply
return a new object like this:</p>

<pre>
  class ABCItemProviderAdapterFactory extends ABCAdapterFactoryImpl
  {
    ...
    public Adapter createCompanyAdapter()
    {
      return new CompanyItemProvider(this);
    }
    ...
  }
</pre>

<p>If, instead, the Singleton pattern is used, the adapter factory also keeps
track of the singleton instance and returns it for each call:</p>

<pre>
  protected DepartmentItemProvider departmentItemProvider;

  public Adapter createDepartmentAdapter()
  {
    if (departmentItemProvider == null)
    {
      departmentItemProvider = new DepartmentItemProvider(this);
    }
    return departmentItemProvider;
  }
</pre>

<h3>The ItemProvider classes</h3>

<p>For each class in the model, a corresponding item provider class is
generated. The generated item providers mix in all the interfaces needed to
support the standard viewers, commands, and the property sheet:</p>

<pre>
  public class DepartmentItemProvider extends ...
    implements 
      IEditingDomainItemProvider,
      IStructuredItemContentProvider, 
      ITreeItemContentProvider, 
      IItemLabelProvider, 
      IItemPropertySource
  {
    ...
  }
</pre>

<p>If a model class is a root (that is, it has no explicit base class) then the
generated item provider will extend from the EMF.Edit item provider base class,
ItemProviderAdapter:</p>

<pre>
  public class EmployeeItemProvider extends ItemProviderAdapter ...
</pre>

<p>If, instead, the model class inherits from a base class, then the generated
item provider will extend from the base item provider like this:</p>

<pre>
  public class EmployeeItemProvider extends PersonItemProvider ...
</pre>

<p>For a multiply inheriting class, the generated item provider will extend from
the first base class's item provider (as in the single inheritance case) and it
will implement the provider function for the rest of the base classes.</p>

<p>If you look at the generated item provider classes, you'll notice that a lot
of their function is actually implemented in the item provider base class. The
most important functions of the generated item provider subclasses are:</p>

<ol>
<li>Identifying the children and parent</li>
<li>Setting up the property descriptors</li>
<li>Passing on the "interesting" notification events.</li>
</ol>

<h3>Editor and ModelWizard</h3>

<p>The generated Editor and ModelWizard show how to put all the other generated
pieces together with standard JFace components to produce a working editor.</p>

<p>The ModelWizard can be used to create new resources of the model's type. If
instead, you already have a resource that was created some other way, you can
import it into your desktop workspace and launch the editor on it, bypassing the
ModelWizard completely.</p>

<br/><hr noshade="noshade" size="1"/>

<p><sup><a class="footnote" href="#ref1">[1]</a><a name="fn1">&nbsp;</a></sup>Notifier
is the base interface in EMF for objects that can register adapters and send
notifications to them. It is extended by EObject, the base interface for all
model objects.</p>

<p><sup><a class="footnote" href="#ref2">[2]</a><a name="fn2">&nbsp;</a></sup>Actually,
EMF adapter factories are inheritance driven, so you can choose to use a base
adapter to handle subclasses at any level in your model, EObject being the
extreme case.</p>

<p><sup><a class="footnote" href="#ref3">[3]</a><a name="fn3">&nbsp;</a></sup>In
addition to the adapter factory, which acts as the change notifier for viewers,
an ItemProviderAdapter can also have other (direct) listeners which are also
called in ItemProviderAdapter.fireNotifyChanged().</p>
</body>
</html>