Sapphire Developer Guide > Releases > 0.3.1

Enhancements in 0.3.1

  1. Expression Language
    1. Cast Between Collections and Strings
    2. InstanceOf Function
  2. Services
    1. DependenciesService
    2. FileExtensionsService
  3. Diagram Editor
    1. Guides Toggle
    2. Diagram Layout
    3. Diagram Tool Palette Customization
    4. Visible When Condition for Diagram Nodes
  4. Java Developer Tools Support
    1. Create Action
  5. Miscellaneous
    1. Byte, Short and Date Values
    2. Optional 'I' Prefix
    3. Visible When Condition for Properties View Pages
    4. Content Outline Validation Message Tool Tip

Cast Between Collections and Strings

Transparently cast between collections and strings. The following rules have been added:

Example

The following two expressions are equivalent.

${ "z" IN List( "x", "y", "z" ) }
${ "z" IN "x,y,z" }

See Documentation

InstanceOf Function

Determines if an object is of specified type. The object to be checked is the first operand and the type is the second operand. The type must be a fully-qualified Java class name.

Example

${ InstanceOf( 12345, "java.lang.Number" ) }
${ InstanceOf( SampleProperty, "org.eclipse.sapphire.samples.ISampleModelElement" ) }

DependenciesService

Use services infrastructure to specify dependencies between properties. Existing annotations such as @DependsOn and @NoDuplicates are now backed by DependenciesService implementations.

Example

@DependsOn( "Name" )

ValueProperty PROP_ID = new ValueProperty( TYPE, "Id" );

Value<String> getId();
void setId( String value );

Example

public class CustomDependenciesService extends DependenciesService
{
    @Override
    protected void compute( Set<ModelPath> dependencies )
    {
        // Compute the list of extensions.
    }
}
@Service( impl = CustomDependenciesService.class )

ValueProperty PROP_NAME = new ValueProperty( TYPE, "Name" );

Value<String> getName();
void setName( String value );

See Documentation

FileExtensionsService

Specify file extensions with expression language capable @FileExtensions annotation or with a completely custom implementation of FileExtensionsService.

Example

@Type( base = Path.class )
@AbsolutePath
@MustExist
@ValidFileSystemResourceType( FileSystemResourceType.FILE )
@FileExtensions( expr = "${ LossyFormat ? "jpeg,jpg" : "png,gif" }" )

ValueProperty PROP_FILE_PATH = new ValueProperty( TYPE, "FilePath" );

Value<Path> getFilePath();
void setFilePath( String value );
void setFilePath( Path value );

Example

public class CustomFileExtensionsService extends FileExtensionsService
{
    @Override
    public void initFileExtensionsService( IModelElement element,
                                           ModelProperty property,
                                           String[] params )
    {
        // Optionally register listeners to invoke refresh method when the list of extensions
        // may need to be updated.
    }

    @Override
    protected void compute( List<String> extensions )
    {
        // Compute the list of extensions.
    }

    @Override
    public void dispose()
    {
        super.dispose();

        // Remove any listeners that were added during initialization.
    }
}
@Type( base = Path.class )
@AbsolutePath
@MustExist
@ValidFileSystemResourceType( FileSystemResourceType.FILE )
@Service( impl = CustomFileExtensionsService.class )

ValueProperty PROP_FILE_PATH = new ValueProperty( TYPE, "FilePath" );

Value<Path> getFilePath();
void setFilePath( String value );
void setFilePath( Path value );

See Documentation

Diagram Guides Toggle

The alignment guides can be toggled by the user via a context menu and the default state can be specified by the developer in the diagram definition.

Example

<diagram-page>
    <guides>
        <visible>true</visible>
    </guides>        
</diagram-page>

Diagram Layout

Users can now trigger diagram layout when necessary via the context menu. Two modes are supported: horizontal layout and vertical lyout. In addition to manually triggering layout, when the diagram editor is opened, if the corresponding layout file cannot be found, horizontal layout will be used.

Diagram Tool Palette Customization

The diagram tool palette compartments can be customized in the diagram definition.

Example

<diagram-page>
    <palette>
        <compartment>
            <id>connections</id>
            <label>my connections</label>
        </compartment>
        <compartment>
            <id>nodes</id>
            <label>my objects</label>
        </compartment>
    </palette>        
</diagram-page>

