<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Tomsondev Blog &#187; Tutorials</title>
	<atom:link href="http://tomsondev.bestsolution.at/category/databinding/emf/tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>http://tomsondev.bestsolution.at</link>
	<description>Tom&#039;s opensource development</description>
	<lastBuildDate>Fri, 24 May 2013 11:15:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='tomsondev.bestsolution.at' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://0.gravatar.com/blavatar/293a1486b971639e6153cd953d1dbc9e?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>Tomsondev Blog &#187; Tutorials</title>
		<link>http://tomsondev.bestsolution.at</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://tomsondev.bestsolution.at/osd.xml" title="Tomsondev Blog" />
	<atom:link rel='hub' href='http://tomsondev.bestsolution.at/?pushpress=hub'/>
		<item>
		<title>Galileo: EMF-Databinding &#8211; Part 5</title>
		<link>http://tomsondev.bestsolution.at/2009/06/27/galileo-emf-databinding-part-5/</link>
		<comments>http://tomsondev.bestsolution.at/2009/06/27/galileo-emf-databinding-part-5/#comments</comments>
		<pubDate>Sat, 27 Jun 2009 13:55:27 +0000</pubDate>
		<dc:creator>Tom Schindl</dc:creator>
				<category><![CDATA[EMF]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://tomsondev.bestsolution.at/?p=384</guid>
		<description><![CDATA[Though the main focus of this article is going to be the usage of the properties API to setup a TableViewer there are some importanted I didn&#8217;t explain in Part 4 of this series. Using the properties API in master-detail (continued) Showing validation states The first interesting thing is how to present validation errors to [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tomsondev.bestsolution.at&#038;blog=7995503&#038;post=384&#038;subd=tomsondev&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Though the main focus of this article is going to be the usage of the properties API to setup a TableViewer there are some importanted I didn&#8217;t explain in Part 4 of this series.</p>
<h2>Using the properties API in master-detail (continued)</h2>
<p><span style="font-size:large;">Showing validation states</span></p>
<p>The first interesting thing is how to present validation errors to user. I&#8217;m personally not a friend of ControlDecorations but prefer to display the validation error in the form-header.<br />
<img src="http://tomsondev.files.wordpress.com/2009/06/detail_area_error.png?w=588" alt="Detail Area Error" title="Detail Area Error"   class="aligncenter size-full wp-image-385" /><br />
This means the header presents an aggregation of all binding states and because this a quite common thing Eclipse-Databinding has built in support for this kind of thing.</p>
<pre class="brush: java; title: ; notranslate">
private void addStatusSupport(ObservablesManager mgr, 
  final DataBindingContext ctx)
{
  AggregateValidationStatus aggregateStatus = 
    new AggregateValidationStatus(
      ctx.getValidationStatusProviders(),
      AggregateValidationStatus.MAX_SEVERITY
  );

  aggregateStatus.addValueChangeListener(
    new IValueChangeListener()
    {
      public void handleValueChange(ValueChangeEvent event)
      {
        handleStateChange(
          (IStatus)event.diff.getNewValue(), 
          ctx
        );
      }
    });
  mgr.addObservable(aggregateStatus);
}
</pre>
<p>The above aggregates the validation states of all validation status providers. By the default there&#8217;s a provider for binding states attached to a databinding context but one can attach also custom ones which opens an interesting opportunity e.g. when used inconjunction with the EMF-Validation framework (probably a topic for another Blog post in the next weeks).<br />
The final task is to display the status to the user through the form header control like this</p>
<pre class="brush: java; title: ; notranslate">
private void handleStateChange(IStatus currentStatus, 
  DataBindingContext ctx)
{
  if (form.isDisposed() || form.getHead().isDisposed())
  {
    return;
  }

  if (currentStatus != null 
    &amp;&amp; currentStatus.getSeverity() != IStatus.OK)
  {
    int type = convertType(currentStatus.getSeverity());

    List&lt;IMessage&gt; list = new ArrayList&lt;IMessage&gt;();
    Iterator&lt; ? &gt; it = ctx.getValidationStatusProviders()
     .iterator()
    ;

    while (it.hasNext())
    {
      ValidationStatusProvider validationStatusProvider = 
        (ValidationStatusProvider)it.next()
      ;
      final IStatus status = (IStatus)
        validationStatusProvider.getValidationStatus()
        .getValue()
      ;

      if (!status.isOK())
      {
        list.add(new IMessage()
        {
          public Control getControl()
          {
            return null;
          }

          public Object getData()
          {
            return null;
          }

          public Object getKey()
          {
            return null;
          }

          public String getPrefix()
          {
            return null;
          }

          public String getMessage()
          {
            return status.getMessage();
          }

          public int getMessageType()
          {
            return convertType(status.getSeverity());
          }
        });
      }
    }
    form.setMessage(&quot;Data invalid&quot;, 
      type, 
      list.toArray(new IMessage [0])
    );
  }
  else
  {
    form.setMessage(null);
  }
}
</pre>
<p><span style="font-size:large;">Master-Detail, Validation and null</span><br />
That&#8217;s kind of a strange title but and not easy to track down but an undiscovered regression in Eclipse-Databinding since about 2 years and was <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=278301">discovered</a> too late to get fixed in 3.5 timeframe.</p>
<p>In short the problem is that if you are producing an validation error in for a model attribute which initially had the value <span style="font-family:Courier;">null</span> the wrong value on the target (=UI-Widget) is not cleared when modifing master. Believe this sounds more complex than it is reality and <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=278301">bug 278301</a> holds an nice example to reproduce the behaviour.</p>
<p>Nonetheless we need a working solution for now because of the location of the problem we won&#8217;t see a fix until 3.6 ships which is 1 year from now. I&#8217;m demonstrating in the following code a possible work-around but there are also other solutions. My solution uses the AggregateValidationStatus-support and forces an target update when the master observable is changed and the current validation status is <strong>NOT OK</strong>.</p>
<pre class="brush: java; title: ; notranslate">
public class Util
{
  public static void masterDetailFixup(
    final DataBindingContext ctx, 
    IObservableValue master)
  {
    final AggregateValidationStatus s = 
      new AggregateValidationStatus(
        ctx, 
        AggregateValidationStatus.MAX_SEVERITY);

    master.addChangeListener(new IChangeListener()
      {

        public void handleChange(ChangeEvent event)
        {
          IStatus status = (IStatus)s.getValue();
          if (status != null &amp;&amp; !status.isOK())
          {
            ctx.updateTargets();
          }
        }
      });
  }
}
</pre>
<h2>Setting up a TableViewer with EMF-Databinding</h2>
<p>Let&#8217;s now take a look a the next topic for this post where we are going to set up a TableViewer using Eclipse-Databinding for JFace/SWT and EMF. The TableViewer is taking up the complete lower right part of the application<br />
<img src="http://tomsondev.files.wordpress.com/2009/06/tableviewer5.png?w=588" alt="Table Viewer" title="Table Viewer"   class="aligncenter size-full wp-image-410" /></p>
<p>In <a href="http://tomsondev.bestsolution.at/2009/06/08/galileo-emf-databinding-%E2%80%93-part-3/">part 3</a> we saw how to setup a TreeViewer, in <a href="http://tomsondev.bestsolution.at/2009/06/15/galileo-emf-databinding-part-4/">part 4</a> we saw how we are setting up a TableViewer without columns and as you&#8217;ll see setting up a TableViewer with multiple columns is very similar. Let&#8217;s take a look at the code first</p>
<pre class="brush: java; title: ; notranslate">
private void init(IViewSite site, 
  CTabFolder folder, 
  DataBindingContext ctx, 
  EditingDomain editingDomain, 
  IObservableValue master)
{
  final TableViewer viewer = new TableViewer(
    folder, SWT.FULL_SELECTION
  );

  viewer.getTable().setHeaderVisible(true);
  ObservableListContentProvider cp = 
    new ObservableListContentProvider()
  ;

  {
    IObservableMap[] attributeMap = new IObservableMap [2];
    attributeMap[0] = EMFEditProperties.value(
      editingDomain,
      FeaturePath.fromList(
        ProjectPackage.Literals.COMMITTER_SHIP__PERSON, 
        ProjectPackage.Literals.PERSON__LASTNAME
      )
    ).observeDetail(cp.getKnownElements());

    attributeMap[1] = EMFEditProperties.value(
      editingDomain,
      FeaturePath.fromList(
        ProjectPackage.Literals.COMMITTER_SHIP__PERSON, 
        ProjectPackage.Literals.PERSON__FIRSTNAME
      )
    ).observeDetail(cp.getKnownElements());

    TableViewerColumn column = new TableViewerColumn(
      viewer, SWT.NONE
    );
    column.getColumn().setText(&quot;Name&quot;);
    column.getColumn().setWidth(150);
    column.setLabelProvider(
      new GenericMapCellLabelProvider(
        &quot;{0}, {1}&quot;, 
        attributeMap
      )
    );
  }

  {
    IObservableMap attributeMap = EMFEditProperties.value(
      editingDomain, 
      ProjectPackage.Literals.COMMITTER_SHIP__START
    ).observeDetail(cp.getKnownElements());

    TableViewerColumn column = new TableViewerColumn(
      viewer, SWT.NONE
    );
    column.getColumn().setText(&quot;Start&quot;);
    column.getColumn().setWidth(100);
    column.setLabelProvider(
      new GenericMapCellLabelProvider(
        &quot;{0,date,short}&quot;, 
        attributeMap
      )
    );
  }

  {
    IObservableMap attributeMap = EMFEditProperties.value(
      editingDomain, 
      ProjectPackage.Literals.COMMITTER_SHIP__END
    ).observeDetail(cp.getKnownElements());

    TableViewerColumn column = new TableViewerColumn(
      viewer, SWT.NONE
    );
    column.getColumn().setText(&quot;End&quot;);
    column.getColumn().setWidth(100);
    column.setLabelProvider(
      new GenericMapCellLabelProvider(
        &quot;{0,date,short}&quot;, 
        attributeMap
      )
    );
  }

  IListProperty prop = EMFEditProperties.list(
    editingDomain, 
    ProjectPackage.Literals.PROJECT__COMMITTERS
  );
  viewer.setContentProvider(cp);
  viewer.setInput(prop.observeDetail(master));

  MenuManager mgr = new MenuManager();
  mgr.add(
    new Action(
      &quot;Hide historic committers&quot;, 
      IAction.AS_CHECK_BOX
    )
  {
    @Override
    public void run()
    {
      if (isChecked())
      {
        viewer.addFilter(new ViewerFilterImpl());
      }
      else
      {
        viewer.setFilters(new ViewerFilter [0]);
      }
    }
  });

  viewer.getControl().setMenu(
    mgr.createContextMenu(viewer.getControl())
  );
  site.registerContextMenu(
    Activator.PLUGIN_ID + &quot;.committers&quot;, mgr, viewer);
}
</pre>
<p>The only thing not already explained before is a special type of CellLabelProvider which allows one to use MessageFormat-Syntax to specify how the label is constructed. This label provider is not part of the JFace-Databinding implementation but written by me but it&#8217;s quite easy to implement.</p>
<pre class="brush: java; title: ; notranslate">
public class GenericMapCellLabelProvider 
  extends ObservableMapCellLabelProvider
{
  private IObservableMap[] attributeMaps;
  private String messagePattern;

  /**
   * Create a new label provider
   * @param messagePattern the message pattern
   * @param attributeMaps the values to observe
   */
  public GenericMapCellLabelProvider(
    String messagePattern, 
    IObservableMap... attributeMaps)
  {
    super(attributeMaps);
    this.messagePattern = messagePattern;
    this.attributeMaps = attributeMaps;
  }

  @Override
  public void update(ViewerCell cell)
  {
    Object element = cell.getElement();
    Object[] values = new Object [attributeMaps.length];
    int i = 0;
    for (IObservableMap m : attributeMaps)
    {
      values[i++] = m.get(element);
      if (values[i - 1] == null)
      {
        cell.setText(&quot;&quot;);
        return;
      }
    }
    cell.setText(
      MessageFormat.format(messagePattern, values)
    );
  }
}
</pre>
<p>That&#8217;s all we need to have a working TableViewer though there&#8217;s even more one can do with the Databinding-API e.g. Inline-Editing is supported and there are helpers to setup viewers in even less lines of code.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tomsondev.wordpress.com/384/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tomsondev.wordpress.com/384/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tomsondev.bestsolution.at&#038;blog=7995503&#038;post=384&#038;subd=tomsondev&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tomsondev.bestsolution.at/2009/06/27/galileo-emf-databinding-part-5/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cab59220024ebbf357443bf711c7f38?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">tomeclipsedev</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/detail_area_error.png" medium="image">
			<media:title type="html">Detail Area Error</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/tableviewer5.png" medium="image">
			<media:title type="html">Table Viewer</media:title>
		</media:content>
	</item>
		<item>
		<title>Galileo: EMF-Databinding &#8211; Part 4</title>
		<link>http://tomsondev.bestsolution.at/2009/06/15/galileo-emf-databinding-part-4/</link>
		<comments>http://tomsondev.bestsolution.at/2009/06/15/galileo-emf-databinding-part-4/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 20:33:09 +0000</pubDate>
		<dc:creator>Tom Schindl</dc:creator>
				<category><![CDATA[EMF]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://tomsondev.bestsolution.at/?p=326</guid>
		<description><![CDATA[Using the properties API in master-detail In the last blog entry we saw how to set up a the left part of our example application which is a JFace-TreeViewer. This blog article deals with the upper right part of the application who allows the user to edit the data of the selected project in the [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tomsondev.bestsolution.at&#038;blog=7995503&#038;post=326&#038;subd=tomsondev&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<h2>Using the properties API in master-detail</h2>
<p>In the last <a href="http://tomsondev.bestsolution.at/2009/06/08/galileo-emf-databinding-%E2%80%93-part-3/">blog entry</a> we saw how to set up a the left part of our example application which is a JFace-TreeViewer. This blog article deals with the upper right part of the application <img src="http://tomsondev.files.wordpress.com/2009/06/detail_area1.png?w=588" alt="detail_area" title="detail_area"   class="aligncenter size-full wp-image-328" /><br />
who allows the user to edit the data of the selected project in the <span style="font-family:Courier;">TreeViewer</span> which is a very common use case in Databinding and called Master-Detail-Scenario where the <span style="font-family:Courier;">TreeViewer</span> acts as the <strong>master</strong> and the upper right area as the <strong>detail part</strong>.</p>
<p><span style="font-size:large;">Creation of the master observable</span></p>
<p>Looking at the API for Master-Detail<br />
<img src="http://tomsondev.files.wordpress.com/2009/06/master_detail_api2.png?w=588" alt="Master Detail API" title="Master Detail API"   class="aligncenter size-full wp-image-365" /><br />
we recognize that we need to have a Master-ObservableValue</strong> when creating the <strong>Detail-ObservableValue</strong> so before we can proceed we need to go back to the <span style="font-family:Courier;">ProjectExplorerPart</span> who is responsible for the <span style="font-family:Courier;">TreeViewer</span> creation and make it provide us an <span style="font-family:Courier;">ObservableValue</span>.<br />
Most of the time the creation of the master observable is quite easy because the only thing one needs to do is to observe the current selection like this:</p>
<pre class="brush: java; title: ; notranslate">
private IObservableValue createMasterObs(Viewer viewer) {
 return ViewerProperties.singleSelection().observe(viewer);
}
</pre>
<p>but in our case it&#8217;s a bit more difficult because our tree has different object types (<span style="font-family:Courier;">Project</span> and <span style="font-family:Courier;">CommitterShip</span>) but our detail can only handle <span style="font-family:Courier;">Project</span>s which means we can&#8217;t use the selection directly but have to add a mediator in between.</p>
<p>The mediator we are useing is a <span style="font-family:Courier;">WritableValue</span> which we declare in the class body:</p>
<pre class="brush: java; title: ; notranslate">
/**
 * Part responsible for rendering the project tree
 */
public class ProjectExplorerPart
{
  // ...
  private IObservableValue master = new WritableValue();
  // ...
}
</pre>
<p>afterwards we observe the <span style="font-family:Courier;">TreeViewer-Selection</span> and adjust the <span style="font-family:Courier;">WritableValue</span> manually:</p>
<pre class="brush: java; title: ; notranslate">
private TreeViewer init(Composite parent, 
  Foundation foundation)
{
  TreeViewer viewer = new TreeViewer(parent);

  // ...

  IObservableValue treeObs = 
    ViewerProperties.singleSelection().observe(viewer);
  treeObs.addValueChangeListener(new IValueChangeListener() 
  {
    public void handleValueChange(ValueChangeEvent event) {
      if (event.diff.getNewValue() instanceof Project) {
        Project pr = (Project)event.diff.getNewValue();
        master.setValue(pr);
      } else if (event.diff.getNewValue() != null) {
        CommitterShip cm = 
          (CommitterShip)event.diff.getNewValue();
        master.setValue(cm.getProject());
      }     
    }
  });

  // ...
}
</pre>
<p><span style="font-size:large;">Create the detail part</span></p>
<p><span style="font-size:medium;">Binding with default conversion</span></p>
<p>We can now go on at the upper right side and use the obervable to bind our detail controls. All the code shown below resides in <span style="font-family:Courier;">ProjectFormAreaPart</span>. For standard text controls where no conversion is needed this is straight forward:</p>
<pre class="brush: java; title: ; notranslate">
private void createFormArea(
  IViewSite site,
  final Composite parent,
  FormToolkit toolkit,
  final IModelResource resource,
  ObservablesManager manager,
  final IObservableValue master)
{
  final EditingDomain editingDomain = 
    resource.getEditingDomain();
  ctx = new EMFDataBindingContext();

  // ...

  IWidgetValueProperty prop = 
    WidgetProperties.text(SWT.Modify);

  final IEMFValueProperty shortProp = 
    EMFEditProperties.value(
      editingDomain, 
      ProjectPackage.Literals.PROJECT__SHORTNAME
   );

  toolkit.createLabel(body, &quot;&amp;Short name&quot;);
  Text t = toolkit.createText(body, &quot;&quot;);
  t.setLayoutData(
    new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1)
  );
  ctx.bindValue(
    prop.observeDelayed(400, t), 
    shortProp.observeDetail(master)
  );
  // ...
}
</pre>
<p>Though as mentioned above it is straight forward there are still some things to notice:</p>
<ul>
<li><strong>EMFDatabindingContext</strong>: Is needed because <span style="font-family:Courier;">IEMFObservables</span> are exposing the <span style="font-family:Courier;">EStructuralFeature</span> as their value type but the default converters (e.g. <span style="font-family:Courier;">String</span> to <span style="font-family:Courier;">Integer</span>, <span style="font-family:Courier;">Integer</span> to <span style="font-family:Courier;">String</span>) who are created by the standard <span style="font-family:Courier;">DatabindingContext</span> work on top of <span style="font-family:Courier;">java.lang.Class</span> informations. <span style="font-family:Courier;">EMFDatabindingContext</span> uses default EMF conversion strageties and applies them instead.</li>
<li><strong>IWidgetValueProperty.observeDelayed(Widget,int)</strong>: This is an important detail to improve the users Undo/Redo experience because if not used every key stroke would result in an attribute change which would result in an undo/redo command. <span style="font-family:Courier;">IWidgetValueProperty.observeDelayed()</span> instructs the created observable to wait for 400 milliseconds before informing syncing the value back to the model and if another change happens within this time to cancel the update process and wait for another 400 milliseconds resulting in far less model changes and an improved undo/redo experience.</li>
</ul>
<p><span style="font-size:medium;">Binding with customized conversion</span></p>
<p>Now that we learned how to bind a Text-Widget to a <span style="font-family:Courier;">String</span>-property let&#8217;s take a look at another slightly more interesting binding use case &#8211; binding a Text-Widget to a <span style="font-family:Courier;">Date</span>-property which involves data conversion from <span style="font-family:Courier;">Date</span> to <span style="font-family:Courier;">String</span> and <span style="font-family:Courier;">String</span> to <span style="font-family:Courier;">Date</span>. <span style="font-family:Courier;">EMFDatabindingContext</span> comes with a standard implementation for this but our users might not expect to see a DateTime-Value including timezone informations when editing a date. So the first thing we need to do is create an improved <span style="font-family:Courier;">Date</span> to <span style="font-family:Courier;">String</span> and <span style="font-family:Courier;">String</span> to <span style="font-family:Courier;">Date</span> converter:</p>
<pre class="brush: java; title: ; notranslate">
/**
 * Convert a String to a date
 */
public class StringToDateConverter extends Converter
{
  private List&lt;DateFormat&gt; formats = 
    new ArrayList&lt;DateFormat&gt;();

  private String message;

  /**
   * New converter
   * @param message message when conversion fails
   */
  public StringToDateConverter(String message)
  {
    super(String.class, Date.class);
    this.message = message;
    formats.add(
      DateFormat.getDateInstance(DateFormat.SHORT)
    );
    formats.add(new SimpleDateFormat(&quot;yyyy-MM-dd&quot;));
  }

  public Object convert(Object fromObject)
  {
    if (fromObject != null 
      &amp;&amp; fromObject.toString().trim().length() == 0)
    {
      return null;
    }

    for (DateFormat f : formats)
    {
      try
      {
        return f.parse(fromObject.toString());
      }
      catch (ParseException e)
      {
        // Ignore
      }
    }

    throw new RuntimeException(message);
  }
}
</pre>
<p>To implement such a converter one normally inherits from a given base class named <span style="font-family:Courier;">Converter</span> and implements the <span style="font-family:Courier;">convert</span>-method. In this case the value conversion is done useing Java&#8217;s <span style="font-family:Courier;">DateFormat</span>-classes. As a special addon an empty <span style="font-family:Courier;">String</span> is converted into a <span style="font-family:Courier;">null</span> value. This converter is used as at the target to model side converting the value entered into the UI into the model type. The converter for the other side looks like this:</p>
<pre class="brush: java; title: ; notranslate">
/**
 * Convert a date to a string
 */
public class DateToStringConverter extends Converter
{
  private DateFormat format = 
    DateFormat.getDateInstance(DateFormat.SHORT);

  /**
   * New converter
   */
  public DateToStringConverter()
  {
    super(Date.class, String.class);
  }

  public Object convert(Object fromObject)
  {
    if (fromObject == null)
    {
      return &quot;&quot;;
    }
    return format.format(fromObject);
  }
}
</pre>
<p>To teach Eclipse-Databinding to use our custom converters instead of the default ones we simply need to set them on the <span style="font-family:Courier;">UpdateValueStrategy</span>s passed to <span style="font-family:Courier;">DatabindingContext.bindValue(IObservableValue,IObservableValue,UpdateValueStrategy,UpdateValueStrategy)</span>. Setting such a custom conversion strategy though leads to many lines of code you repeat in many places. What I do in my project to reduce this amout of code is to move the creation of a common <span style="font-family:Courier;">UpdateValueStrategy</span> like <span style="font-family:Courier;">String-Date-String</span> into a factory like this:</p>
<pre class="brush: java; title: ; notranslate">
public class UpdateStrategyFactory
{
  public static EMFUpdateValueStrategy stringToDate(
    String message)
  {
    EMFUpdateValueStrategy strat = 
      new EMFUpdateValueStrategy();

    StringToDateConverter c = 
      new StringToDateConverter(message);

    strat.setConverter(c);
    return strat;
  }

  /**
   * Create an update strategy which converts a date 
   * to a string
   * @return the update strategy
   */
  public static EMFUpdateValueStrategy dateToString()
  {
    EMFUpdateValueStrategy strat = 
      new EMFUpdateValueStrategy();
    DateToStringConverter c = new DateToStringConverter();
    strat.setConverter(c);
    return strat;
  }
}
</pre>
<p>resulting into binding code like this:</p>
<pre class="brush: java; title: ; notranslate">
IEMFValueProperty mProp = EMFEditProperties.value(
  editingDomain, 
  ProjectPackage.Literals.PROJECT__END
);

toolkit.createLabel(body, &quot;End Date&quot;);
Text t = toolkit.createText(body, &quot;&quot;);
t.setLayoutData(
  new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1)
);
ctx.bindValue(
  prop.observeDelayed(400, t),
  mProp.observeDetail(master),
  UpdateStrategyFactory.stringToDate(
    NLSMessages.ProjectAdminViewPart_EndDateNotParseable
  ),
  UpdateStrategyFactory.dateToString());
</pre>
<p><span style="font-size:medium;">Binding with customized conversion and validation</span></p>
<p>But there&#8217;s even more you can do with the <span style="font-family:Courier;">UpdateValueStrategy</span> &#8211; You ensure for example that an a project is not allowed to have an <span style="font-family:Courier;">empty</span> == <span style="font-family:Courier;">null</span> start date by setting an <span style="font-family:Courier;">IValidator</span> on the target to model <span style="font-family:Courier;">UpdateValueStrategy</span>. Once more this method is part of the <span style="font-family:Courier;">UpdateStrategyFactory</span> introduced above.</p>
<pre class="brush: java; title: ; notranslate">
/**
  * Create an update strategy which converts a string to 
  * a date and ensures that the date value on the 
  * destinations  is not set to null
  * @param convertMessage the message shown when 
  *   the conversion fails
  * @param validationMessage the message when the 
  *   value is set to null
  * @return the update strategy
  */
public static EMFUpdateValueStrategy stringToDateNotNull(
  String convertMessage, final String validationMessage)
{
  EMFUpdateValueStrategy strat = 
    stringToDate(convertMessage);

  strat.setBeforeSetValidator(new IValidator()
  {
    public IStatus validate(Object value)
    {
      if (value == null)
      {
        return new Status(
          IStatus.ERROR, 
          Activator.PLUGIN_ID, 
          validationMessage
        );
      }
      return Status.OK_STATUS;
    }
  });
  return strat;
}
</pre>
<p>and is used like this</p>
<pre class="brush: java; title: ; notranslate">
IEMFValueProperty mProp = EMFEditProperties.value(
  editingDomain, 
  ProjectPackage.Literals.PROJECT__START
);
toolkit.createLabel(body, &quot;Start Date&quot;);
Text t = toolkit.createText(body, &quot;&quot;);
t.setLayoutData(
  new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1)
);
ctx.bindValue(
  prop.observeDelayed(400, t), 
  mProp.observeDetail(master), 
  // Custom conversion
  UpdateStrategyFactory.stringToDateNotNull(
    NLSMessages.ProjectAdminViewPart_StartDateNotParseable,
    &quot;Start date must not be null&quot;
  ), 
  UpdateStrategyFactory.dateToString()
);
</pre>
<p>ensuring that the start date is not set to <span style="font-family:Courier;">null</span>.</p>
<p><span style="font-size:medium;">Binding to a list of values</span></p>
<p>The last binding presented is how to bind the value of a multi value attribute to to a Table-Widget which used as a List in this case.</p>
<pre class="brush: java; title: ; notranslate">
IEMFListProperty mProp = EMFEditProperties.list(
  editingDomain, 
  ProjectPackage.Literals.PROJECT__PROJECTLEADS);

toolkit.createLabel(body, &quot;Project Leads&quot;).setLayoutData(
  new GridData(SWT.TOP, SWT.DEFAULT, false, false)
);

Table c = toolkit.createTable(
  body, 
  SWT.MULTI | SWT.FULL_SELECTION 
  | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER
);

final TableViewer tv = new TableViewer(c);
tv.setLabelProvider(new ColumnLabelProvider()
{
  @Override
  public String getText(Object element)
  {
    Person p = (Person)element;
    return p.getLastname() + &quot;, &quot; + p.getFirstname();
  }
});
tv.setContentProvider(new ObservableListContentProvider());
tv.setInput(mProp.observeDetail(master));
</pre>
<p>The code shown here is not much different from the one showing how to setup a TreeViewer though much simpler for a none hierarchical widget. We are also using a default LabelProvider here instead of one who observes the attributes shown. Now let&#8217;s take a look at the dialog which gets opened when the Add &#8230; button is pressed.<br />
<img src="http://tomsondev.files.wordpress.com/2009/06/filter_dialog.png?w=588" alt="Filter Dialog" title="Filter Dialog"   class="aligncenter size-full wp-image-373" /><br />
The Eclipse-RCP-Framework provides a Dialog implementation named FilteredItemsSelectionDialog we can subclass and customize it</p>
<pre class="brush: java; title: ; notranslate">
/**
 * Dialog to find persons
 */
public class PersonFilterDialog extends 
  FilteredItemsSelectionDialog
{
  private final IModelResource resource;

  /**
   * Create a new dialog
   * @param shell the parent shell
   * @param resource the model resource
   */
  public PersonFilterDialog(Shell shell, 
    IModelResource resource)
  {
    super(shell);
    this.resource = resource;

    setListLabelProvider(new LabelProvider()
      {
        @Override
        public String getText(Object element)
        {
          if (element == null)
          {
            return &quot;&quot;;
          }
          return PersonFilterDialog.this.getText(
            (Person)element
          );
        }
      });

    setDetailsLabelProvider(new LabelProvider()
      {
        @Override
        public String getText(Object element)
        {
          if (element == null)
          {
            return &quot;&quot;;
          }
          return PersonFilterDialog.this.getText(
            (Person)element
          );
        }
      });
  }

  private String getText(Person p)
  {
    return p.getLastname() + &quot; &quot; + p.getFirstname();
  }

  @Override
  protected IStatus validateItem(Object item)
  {
    return Status.OK_STATUS;
  }

  @Override
  protected Comparator&lt; ? &gt; getItemsComparator()
  {
    return new Comparator&lt;Person&gt;()
      {

        public int compare(Person o1, Person o2)
        {
          return getText(o1).compareTo(getText(o2));
        }
      };
  }

  @Override
  public String getElementName(Object item)
  {
    Person p = (Person)item;
    return getText(p);
  }

  @Override
  protected IDialogSettings getDialogSettings()
  {
    IDialogSettings settings = Activator.getDefault()
      .getDialogSettings().getSection(&quot;committerdialog&quot;);

    if (settings == null)
    {
      settings = Activator.getDefault()
        .getDialogSettings()
        .addNewSection(&quot;committerdialog&quot;);
    }
    return settings;
  }

  @Override
  protected void fillContentProvider(
    AbstractContentProvider contentProvider, 
    ItemsFilter itemsFilter, 
    IProgressMonitor progressMonitor) throws CoreException
  {
    for (Person p : resource.getFoundation().getPersons())
    {
      if (progressMonitor.isCanceled())
      {
        return;
      }

      contentProvider.add(p, itemsFilter);
    }
  }

  @Override
  protected ItemsFilter createFilter()
  {
    return new ItemsFilter()
      {

        @Override
        public boolean isConsistentItem(Object item)
        {
          return true;
        }

        @Override
        public boolean matchItem(Object item)
        {
          Person p = (Person)item;
          return matches(p.getLastname() + &quot; &quot; 
            + p.getFirstname()
          );
        }

      };
  }

  @Override
  protected Control createExtendedContentArea(
    Composite parent)
  {
    return null;
  }
}
</pre>
<p>and use it in our code like this</p>
<pre class="brush: java; title: ; notranslate">
Button b = toolkit.createButton(
  buttonContainer, 
  &quot;Add ...&quot;, 
  SWT.FLAT);

gd = new GridData(SWT.DEFAULT, SWT.DEFAULT);
gd.horizontalAlignment = SWT.FILL;
b.setLayoutData(gd);
b.addSelectionListener(new SelectionAdapter()
{
  @Override
  public void widgetSelected(SelectionEvent e)
  {
    PersonFilterDialog dialog = new PersonFilterDialog(
      parent.getShell(), 
      resource
    );

    if (dialog.open() == IDialogConstants.OK_ID)
    {
      Command cmd = AddCommand.create(
        editingDomain,
        master.getValue(),
        ProjectPackage.Literals.PROJECT__PROJECTLEADS,
        dialog.getFirstResult());
      if (cmd.canExecute())
      {
        resource.executeCmd(cmd);
      }
    }
  }
});
</pre>
<p>That&#8217;s it for today in the next part we&#8217;ll take a look at setting up of TableViewer with different columns and how the nice validation stuff is working.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tomsondev.wordpress.com/326/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tomsondev.wordpress.com/326/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tomsondev.bestsolution.at&#038;blog=7995503&#038;post=326&#038;subd=tomsondev&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tomsondev.bestsolution.at/2009/06/15/galileo-emf-databinding-part-4/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cab59220024ebbf357443bf711c7f38?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">tomeclipsedev</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/detail_area1.png" medium="image">
			<media:title type="html">detail_area</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/master_detail_api2.png" medium="image">
			<media:title type="html">Master Detail API</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/filter_dialog.png" medium="image">
			<media:title type="html">Filter Dialog</media:title>
		</media:content>
	</item>
		<item>
		<title>Galileo: EMF-Databinding – Part 3</title>
		<link>http://tomsondev.bestsolution.at/2009/06/08/galileo-emf-databinding-%e2%80%93-part-3/</link>
		<comments>http://tomsondev.bestsolution.at/2009/06/08/galileo-emf-databinding-%e2%80%93-part-3/#comments</comments>
		<pubDate>Mon, 08 Jun 2009 21:41:09 +0000</pubDate>
		<dc:creator>Tom Schindl</dc:creator>
				<category><![CDATA[EMF]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://tomsondev.bestsolution.at/?p=291</guid>
		<description><![CDATA[Setting up a TreeViewer with EMF-Databinding The RCP-Application With this article we are starting to write our RCP-Application which uses Eclipse-Databinding. I&#8217;m not going into detail how you create an RCP-Application (I simply use the PDE-Wizard) but assume that you are familiar with this kind of thing. Still I&#8217;d like to describe the application design [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tomsondev.bestsolution.at&#038;blog=7995503&#038;post=291&#038;subd=tomsondev&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<h2>Setting up a TreeViewer with EMF-Databinding</h2>
<p><span style="font-size:large;">The RCP-Application</span><br />
With this article we are starting to write our RCP-Application which uses Eclipse-Databinding. I&#8217;m not going into detail how you create an RCP-Application (I simply use the PDE-Wizard) but assume that you are familiar with this kind of thing.</p>
<p>Still I&#8217;d like to describe the application design and the reason behind decisions I made a bit. The first and most important thing is that I&#8217;m not a fan of <span style="font-family:Courier;">EditorPart</span> and I think for none-file resources the IEditorInput stuff simply doesn&#8217;t make a lot of sense so all applications I&#8217;ve written since I develop RCP are <span style="font-family:Courier;">ViewPart</span>s. </p>
<p>A misconception I often see when I say that my RCP-Applications are free from editors is that people ask: &#8220;How are you going to be part of Workbench-Dirty/Save-Lifecyle if you use a ViewPart?&#8221;.</p>
<p>The answer is quite simple the only thing you have to do is to make your ViewPart implement <span style="font-family:Courier;">ISaveablePart2</span> and then your view is part of the workbench-dirty state lifecycle.</p>
<p><img src="http://tomsondev.files.wordpress.com/2009/06/appparts.png?w=588" alt="Application Parts" title="Application Parts"   class="aligncenter size-full wp-image-294" /></p>
<p>The screen shot from above shows that how the applications UI code is broken up in smaller logical parts:</p>
<ul>
<li><span style="color:rgb(0,174,0);">ProjectAdminViewPart:</span><br />
This is the main UI area which is subclassing <span style="font-family:Courier;">ViewPart</span> and registered into the workbench usin the views-Extension-Point.
</li>
<li><span style="color:rgb(255,0,0);">ProjectExplorerPart:</span><br />
This class makes up the left part of the application showing a TreeViewer to select project, create subprojects, &#8230; . The internals of this part are described in more detail in this blog post later on.
</li>
<li><span style="color:rgb(0,0,255);">ProjectFormAreaPart:</span><br />
This class makes up the right upper part showing a set of input controls who act as a detail part of the <span style="color:rgb(255,0,0);">ProjectExplorerPart</span>. The internals of this part are explained in detail in Part 4 of this blog series.
</li>
<li><span style="color:rgb(255,102,51);">ProjectCommittersPart:</span><br />
This class makes up the right lower part showing a <span style="font-family:Courier;">TableViewer</span>. The internals of this part are explained in detail in Part 5 of this blog series.
</li>
</ul>
<p>Before we dive into the main topic of this blog post I&#8217;d like to show some interesting code found inside the ProjectAdminViewPart because it shows some interesting RCP features and introduces a small but often forgotten databinding stuff leading to memory leaks in conjunction with databinding.</p>
<p><span style="font-size:medium;">Restoring view state information</span><br />
The first interesting thing is that the content of the main area is created using a <span style="font-family:Courier;">SashForm</span> to give the user the possibility to define how much space the <span style="color:rgb(255,0,0);">left part</span> should occupy. The user naturally expects that when he starts the application the next time that the UI comes up in the same state it&#8217;s been when shutting down so we need to store the sash-weights when shutting down and restore them on the next start up.</p>
<p>The Eclipse-RCP-Framework provides a possibility to make this happen by using an IMemento to persist informations across application launches the only thing you to do is to use the API:</p>
<pre class="brush: java; title: ; notranslate">
public class ProjectAdminViewPart 
  extends ViewPart implements ISaveablePart2
{
  private float divider = 0.2f;
  private SashForm sashForm;

  @Override
  public void init(final IViewSite site, IMemento memento) 
    throws PartInitException
  {
    super.init(site, memento);
    if (memento != null 
      &amp;&amp; memento.getFloat(DIVIDER_KEY) != null)
    {
      divider = memento.getFloat(DIVIDER_KEY);
    }

    listener = new PartListenerImpl(site);
    site.getPage().addPartListener(listener);
  }

  @Override
  public void saveState(IMemento memento)
  {
    super.saveState(memento);
    int total = sashForm.getWeights()[0] 
                       + sashForm.getWeights()[1];
    memento.putFloat(
      DIVIDER_KEY, 
      sashForm.getWeights()[0] * 1.f / total);
  }

  @Override
  public void createPartControl(Composite parent)
  {
    // ...
    sashForm = new SashForm(parent, SWT.HORIZONTAL);
    // ...
    int left = (int)(100 * divider);
    sashForm.setWeights(new int []{ left, 100 - left });
  }
}
</pre>
<p><span style="font-size:medium;">Avoid listener leaking</span><br />
There&#8217;s something I very often see in databinding code from various people (even those who have a lot of databinding knowledge) is that they are not diposing their observables once not more needed which leads to memory leaks. This means that we have to remember all observables created and dispose them manually when not needed any more. </p>
<p>An exception to this are observables created for SWT-Widgets because they dispose themselves when the SWT-Widget is disposed but for all others the rule is the one who created it has to dispose it. Databinding provides a class named <span style="font-family:Courier;">ObservablesManager</span> which helps you with this. </p>
<p>In 3.5 EMF-Databinding added new API to ObservableManager which would make collecting observables very easy but apparently a bug was found very late in the release cycle and so the API is not useable currently. The API in question is used like this:</p>
<pre class="brush: java; title: ; notranslate">
ObservablesManager mgr = new ObservablesManager();
mgr.runAndCollect(new Runnable()
  {
    public void run()
    {
      // your code which creates observables
    }
  });
</pre>
<p>Though the default API is broken for EMF-Databinding we can add an easy fix so that the API at least collects all <span style="font-family:Courier;">IEMFObservable</span> so that we only have to deal with things like ComputedValue and such stuff because as stated above SWT-Observables dispose themselves when the SWT-Widget is disposed.</p>
<p>So our code looks like this:</p>
<pre class="brush: java; title: ; notranslate">
  @Override
  public void createPartControl(Composite parent)
  {
    // ...
    /* 
     * Track the creation of observables so that we 
     * don't leak listeners when the view part is closed
     */
    mgr = new EMFObservablesManager();
    defaultMgr = new ObservablesManager();
    mgr.runAndCollect(new Runnable()
      {

        public void run()
        {
          projectExplorer = new ProjectExplorerPart(
            getViewSite(), 
            sashForm, 
            toolkit, 
            resource.getFoundation(), 
            defaultMgr);

          projectDataForm = new ProjectFormAreaPart(
            getViewSite(),
            sashForm,
            toolkit,
            resource,
            defaultMgr,
            projectExplorer.getProjectObservable());
        }
      });
    // ...
  }
</pre>
<p><span style="font-size:large;">Setting up a TreeViewer</span><br />
Enough about the generic stuff and let&#8217;s now concentrate on the main topic of this blog.<br />
<img src="http://tomsondev.files.wordpress.com/2009/06/tree_viewer1.png?w=588" alt="Project Explorer" title="Project Explorer"   class="aligncenter size-full wp-image-300" /><br />
Though I guess most of you know how to set up a standard TreeViewer here a short description:</p>
<ol>
<li>Set a <span style="font-family:Courier;">CellLabelProvider</span>: Responsible to translate the model object into a visual representation (text,colors,image,&#8230;). The CellLabelProvider-API was introduced in 3.3 and on top it JFace provides many cool new features like StyledText-Support (different fonts and colors in one cell) and ToolTip-Support. It&#8217;s worth revisiting your old code and replace <span style="font-family:Courier;">LabelProvider</span> through <span style="font-family:Courier;">CellLabelProvider</span> subclasses</li>
<li>Set an <span style="font-family:Courier;">ITreeContentProvider</span>: Responsible to translate the input into a tree-structure.</li>
<li>Set an input: Any input the ITreeContentProvider can handle</li>
</ol>
<p><span style="font-size:large;">Createing the content provider</span><br />
The Eclipse-RCP-Platform comes with a plugin named <b>org.eclipse.jface.databinding</b> which provides databinding support and implementation classes for SWT and JFace controls. One of those classes is <span style="font-family:Courier;">ObservableListTreeContentProvider</span> which is a class implementing the <span style="font-family:Courier;">ITreeContentProvider</span> and makes setting up an observed tree quite easily.</p>
<p>The <span style="font-family:Courier;">ObservableListTreeContentProvider</span> can&#8217;t do all the work on its own but expects us to provide it helper classes:</p>
<ul>
<li><span style="font-family:Courier;">TreeFactory</span>: responsible to create <span style="font-family:Courier;">IObservableList</span>s to observe the childitems of a treenode</li>
<li><span style="font-family:Courier;">TreeStructureAdvisor</span>: responsible to provide informations on how to access the model parent of an item and helping to make the decision if an item has child-items</li>
</ul>
<p>Looking at the picture above shows us that our structure is a bit of an virtual one when we compare it to the domain instance where we would only see the project-subprojects relation on the first sight.<br />
<img src="http://tomsondev.files.wordpress.com/2009/06/ecore_project.png?w=588" alt="Project Class" title="Project Class"   class="aligncenter size-full wp-image-131" /><br />
Our viewer though displays to different multi-value features as children in the Tree:</p>
<ul>
<li>subprojects whose elements are of type Project</li>
<li>committerships whose elements are of type CommitterShip</li>
</ul>
<p>Displaying different Object-Types was not supported in 3.4 and is a new feature in the new Databinding implementation as well as the possibility to combine 2 multi-value features into a single observable list which is for me personally one of the coolest features in the Properties-API.</p>
<pre class="brush: java; title: ; notranslate">
  private static class TreeFactoryImpl 
    implements IObservableFactory
  {
    private IEMFListProperty multi = EMFProperties.multiList(
      ProjectPackage.Literals.PROJECT__SUBPROJECTS,
      ProjectPackage.Literals.PROJECT__COMMITTERS);

    public IObservable createObservable(final Object target)
    {
      if (target instanceof IObservableList)
      {
        return (IObservable)target;
      }
      else if (target instanceof Project)
      {
        return multi.observe(target);
      }

      return null;
    }
  }

  private static class TreeStructureAdvisorImpl 
    extends TreeStructureAdvisor
  {
    @Override
    public Object getParent(Object element)
    {
      if (element instanceof Project)
      {
        return ((Project)element).getParent();
      }

      return null;
    }

    @Override
    public Boolean hasChildren(Object element)
    {
      if (element instanceof Project 
        &amp;&amp; (
          ((Project)element).getCommitters().size() &gt; 0 
          || ((Project)element).getSubprojects().size() &gt; 0
        )
      )
      {
        return Boolean.TRUE;
      }
      return super.hasChildren(element);
    }
  }
</pre>
<p>and used like this</p>
<pre class="brush: java; title: ; notranslate">
private TreeViewer init(Composite parent, 
  Foundation foundation)
{
  TreeViewer viewer = new TreeViewer(parent);
  ObservableListTreeContentProvider cp = 
    new ObservableListTreeContentProvider(
      new TreeFactoryImpl(), 
      new TreeStructureAdvisorImpl()
  );
  viewer.setContentProvider(cp);
  
  // rest of viewer setup
}
</pre>
<p><span style="font-size:large;">Createing the CellLabelProvider</span><br />
To get such a nice looking tree we can&#8217;t use a simple CellLabelProvider (e.g. ColumnLabelProvider is a simple implementation of it) but need one with more features. Another CellLabelProvider implementation is the StyledCellLabelProvider which uses owner-draw to draw StyledText-Strings in the tree.</p>
<p>JFace-Databinding doesn&#8217;t provide an implementation for StyledCellLabelProvider out of the box so I had to write my own one but that&#8217;s not too hard. The only thing which has to be done is to attach a listener to IObservableMap(s) to observe attributes of all tree elements and update the viewer if one of them changes.</p>
<pre class="brush: java; title: ; notranslate">
private class TreeLabelProviderImpl 
  extends StyledCellLabelProvider
{
  private IMapChangeListener mapChangeListener = 
    new IMapChangeListener()
    {
      public void handleMapChange(MapChangeEvent event)
      {
        Set&lt;?&gt; affectedElements = 
          event.diff.getChangedKeys();
        if (!affectedElements.isEmpty())
        {
          LabelProviderChangedEvent newEvent = 
            new LabelProviderChangedEvent(
              TreeLabelProviderImpl.this, 
              affectedElements.toArray()
          );
          fireLabelProviderChanged(newEvent);
        }
      }
    };

  public TreeLabelProviderImpl(
    IObservableMap... attributeMaps)
  {
    for (int i = 0; i &lt; attributeMaps.length; i++)
    {
      attributeMaps[i].addMapChangeListener(
        mapChangeListener
      );
    }
  }

  @Override
  public String getToolTipText(Object element)
  {
    return &quot;#dummy#&quot;;
  }

  @Override
  public void update(ViewerCell cell)
  {
    if (cell.getElement() instanceof Project)
    {
      Project p = (Project)cell.getElement();

      StyledString styledString = new StyledString(
        p.getShortname()!=null ? p.getShortname():&quot;*noname*&quot;,
        null
      );
      String decoration = &quot; (&quot; + 
        p.getCommitters().size() + &quot; Committers)&quot;;
      styledString.append(
        decoration, 
        StyledString.COUNTER_STYLER
      );
      cell.setText(styledString.getString());
      cell.setImage(projectImage);
      cell.setStyleRanges(styledString.getStyleRanges());
    }
    else if (cell.getElement() instanceof CommitterShip)
    {
      Person p = (
        (CommitterShip)cell.getElement()
      ).getPerson();
      String value = &quot;*noname*&quot;;
      if (p != null)
      {
        value = p.getLastname() + &quot;, &quot; + p.getFirstname();
      }
      StyledString styledString = new StyledString(
        value, null);
      cell.setText(styledString.getString());
      cell.setForeground(
        cell.getControl().getDisplay().getSystemColor(
          SWT.COLOR_DARK_GRAY
        )
      );
      cell.setImage(committerImage);
      cell.setStyleRanges(styledString.getStyleRanges());
    }
  }
}
</pre>
<p>and used like this</p>
<pre class="brush: java; title: ; notranslate">
private TreeViewer init(Composite parent, 
  Foundation foundation)
{
  TreeViewer viewer = new TreeViewer(parent);
  ObservableListTreeContentProvider cp = 
    new ObservableListTreeContentProvider(
      new TreeFactoryImpl(), 
      new TreeStructureAdvisorImpl()
  );
  viewer.setContentProvider(cp);

  IObservableSet set = cp.getKnownElements();
  IObservableMap[] map = new IObservableMap [4];

  map[0] = EMFProperties.value(
    ProjectPackage.Literals.PROJECT__SHORTNAME
  ).observeDetail(set);

  map[1] = EMFProperties.value(
    ProjectPackage.Literals.PROJECT__COMMITTERS
  ).observeDetail(set);

  map[2] = EMFProperties.value(
      FeaturePath.fromList(
        ProjectPackage.Literals.COMMITTER_SHIP__PERSON,
        ProjectPackage.Literals.PERSON__FIRSTNAME)
      ).observeDetail(set);

  map[3] = EMFProperties.value(
      FeaturePath.fromList(
        ProjectPackage.Literals.COMMITTER_SHIP__PERSON, 
        ProjectPackage.Literals.PERSON__LASTNAME)
      ).observeDetail(set);

  viewer.setLabelProvider(new TreeLabelProviderImpl(map));
  // Further viewer setup
</pre>
<p>The last step is to set the input of the viewer which has to be an IObservableList which is in our example all top-level projects who are restored in the foundation instance.</p>
<pre class="brush: java; title: ; notranslate">
IEMFListProperty projects = EMFProperties.list(
  ProjectPackage.Literals.FOUNDATION__PROJECTS
);
viewer.setInput(projects.observe(foundation));
</pre>
<p>There is even more code in the ProjectExplorerPart e.g. a customized ColumnViewerToolTipSupport to create the nice looking ToolTips when hovering items of the tree as well as some RCP-Code to allow plugin.xml to contribute a context menu but that&#8217;s standard JFace and RCP code.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tomsondev.wordpress.com/291/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tomsondev.wordpress.com/291/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tomsondev.bestsolution.at&#038;blog=7995503&#038;post=291&#038;subd=tomsondev&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tomsondev.bestsolution.at/2009/06/08/galileo-emf-databinding-%e2%80%93-part-3/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cab59220024ebbf357443bf711c7f38?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">tomeclipsedev</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/appparts.png" medium="image">
			<media:title type="html">Application Parts</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/tree_viewer1.png" medium="image">
			<media:title type="html">Project Explorer</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/ecore_project.png" medium="image">
			<media:title type="html">Project Class</media:title>
		</media:content>
	</item>
		<item>
		<title>Galileo: EMF-Databinding &#8211; Part 2</title>
		<link>http://tomsondev.bestsolution.at/2009/06/07/galileo-emf-databinding-part-2/</link>
		<comments>http://tomsondev.bestsolution.at/2009/06/07/galileo-emf-databinding-part-2/#comments</comments>
		<pubDate>Sun, 07 Jun 2009 14:31:16 +0000</pubDate>
		<dc:creator>Tom Schindl</dc:creator>
				<category><![CDATA[EMF]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://tomsondev.bestsolution.at/?p=175</guid>
		<description><![CDATA[Introduce the new Properties API In 3.5 Eclipse-Databinding introduces a new API which should be used in favor of the 3.4 EMFObservables-Factory because it provides many features who couldn&#8217;t be provided by the old API (e.g. the new API provides you with the possibility to observe nested attributes in Table/TreeViewers, allows you do observe different [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tomsondev.bestsolution.at&#038;blog=7995503&#038;post=175&#038;subd=tomsondev&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<h2>Introduce the new Properties API</h2>
<p>In 3.5 Eclipse-Databinding introduces a new API which should be used in favor of the 3.4 EMFObservables-Factory because it provides many features who couldn&#8217;t be provided by the old API (e.g. the new API provides you with the possibility to observe nested attributes in Table/TreeViewers, allows you do observe different object types in the same viewer which is very handy in case of a TreeViewer).</p>
<p>Like in previous releases the Core-Eclipse-Databinding bundles define an API and provide an abstract base implementations and downstream modules need to provide the concrete implementation for the domain model implementation and its notification system.</p>
<p>Let&#8217;s take a look at the bundles and their dependencies:<br />
<a href="http://tomsondev.files.wordpress.com/2009/06/plugin-dependencies2.png"><img src="http://tomsondev.files.wordpress.com/2009/06/plugin-dependencies2.png?w=588" alt="Plugin Dependencies" title="Plugin Dependencies"   class="aligncenter size-full wp-image-307" /></a></p>
<p>As you notice EMF-Databinding is split into 2 bundles:</p>
<ul>
<li><strong>org.eclipse.emf.databinding</strong>: The core implementation of the Eclipse-Databinding-API which makes changes using <span style="font-family:Courier;">EObject#eSet()</span>, <span style="font-family:Courier;">EObject#eAdd()</span> and <span style="font-family:Courier;">EObject#eRemove()</span> methods</li>
<li><strong>org.eclipse.emf.databinding.edit</strong>: Implementation which builds upon the EMF-Databinding-Core implementation but uses features provided by the EMF-Edit. Changes to the model instance are not made directly on the model-instance but are done by executing EMF-Commands on so called EditingDomain. Going through this additional framework provides us new features like Undo/Redo-Support. Naturally whenever you get new features you have to pay a price &#8211; going through this additional API causes a bit overhead.</li>
</ul>
<p>An example might make the difference between modifying a domain instance in pure EMF vs EMF-Edit clearer. In pure EMF setting the lastname attribute of a Person is done like this:</p>
<pre class="brush: java; title: ; notranslate">
public void example(Person p) {
  p.eSet(
    ProjectPackage.Literals.PERSON__LASTNAME,
    &quot;Schindl&quot;
  );
}
</pre>
<p>And when using EMF-Edit:</p>
<pre class="brush: java; title: ; notranslate">
public void example(EditingDomain eDomain, Person p) {
  Command cmd = SetCommand.create(
    eDomain, 
    p, 
    ProjectPackage.Literals.PERSON__LASTNAME, 
    &quot;Schindl&quot;);

  if( cmd.canExecute() ) {
    eDomain.getCommandStack().execute(cmd);
  }
}
</pre>
<p>Now that we saw the highlevel overview it&#8217;s time to take a closer look at the new Eclipse-Databinding-API. It is called Properties-API because of the name of the root interface <span style="font-family:Courier;">org.eclipse.core.databinding.property.IProperty</span>.</p>
<p><a href="http://tomsondev.files.wordpress.com/2009/06/interface_overview6.png"><img class="aligncenter size-full wp-image-236" title="Interface and Class Overview" src="http://tomsondev.files.wordpress.com/2009/06/interface_overview6.png?w=588" alt="Interface and Class Overview"   /></a></p>
<p><span style="font-size:large;"><strong>The nature of nested properties</strong></span><br />
A nested property is a property which is not the direct member of an observed class but one of its member instances. In our example application we have many different nested properties for example the lastname of a committer:<br />
<a href=""><img src="http://tomsondev.files.wordpress.com/2009/06/committer_lastname.png?w=588" alt="Nested Lastname Property" title="Nested Lastname Property"   class="aligncenter size-full wp-image-259" /></a><br />
If we have a CommitterShip instance we are not able to directly access the last name but have to go through the person-property.</p>
<pre class="brush: java; title: ; notranslate">
public void example(CommitterShip cship) {
  // CommitterShip.person
  Person p = cship.eGet(
    ProjectPackage.Literals.COMMITTER_SHIP__PERSON
  );

  // Person.lastname
  String lastname = p.eGet(
    ProjectPackage.Literals.PERSON__LASTNAME
  );
}
</pre>
<p>What we are doing here is traversing the object-tree to get access to the property we are interested in and this traversal is often referred to as following a path through the model.</p>
<p>Observing nested properties is quite a common use case but the 3.4 Databinding-API didn&#8217;t provided such support out of the box though it was available in some situations. </p>
<p>This changed with the new Properties-API which has built in support for nested properties and so the EMF-Databinding honors this with a set of factory methods (see below for more informations on this) and one special class describing the path to a nested property.<br />
<a href="http://tomsondev.files.wordpress.com/2009/06/feature_path_class.png"><img src="http://tomsondev.files.wordpress.com/2009/06/feature_path_class.png?w=588" alt="Feature Path" title="Feature Path"   class="aligncenter size-full wp-image-257" /></a></p>
<p>So specifing the path shown above we&#8217;d write Java code like this:</p>
<pre class="brush: java; title: ; notranslate">
// /person/lastname
FeaturePath path = FeaturePath.fromList(
  ProjectPackage.Literals.COMMITTER_SHIP__PERSON,
  ProjectPackage.Literals.PERSON__LASTNAME
);
</pre>
<p><span style="font-size:large;"><strong>The Factories</strong></span><br />
The EMF-Databinding implementations hide the implementation behind 2 factories:</p>
<p><span style="font-size:small;"><strong>EMFProperties</strong></span><br />
<a><img class="aligncenter size-full wp-image-240" title="EMFProperties-Factory" src="http://tomsondev.files.wordpress.com/2009/06/emf_properties_class.png?w=588" alt="EMFProperties-Factory"   /></a></p>
<p>This class provides factory methods to create instances of <span style="font-family:Courier;">IEMFValueProperty</span>, <span style="font-family:Courier;">IEMFListProperty</span> and <span style="font-family:Courier;">IEMFMapProperty</span> by passing the <span style="font-family:Courier;">EStructuralFeature</span> or the path to a nested EStructuralFeature the property should represent.</p>
<pre class="brush: java; title: ; notranslate">
// Direct attribute
IEMFProperty pSurname = EMFProperties.value(
  ProjectPackage.Literals.PERSON__LASTNAME
);

// Nested attribute
IEMFProperty committerSurname = EMFProperties.value(
  FeaturePath.fromList(
    ProjectPackage.Literals.COMMITTER_SHIP__PERSON,
    ProjectPackage.Literals.PERSON__LASTNAME
  )
);
</pre>
<p><span style="font-size:small;"><strong>EMFEditProperties</strong></span><br />
<a href="http://tomsondev.files.wordpress.com/2009/06/emf_edit_properties_class1.png"><br />
<img src="http://tomsondev.files.wordpress.com/2009/06/emf_edit_properties_class1.png?w=588" alt="EMF-Edit Factory" title="EMF-Edit Factory"   class="aligncenter size-full wp-image-263" /></a><br />
This class provides factory methods to create instances of <span style="font-family:Courier;">IEMFEditValueProperty</span>, <span style="font-family:Courier;">IEMFEditListProperty</span> and <span style="font-family:Courier;">IEMFEditMapProperty</span> by passing the <span style="font-family:Courier;">EStructuralFeature</span> or the path to a nested <span style="font-family:Courier;">EStructuralFeature</span> the property should represent and the <span style="font-family:Courier;">EditingDomain</span> through which the modifications are made.</p>
<p>The usage of the API is very similar to the one of EMFProperties</p>
<pre class="brush: java; title: ; notranslate">
// Direct attribute
IEMFEditProperty pSurname = EMFEditProperties.value(
  eDomain,
  ProjectPackage.Literals.PERSON__LASTNAME
);

// Nested attribute
IEMFEditProperty committerSurname = EMFEditProperties.value(
  eDomain,
  FeaturePath.fromList(
    ProjectPackage.Literals.COMMITTER_SHIP__PERSON,
    ProjectPackage.Literals.PERSON__LASTNAME
  )
);
</pre>
<p><span style="font-size:large;"><strong>Observing single value attributes/properties</strong></span><br />
<a href="http://tomsondev.files.wordpress.com/2009/06/value_property4.png"><img src="http://tomsondev.files.wordpress.com/2009/06/value_property4.png?w=588" alt="value_property" title="value_property"   class="aligncenter size-full wp-image-271" /></a></p>
<p>The <span style="font-family:Courier;">IValueProperty</span> implementations <span style="font-family:Courier;">IEMFValueProperty</span> and <span style="font-family:Courier;">IEMFEditValueProperty</span> provide the possibility to create observables of single value attribute/properties of an object like the lastname of Person.</p>
<p><a href="http://tomsondev.files.wordpress.com/2009/06/emf_value_property2.png"><img src="http://tomsondev.files.wordpress.com/2009/06/emf_value_property2.png?w=588" alt="emf_value_property" title="emf_value_property"   class="aligncenter size-full wp-image-280" /></a></p>
<p>Let&#8217;s take a look how we can use this new API in our Java-Code. Code below only uses the Pure-EMF-API and not the EMF-Edit one because the only difference would be the creation of the IValueProperty (The <span style="font-family:Courier;">EditingDomain</span> has to be passed there).</p>
<pre class="brush: java; title: ; notranslate">
// 1. Use case - Create an observable
public IObservableValue uc1(Person p) {
  IEMFValueProperty prop = EMFProperties.value(
    ProjectPackage.Literals.PERSON__LASTNAME
  );
  return prop.observe(p);
}

// 2. Use case - Create an observable for a nested attribute
public IObservableValue uc2(CommitterShip c) {
  IEMFValueProperty prop = EMFProperties.value(
    FeaturePath.fromList(
      ProjectPackage.Literals.COMMITTER_SHIP__PERSON,
      ProjectPackage.Literals.PERSON__LASTNAME
    )
  );
  return prop.observe(c);
}

// 3. Use case - Create multiple observables
public IObservableValue[] uc3(Person p) {
  IEMFValueProperty[] props = EMFProperties.values(
    ProjectPackage.Literals.PERSON__LASTNAME,
    ProjectPackage.Literals.PERSON__FIRSTNAME,
  );
  return new IObservableValue[] { 
    props[0].observe(p), 
    props[1].observe(p) 
  };
}

// 4. Use case - Create multiple observables 
// for a nested attributes
public IObservableValue[] uc4(CommitterShip c) {
  IEMFValueProperty[] props = EMFProperties.values(
    FeaturePath.fromList(
      ProjectPackage.Literals.COMMITTER_SHIP__PERSON,
      ProjectPackage.Literals.PERSON__LASTNAME
    ),
    FeaturePath.fromList(
      ProjectPackage.Literals.COMMITTER_SHIP__PERSON,
      ProjectPackage.Literals.PERSON__FIRSTNAME
    )
  );
  return new IObservableValue[] { 
    props[0].observe(c), 
    props[1].observe(c) 
  };
}

// 5. Use case - Create a detail observable
public IObservableValue uc5(IObservableValue master) {
  IEMFValueProperty prop = EMFProperties.value(
    ProjectPackage.Literals.PERSON__LASTNAME
  );
  return prop.observeDetail(master);
}

// 6. Use case - Observe the lastname 
// attribute of list of persons
public IObservableMap uc6(IObservableSet persons) {
  IEMFValueProperty prop = EMFProperties.value(
    ProjectPackage.Literals.PERSON__LASTNAME
  );
  return prop.observeDetail(persons);
}
</pre>
<p><span style="font-size:large;"><strong>IEMFListProperty/IEMFEditListProperty</strong></span><br />
<a href="http://tomsondev.files.wordpress.com/2009/06/list_property.png"><img src="http://tomsondev.files.wordpress.com/2009/06/list_property.png?w=588" alt="list_property" title="list_property"   class="aligncenter size-full wp-image-279" /></a></p>
<p>The <span style="font-family:Courier;">IListProperty</span> implementations <span style="font-family:Courier;">IEMFListProperty</span> and <span style="font-family:Courier;">IEMFEditListProperty</span> provide the possibility to create observables of multi valued attribute/properties like e.g. subprojects of a project.</p>
<p><a href="http://tomsondev.files.wordpress.com/2009/06/emf_list_property1.png"><img src="http://tomsondev.files.wordpress.com/2009/06/emf_list_property1.png?w=588" alt="emf_list_property" title="emf_list_property"   class="aligncenter size-full wp-image-283" /></a><br />
Let&#8217;s take a look at some lines of Java how we are using this API:</p>
<pre class="brush: java; title: ; notranslate">
// 1. Use case - observe the subprojects
public IObservableList uc1(Project p) {
  IEMFListProperty prop = EMFProperties.list(
    ProjectPackage.Literals.PROJECT__SUBPROJECTS
  );
  return prop.observe(p);
}

// 2. Use case - observe the nested list
// The list of all subprojects of the projects parent
public IObservableList uc2(Project p) {
  IEMFListProperty prop = EMFProperties.list(
    FeaturePath.formList(
      ProjectPackage.Literals.PROJECT__PROJECT,
      ProjectPackage.Literals.PROJECT__SUBPROJECTS
    )
  );
  return prop.observe(p);
}

// 3. Use case - Observe a detail list
public IObservableList uc3(IObservableValue master) {
  IEMFListProperty prop = EMFProperties.list(
    ProjectPackage.Literals.PROJECT__SUBPROJECTS
  );
  return prop.observeDetail(master);
}

// 4. Use case - Combine to lists into one
public IObservableList uc4(Project p) {
  IEMFListProperty prop = EMFProperties.multiList(
      ProjectPackage.Literals.PROJECT__SUBPROJECTS,
      ProjectPackage.Literals.PROJECT__COMMITTERS
  );
  return prop.observe(p);
}
</pre>
<p><span style="font-size:large;"><strong>IEMFMapProperty/IEMFEditMapProperty</strong></span><br />
We are not useing maps in the example code so I&#8217;m not going to show the API in detail here but the idea behind it should be quite obvious. With the type of properties you can observe an java.util.Map-Type of multi-valued property.</p>
<p><span style="font-size:large;"><strong><span style="color:red;">NO</span> IEMFSetProperty/IEMFEditSetProperty</strong></span><br />
You might ask why those to files are grayed out a bit in the screenshot. The reason is that support for this didn&#8217;t made it into EMF 2.5 but we are looking into it for 2.6.</p>
<p><span style="font-size:large;"><strong>Hidden secrets of the properties API</strong></span><br />
The IProperty API is quite an impressive piece of API &#8211; extremly powerful but still easy to use and in the next parts of this blog series we&#8217;ll see most the API in action. One of it&#8217;s big advantages is that it decouples the creation of the observable from specifying which attribute/property from which domain model one likes to observe which is really powerful when it comes to writing API code which should be domain model agnostic.</p>
<p>Suppose we write a library on top of Eclipse-Databinding which allows us to create text-input-forms in a more condensed way but the API should be useable with any domain model technology.</p>
<p>If we&#8217;d used the 3.4 Observables-Factories like (BeanObservables, EMFObservables, EMFEditObservables) we would have to write an specialized implementation for every widget technology because the specification of the attribute and how the binding is created is different for each of them.</p>
<p>Using the new Properties-API which defines a common description of a property a observable is going to be created later would lead to an API like this.</p>
<pre class="brush: java; title: ; notranslate">
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.property.value.IValueProperty;
import org.eclipse.jface.databinding.swt.IWidgetValueProperty;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import org.eclipse.emf.databinding.EMFUpdateValueStrategy;

/**
 * Helper class which builds a two column form 
 * with labels and text-fields
 * @param the value property type
 */
public class FormBuilder&lt;P extends IValueProperty&gt;
{
  private class Entry
  {
    private String label;
    private P property;
    private String nullMessage;

    private Entry(String label, 
      P property, 
      String nullMessage)
    {
      this.label = label;
      this.property = property;
      this.nullMessage = nullMessage;
    }
  }

  private List&lt;Entry&gt; entries = new ArrayList&lt;Entry&gt;();

  /**
   * Add a text entry
   * @param label the label to display
   * @param property the property to bind
   * @param nullMessage the message shown 
   *               when the property gets set to null
   */
  public void addTextEntry(String label, 
    P property, 
    String nullMessage)
  {
    entries.add(
      new Entry(label, property, nullMessage)
    );
  }

  /**
   * Build a two column form with the elements added
   *
   * @param dbc the databinding context
   * @param parent the parent the form is created on
   * @param object the object to bind
   * @return the form container
   */
  public Composite build(DataBindingContext dbc, 
    Composite parent, 
    Object object)  {
    Composite container = new Composite(parent, SWT.NONE);
    container.setLayout(new GridLayout(2, false));

    IWidgetValueProperty textProp = WidgetProperties.text(
      SWT.Modify
    );

    for (Entry e : entries)
    {

      Label l = new Label(container, SWT.NONE);
      l.setText(e.label);

      Text t = new Text(container, SWT.BORDER);
      t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

      IObservableValue uiObs = textProp.observeDelayed(
        400, t
      );
      IObservableValue mObs;

      if (object instanceof IObservableValue)
      {
        mObs = e.property.observeDetail(
          (IObservableValue)object
        );
      }
      else
      {
        mObs = e.property.observe(object);
      }

      dbc.bindValue(
        uiObs, 
        mObs, 
        new EMFUpdateValueStrategy().setBeforeSetValidator(
          new EmptyStringValidator(e.nullMessage)
        ), 
        null
      );
    }

    return container;
  }
}
</pre>
<p>The <a href="http://wiki.eclipse.org/UFaceKit">UFaceKit</a>-project has a similar abstraction to provide domain model agnostic API so something like this was doable also before the introduction of the new API. Still having this concept at the core of the implementation is highly appreciated.</p>
<p>Now that we got introduced into the most important parts of the new Properties-API we are ready to start working on our programm in the next blog series.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tomsondev.wordpress.com/175/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tomsondev.wordpress.com/175/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tomsondev.bestsolution.at&#038;blog=7995503&#038;post=175&#038;subd=tomsondev&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tomsondev.bestsolution.at/2009/06/07/galileo-emf-databinding-part-2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cab59220024ebbf357443bf711c7f38?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">tomeclipsedev</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/plugin-dependencies2.png" medium="image">
			<media:title type="html">Plugin Dependencies</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/interface_overview6.png" medium="image">
			<media:title type="html">Interface and Class Overview</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/committer_lastname.png" medium="image">
			<media:title type="html">Nested Lastname Property</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/feature_path_class.png" medium="image">
			<media:title type="html">Feature Path</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/emf_properties_class.png" medium="image">
			<media:title type="html">EMFProperties-Factory</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/emf_edit_properties_class1.png" medium="image">
			<media:title type="html">EMF-Edit Factory</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/value_property4.png" medium="image">
			<media:title type="html">value_property</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/emf_value_property2.png" medium="image">
			<media:title type="html">emf_value_property</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/list_property.png" medium="image">
			<media:title type="html">list_property</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/emf_list_property1.png" medium="image">
			<media:title type="html">emf_list_property</media:title>
		</media:content>
	</item>
		<item>
		<title>Galileo: EMF-Databinding &#8211; Part 1</title>
		<link>http://tomsondev.bestsolution.at/2009/06/06/galileo-emf-databinding-part-1/</link>
		<comments>http://tomsondev.bestsolution.at/2009/06/06/galileo-emf-databinding-part-1/#comments</comments>
		<pubDate>Sat, 06 Jun 2009 16:36:46 +0000</pubDate>
		<dc:creator>Tom Schindl</dc:creator>
				<category><![CDATA[EMF]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://tomsondev.wordpress.com/?p=52</guid>
		<description><![CDATA[Creation of the Domain-Model Before we can start with the domain model for our application we need to know what the model is going to be for. So let me explain the application we are going to write in this blog series: Suppose the Eclipse Foundation hired you to write an application which allows them [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tomsondev.bestsolution.at&#038;blog=7995503&#038;post=52&#038;subd=tomsondev&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<h2>Creation of the Domain-Model</h2>
<p>Before we can start with the domain model for our application we need to know<br />
what the model is going to be for. So let me explain the application we are<br />
going to write in this blog series:</p>
<p><span style="font-family:Courier;">Suppose the Eclipse Foundation hired you to write an application which allows them to administrate their committer and project metadata.</span></p>
<p>We now need to create a domain model of this minimal information given<br />
which could potentially look like this:<br />
<a href="http://tomsondev.files.wordpress.com/2009/06/ecorescreen.png"><img src="http://tomsondev.files.wordpress.com/2009/06/ecorescreen.png?w=588" alt="Screen shot of the Ecore-Editor" title="Screen shot of the Ecore-Editor"   class="alignnone size-full wp-image-128" /></a><br />Let&#8217;s take a closer look on the domain model objects:</p>
<ul>
<li>Foundation<br />
<a href="http://tomsondev.files.wordpress.com/2009/06/ecore_foundation.png"><img src="http://tomsondev.files.wordpress.com/2009/06/ecore_foundation.png?w=588" alt="Foundation Class" title="Foundation Class"   class="alignnone size-full wp-image-130" /></a><br />The root of the domain model is the foundation which has 2 list properties:</p>
<ul>
<li><strong>projects:</strong> top level projects like EMF, Technology, Platform, &#8230;</li>
<li><strong>persons:</strong> persons who take a part in one ore multiple projects</li>
</ul>
</li>
<li>Project<br />
<a href="http://tomsondev.files.wordpress.com/2009/06/ecore_project.png"><img src="http://tomsondev.files.wordpress.com/2009/06/ecore_project.png?w=588" alt="Project Class" title="Project Class"   class="alignnone size-full wp-image-131" /></a><br />An Eclipse project has many diﬀerent properties from the project start to the project end date to the url of the homepage.  The most interesting ones are:</p>
<ul>
<li><strong>subprojects</strong>: a project can have subprojects who can then itself have subprojects</li>
<li><strong>parent</strong>: a project has one parent pro ject (beside the top-level ones) &#8211; this means projet-subprojects relation is modeled as a bidirectional relationship</li>
<li><strong>projectleads</strong>: a projet can have multiple project leads</li>
<li><strong>committers</strong>: a project has multiple committers</li>
</ul>
</li>
<li>CommitterShip<br />
<a href="http://tomsondev.files.wordpress.com/2009/06/ecore_committership1.png"><img src="http://tomsondev.files.wordpress.com/2009/06/ecore_committership1.png?w=588" alt="Committership Class" title="Committership Class"   class="alignnone size-full wp-image-133" /></a><br />People who are committers on a project get a so called committership which has a start and end date. The most interesting of them are:
<ul>
<li><strong>project</strong>: the project the committership is for &#8211; this means once more that the committership-project relation is modeled as a bidirectional relationship</li>
<li><strong>person</strong>: the person who holds the committership</li>
</ul>
</li>
<li>Person<br />
<a href="http://tomsondev.files.wordpress.com/2009/06/ecore_person.png"><img src="http://tomsondev.files.wordpress.com/2009/06/ecore_person.png?w=588" alt="Person Class" title="Person Class"   class="alignnone size-full wp-image-134" /></a><br />The “real” person who gets committer or project lead on a project. The ﬁeld of interest here is:
<ul>
<li><strong>committerships</strong>: which holds all committerships a person has this means that the committership-person relation is also once more modeled as a bidirectional relationship</li>
</ul>
</li>
</ul>
<p>To get a highlevel overview above the model and how the classes are related together the Class-Diagram helps a lot:<br />
<a href="http://tomsondev.files.wordpress.com/2009/06/project.png"><img src="http://tomsondev.files.wordpress.com/2009/06/project.png?w=588" alt="Ecore-Class-Diagram" title="Ecore-Class-Diagram"   class="alignnone size-full wp-image-126" /></a><br />
As you noticed I modeled many of the relations as bidirectional relations. This is not strictly need everywhere because some of the relations like project-subproject have an implicit parent relation because they are containments and hence eContainer() could be used to access the parent. Still when it comes to databinding such a containment relationship doesn&#8217;t help because there&#8217;s no feature you can use to navigate from child to container but only the call to the method eContainer().</p>
<p>EMF also provides an editor to create an instance of your Ecore-Model and save it to XMI which makes it easy for us to create test data. An example of an XMI looks like this:<br />
<a href="http://tomsondev.files.wordpress.com/2009/06/xmi.png"><img src="http://tomsondev.files.wordpress.com/2009/06/xmi.png?w=588" alt="XMI-File" title="XMI-File"   class="alignnone size-full wp-image-141" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tomsondev.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tomsondev.wordpress.com/52/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tomsondev.bestsolution.at&#038;blog=7995503&#038;post=52&#038;subd=tomsondev&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://tomsondev.bestsolution.at/2009/06/06/galileo-emf-databinding-part-1/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6cab59220024ebbf357443bf711c7f38?s=96&#38;d=&#38;r=G" medium="image">
			<media:title type="html">tomeclipsedev</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/ecorescreen.png" medium="image">
			<media:title type="html">Screen shot of the Ecore-Editor</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/ecore_foundation.png" medium="image">
			<media:title type="html">Foundation Class</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/ecore_project.png" medium="image">
			<media:title type="html">Project Class</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/ecore_committership1.png" medium="image">
			<media:title type="html">Committership Class</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/ecore_person.png" medium="image">
			<media:title type="html">Person Class</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/project.png" medium="image">
			<media:title type="html">Ecore-Class-Diagram</media:title>
		</media:content>

		<media:content url="http://tomsondev.files.wordpress.com/2009/06/xmi.png" medium="image">
			<media:title type="html">XMI-File</media:title>
		</media:content>
	</item>
	</channel>
</rss>
