Migration Guide for 0.2
This documents covers code changes that need to be made by Sapphire adopters as part of migrating
to 0.2 release. Only changes from the previous milestone are covered.
Table of Contents
- Annotations
- Element Properties
- NoDuplicates and UniqueValueValidator
- SapphireEditorForXml
- SapphireCondition
- Browse Handlers
- Jump Handlers
- Action Links
- Dynamic Label
- Project Metadata
- Miscellaneous
Annotations
Annotations on model elements:
Before |
After |
@DefaultValue( "something" )
|
@DefaultValue( text = "something" )
|
@DefaultValueProvider( impl = CustomImpl.class )
public class CustomImpl extends DefaultValueProviderImpl
{
...
}
|
@DefaultValue( service = CustomImpl.class )
public class CustomImpl extends DefaultValueService
{
...
}
|
@PossibleValuesFromModel( path = "/SomeProperty" )
|
@PossibleValues( property = "/SomeProperty" )
|
@PossibleValuesProvider( impl = CustomImpl.class )
public class CustomImpl extends PossibleValuesProviderImpl
{
...
}
|
@PossibleValues( service = CustomImpl.class )
public class CustomImpl extends PossibleValuesService
{
...
}
|
@ValueSerializer( impl = CustomImpl.class )
public class CustomImpl extends ValueSerializerImpl
{
...
}
|
@ValueSerialization( service = CustomImpl.class )
public class CustomImpl extends ValueSerializationService
{
...
}
|
@Enabler( impl = CustomImpl.class )
public class CustomImpl extends EnablerImpl
{
...
}
|
@Enablement( service = CustomImpl.class )
public class CustomImpl extends EnablementService
{
...
}
|
@EnabledWhen( "..." )
|
@Enablement( expr = "..." )
|
@EnabledByBooleanProperty( "SomeProperty" )
|
@Enablement( expr = "${ SomeProperty }" )
|
@EnabledByEnumProperty( property = "SomeProperty", values = { "A", "B", "C" } )
|
@Enablement( expr = "${ SomeProperty == 'A' || SomeProperty == 'B' || SomeProperty == 'C' }" )
|
@Reference( target = Object.class, resolver = CustomImpl.class )
public class CustomImpl extends ReferenceResolverImpl
{
...
}
|
@Reference( target = Object.class, service = CustomImpl.class )
public class CustomImpl extends ReferenceService
{
...
}
|
Element Properties
Before |
After |
@Type( base = IAddress.class )
ElementProperty PROP_ADDRESS = new ElementProperty( TYPE, "Address" );
IAddress getAddress();
...
@GenerateXmlBinding( elementPath = "address" )
public interface IAddress extends IModelElementForXml
{
...
}
|
@Type( base = IAddress.class )
@XmlBinding( path = "address" )
ImpliedElementProperty PROP_ADDRESS = new ImpliedElementProperty( TYPE, "Address" );
IAddress getAddress();
...
@GenerateImpl
public interface IAddress extends IModelElement
{
...
}
|
@Type( base = IAssistant.class )
@XmlBinding( path = "assistant" )
ElementProperty PROP_ASSISTANT = new ElementProperty( TYPE, "Assistant" );
IAssistant getAssistant();
IAssistant getAssistant( boolean createIfNecessary );
|
@Type( base = IAssistant.class )
@XmlBinding( path = "assistant" )
ElementProperty PROP_ASSISTANT = new ElementProperty( TYPE, "Assistant" );
ModelElementHandle<IAssistant> getAssistant();
|
<with>
<property>Address</property>
<content>
...
</content>
</with>
|
<with>
<property>Address</property>
<default-panel>
<content>
...
</content>
</default-panel>
</with>
|
<element-property-composite>
<property>Assistant</property>
<conditional>delegate some tasks to an assistant</conditional>
<default-panel>
<content>
...
</content>
</default-panel>
</element-property-composite>
|
<with>
<property>Assistant</property>
<label>delegate some tasks to an assistant</label>
<panel>
<key>IAbc</key>
<content>
...
</content>
</panel>
</with>
|
The following Eclipse search/replace regular expressions can be use to perform the last migration
migration in the table:
Scope: *.sdef
Search: (?s)<element-property-composite>(.*?)<conditional>(.*?)</conditional>(.*?)<default-panel>(.*?)</default-panel>(.*?)</element-property-composite>
Replace: <with>\1<label>\2</label>\3<panel><key>?????</key>\4</panel>\5</with>
After applying the above search and replace, look for <key>?????</key> in your sdef files and specify
the actual key. In this case, it would be the type name of the element held by the property.
NoDuplicates and UniqueValueValidator
The @NoDuplicates
annotation is now applied to a value property (for elements
contained in a list) rather than the list property. It can be used any place where
UniqueValueValidator
class has previously been used.
Before |
After |
@DependsOn( "*/Name" )
@Validator( impl = UniqueValueValidator.class )
ValueProperty PROP_NAME = new ValueProperty( TYPE, "Name" );
|
@NoDuplicates
ValueProperty PROP_NAME = new ValueProperty( TYPE, "Name" );
|
@Type( base = IConnection.class )
@NoDuplicates
ListProperty PROP_CONNECTIONS = new ListProperty( TYPE, "Connections" );
ModelElementList<IConnection> getConnections();
...
public interface IConnection extends IModelElement
{
@DependsOn( "*/Name" )
@Validator( impl = UniqueValueValidator.class )
ValueProperty PROP_NAME = new ValueProperty( TYPE, "Name" );
}
|
@Type( base = IConnection.class )
ListProperty PROP_CONNECTIONS = new ListProperty( TYPE, "Connections" );
ModelElementList<IConnection> getConnections();
...
public interface IConnection extends IModelElement
{
@NoDuplicates
ValueProperty PROP_NAME = new ValueProperty( TYPE, "Name" );
}
|
SapphireEditorForXml
Before |
After |
public class SampleEditor extends SapphireEditorForXml
{
public SampleEditor()
{
super( "org.something.ui" );
setEditorDefinitionPath( "org.something.ui/sdef/SampleEditor.sdef/main" );
}
@Override
protected IModel createModel( ModelStore modelStore )
{
...
}
}
|
public class SampleEditor extends SapphireEditorForXml
{
public SampleEditor()
{
super( "org.something.ui" );
setRootModelElementType( ISampleModel.TYPE );
setEditorDefinitionPath( "org.something.ui/sdef/SampleEditor.sdef/main" );
}
}
|
SapphireCondition
Any existing implementations of SapphireCondition that override getDependencies() method should be
changed to override SapphireModelCondition instead.
Before |
After |
public class SampleCondition extends SapphireCondition
{
@Override
public boolean evaluate()
{
...
}
@Override
public List getDependencies()
{
...
}
}
|
public class SampleCondition extends SapphireModelCondition
{
@Override
public boolean evaluate()
{
...
}
@Override
public List getDependencies()
{
...
}
}
|
Browse Handlers
Browse handler definition in the UI definition file:
Before |
After |
<property-editor>
<browse-handler>
<class>MyBrowseHandler</class>
</browse-handler>
</property-editor>
|
<property-editor>
<action-handler>
<action>Sapphire.Browse</action>
<impl>MyBrowseHandler</impl>
</action-handler>
</property-editor>
|
Browse handler definition in an extension:
Before |
After |
<plugin>
<extension point="org.eclipse.sapphire.ui.browseHandlers">
<browse-handler factory="org.something.MyBrowseHandlerFactory"/>
</extension>
</plugin>
|
Sapphire no longer uses Eclipse extension system. Instead, create
sapphire-extension.xml file in the META-INF folder. The extension must be located in the
same classloader as Sapphire. On an OSGi system this is done by creating a fragment to
the org.eclipse.sapphire.ui bundle.
Note that the factory concept has been removed. The browse handler implementation class
is specified directly. Applicability is controlled by a separate condition class that
must extends SapphireCondition.
<extension xmlns="http://www.eclipse.org/sapphire/xmlns/extension">
<action-handler>
<action>Sapphire.Browse</action>
<impl>org.something.MyBrowseHandler</impl>
<condition>org.something.MyBrowseHandlerCondition</condition>
</action-handler>
</extension>
|
Browse handler implementation:
Before |
After |
public class MyBrowseHandler extends BrowseHandler
{
@Override
public String browse( SapphireRenderingContext context )
{
...
}
}
|
public class MyBrowseHandler extends SapphireBrowseActionHandler
{
@Override
public String browse( SapphireRenderingContext context )
{
...
}
}
|
Jump Handlers
Jump handler definition in the UI definition file:
Before |
After |
<property-editor>
<jump-handler>
<class>MyJumpHandler</class>
</jump-handler>
</property-editor>
|
<property-editor>
<action-handler>
<action>Sapphire.Jump</action>
<impl>MyJumpHandler</impl>
</action-handler>
</property-editor>
|
Jump handler definition in an extension:
Before |
After |
<plugin>
<extension point="org.eclipse.sapphire.ui.jumpHandlers">
<jump-handler class="org.something.MyJumpHandler"/>
</extension>
</plugin>
|
Sapphire no longer uses Eclipse extension system. Instead, create
sapphire-extension.xml file in the META-INF folder. The extension must be located in the
same classloader as Sapphire. On an OSGi system this is done by creating a fragment to
the org.eclipse.sapphire.ui bundle.
Note that the logic from the isApplicable method needs to be extracted into a separate
condition class. The condition class must extend SapphireCondition.
<extension xmlns="http://www.eclipse.org/sapphire/xmlns/extension">
<action-handler>
<action>Sapphire.Jump</action>
<impl>org.something.MyJumpHandler</impl>
<condition>org.something.MyJumpHandlerCondition</condition>
</action-handler>
</extension>
|
Jump handler implementation:
Before |
After |
public class MyJumpHandler extends JumpHandler
{
@Override
public boolean isApplicable( ValueProperty property )
{
return true;
}
@Override
public int getPriority()
{
return 0;
}
@Override
public boolean canLocateJumpTarget( SapphirePart part,
SapphireRenderingContext context,
IModelElement element,
ValueProperty property )
{
// Logic for evaluating whether the jump handler is active goes here.
return false
}
@Override
public void jump( SapphirePart part,
SapphireRenderingContext context,
IModelElement element,
ValueProperty property )
{
// Logic for executing the jump goes here.
}
}
|
The isApplicable method has been replaced with a separate condition class that
is specified as part of handler definition. This is usually only necessary when
a jump handler is contributed in an extension (as opposed to locally as part of
a property editor definition).
The getPriority method has been replaced with location hints specified as part of
handler definition.
public class MyJumpHandler extends SapphireJumpActionHandler
{
@Override
public void init( SapphireAction action,
ISapphireActionHandlerDef def )
{
super.init( def );
// Setup listeners on external resources relevant in determining whether
// the jump handler is active. The listeners should call refreshEnablementState
// method. If a listener infrastructure is not available, a polling thread
// can be used instead.
// If all relevant resources are other properties in the same model, skip
// overriding this method and override initDependencies method instead.
}
@Override
protected void initDependencies( List<String> dependencies )
{
super.initDependencies( dependencies );
// The default implementation will add the property whose editor the jump handler
// is attached to. If the enablement state of the jump handler is dependent on other
// properties in the model, paths to those properties should be added here.
}
@Override
protected void refreshEnablementState()
{
// Logic for evaluating whether the jump handler is active goes here.
setEnabled( false );
}
@Override
protected Object run( SapphireRenderingContext context )
{
// Logic for executing the jump goes here.
return null;
}
@Override
public void dispose()
{
super.dispose();
// Remove listeners and stop threads configured in the init method.
}
}
|
Action Links
Defined by referencing existing action:
Before |
After |
<content>
<action-link>
<action-id>node:add</action-id>
<label>Add a contact</label>
</action-link>
</content>
|
While the XML markup for definining action links hasn't changed for this
scenario, the IDs for all system actions have changed. The appropriate
system action ID can be found here.
<content>
<action-link>
<action-id>Sapphire.Add</action-id>
<label>Add a contact</label>
</action-link>
</content>
|
Defined by referencing existing action handler:
Before |
After |
<content>
<action-link>
<action-id>node:add:IListItemWithInteger</action-id>
<label>Add a list item with integer</label>
</action-link>
</content>
|
<content>
<action-link>
<action-id>Sapphire.Add</action-id>
<action-handler-id>Sapphire.Add.IListItemWithInteger</action-handler-id>
<label>Add a list item with integer</label>
</action-link>
</content>
|
Defined with inline action implementation:
Before |
After |
<content>
<action-link>
<action-class>MyAction</action-class>
<label>Link</label>
</action-link>
</content>
|
<content>
<action-link>
<action-id>MyAction</action-id>
<label>Link</label>
<action>
<id>MyAction</id>
</action>
<action-handler>
<action>MyAction</action>
<impl>MyActionHandler</impl>
</action-handler>
</action-link>
</content>
|
Dynamic Label
With the new support for expressions, some old workarounds have been retired. One of these
is the "dynamic-label" used for specifying label for the content outline. You must now use
an expression to achieve the same affect.
Before |
After |
<node-list>
<node-template>
<dynamic-label>
<property>Name</property>
<null-value-label><contact></null-value-label>
</dynamic-label>
</node-template>
</node-list>
|
<node-list>
<node-template>
<label>${ Name == null ? "<contact>" : Name }</label>
</node-template>
</node-list>
|
The following Eclipse search/replace regular expressions can be use to perform this
migration:
Scope: *.sdef
Search: <dynamic-label>\s*<property>(.*)</property>\s*<null-value-label>(.*)</null-value-label>\s*</dynamic-label>
Replace: <label>\$\{ \1 == null \? \"\2\" \: \1 \}</label>
Project Metadata
In the .project file:
Before |
After |
<buildCommand>
<name>org.eclipse.sapphire.ui.builder</name>
<arguments>
<dictionary>
<key>input</key>
<value>sdef</value>
</dictionary>
<dictionary>
<key>output</key>
<value>.resources/sdef</value>
</dictionary>
</arguments>
</buildCommand>
|
<buildCommand>
<name>org.eclipse.sapphire.sdk.builder</name>
<arguments>
</arguments>
</buildCommand>
|
In the customBuildCallbacks.xml file:
Before |
After |
<taskdef
resource="org/eclipse/sapphire/ui/build/antlib.xml"
classpathref="sapphire.classpath"/>
<sapphire.extract-string-resources src="sdef" dest=".resources/sdef"/>
|
<taskdef
resource="org/eclipse/sapphire/sdk/build/antlib.xml"
classpathref="sapphire.classpath"/>
<sapphire src="." dest=".resources"/>
|
Miscellaneous
Child property editor definition:
Before |
After |
<property-editor>
<child-property>
<name>MyChildProperty</name>
</child-property>
</property-editor>
|
<property-editor>
<child-property>
<property>MyChildProperty</property>
</child-property>
</property-editor>
|