Developer can also control which compartment of the tool palette to place each node or connection creation tool in the node or connection definition.

Example

<node>
    <tool-palette-compartment>connections</tool-palette-compartment>
</node>

If no compartments are defined in diagram page definition, there'll be two default compartments: one for connections and one for nodes. The default compartment label for connections is "Connections" and the default id is "Sapphire.Diagram.Palette.Connections". The default compartment label for nodes is "Objects" and the default id is "Sapphire.Diagram.Palette.Nodes".

Visible When Condition for Diagram Nodes

Use Sapphire Expression Language to specify when diagram nodes of certain type should be shown. When the condition evaluates to false, the palette will not show the node entry and any existing nodes of this type will be hidden.

<diagram-page>
    <node>
        <visible-when>${ Root().DetailLevel GE 2 }</visible-when>
    </node>
<diagram-page>

Java Type Create Action

The Java type support has been further improved with addition of an action that can create a new Java type if the specified type name cannot be resolved.

Example

@Type( base = JavaTypeName.class )
@Reference( target = JavaType.class )
@Label( standard = "filter" )
@JavaTypeConstraint( kind = { JavaTypeKind.CLASS, JavaTypeKind.INTERFACE }, type = "java.io.FileFilter" )
@MustExist
@Required

ValueProperty PROP_FILTER = new ValueProperty( TYPE, "Filter" );

ReferenceValue<JavaTypeName,JavaType> getFilter();
void setFilter( String value );
void setFilter( JavaTypeName value );

Since @JavaTypeConstraint annotation in this example specifies that the property can reference either a class or an interface, the user is presented with a choice after clicking on the create button.

Once the appropriate option is selected, the new type is created and opened in the Java editor. The created type derives from the type specified in @JavaTypeConstraint annotation and is formatted according to user's format preferences.

Byte, Short and Date Values

Use Byte, Short and Date types for value properties without writing a custom serialization service. The serialization service for Date is configurable and can be subclassed to meet the date format requirements.

Example

In this example, the framework's default Date serialization logic is used.

@Type( base = Date.class )

ValueProperty PROP_DATE = new ValueProperty( TYPE, "Date" );

Value<Date> getDate();
void setDate( String value );
void setDate( JavaTypeName value );

Example

In this example, the framework's DateSerializationService implementation is used, but is configured with specific formats.

@Type( base = Date.class )
@ValueSerialization( service = DateSerializationService.class, params = { "yyyy.MM.dd", "MM/dd/yyyy" } )

ValueProperty PROP_DATE = new ValueProperty( TYPE, "Date" );

Value<Date> getDate();
void setDate( String value );
void setDate( JavaTypeName value );

Example

In this example, the framework's DateSerializationService is subclassed to create a custom serialization service..

public class CustomDateSerializationService extends DateSerializationService
{
    private final static List<DateFormat> FORMATS;

    static 
    {
        final List<DateFormat> formats = new ArrayList<DateFormat>();
        formats.add( new SimpleDateFormat( "dd.MM.yyyy" ) );
        formats.add( new SimpleDateFormat( "yyyy/MM/dd" ) );

        FORMATS = Collections.unmodifiableList(formats);
    };

    @Override
    public List<? extends DateFormat> formats()
    {
        return FORMATS;
    }

}
@Type( base = Date.class )
@ValueSerialization( service = CustomDateSerializationService.class )

ValueProperty PROP_DATE = new ValueProperty( TYPE, "Date" );

Value<Date> getDate();
void setDate( String value );
void setDate( JavaTypeName value );

Optional 'I' Prefix

Sapphire adopters are no longer required to utilize the convention of prefixing 'I' in front of interface names when defining model elements. The @GenerateImpl annotation has a new className attribute for explicitly controlling the implementation class name. The default implementation class name is now defined as follows:

if( using 'I' prefix convention )
{
    default implementation class name is typeClassName.substring( 1 )
}
else
{
    default implementation class name is typeClassName + "Impl"
}

Visible When Condition for Properties View Pages

Use Sapphire Expression Language to specify when contributed properties view pages should be shown.

<properties-view>
    <page>
        <label>provider</label>
        <visible-when>${ Root().DetailLevel GE 2 }</visible-when>
        <content>
            ...
        </content>
    </page>
</properties-view>

Content Outline Validation Message Tool Tip

Easily see the aggregate validation messages by hovering over a node in the content outline.