When a property is described to a user in documentation one does it with a series of short statements that define its semantics, such as "must be specified" or "maximum value is 100". When a property is described to Sapphire one does it with a series of annotations, such as @Required or @NumericRange. This duplicate specification is a maintenance problem.
A FactsService provides a means to dynamically derive statements about property's semantics based on property's metadata. The derived facts can then be presented to the user as part of documentation, property editor information popup and in other relevant places.
A single facts service can produce multiple facts and multiple facts services can be active concurrently for a given property. See FactsAggregationService for an easier way to consume all facts.
Sapphire includes a number of FactsService implementations.
##servicess##Example
This screen capture shows user experience with some of the provided FactsService implementation. See if you can match facts in the screen capture to service implementations above.
Adopters can provide custom FactService implementations either globally using Sapphire extension system or at the property level using @Service annotation.
Example
A simple global FactsService implementation that is triggered by a hypothetical @Since property annotation.
public class SinceVersionFactsService extends FactsService
{
@Override
protected void facts( List facts )
{
Since since = property().getAnnotation( Since.class );
facts.add( "Since version " + since.version() + "." );
}
public static class Factory extends ServiceFactory
{
@Override
public boolean applicable( ServiceContext context,
Class<? extends Service> service )
{
return context.find( ModelProperty.class ).hasAnnotation( Since.class );
}
@Override
public Service create( ServiceContext context,
Class<? extends Service> service )
{
return new SinceVersionFactsService();
}
}
}
The service implementation is registered in META-INF/sapphire-extension.xml file.
<extension xmlns="http://www.eclipse.org/sapphire/xmlns/extension">
<service>
<id>Example.SinceVersionFactsService</id>
<type>org.eclipse.sapphire.services.FactsService</type>
<context>Sapphire.Property.Instance</context>
<factory>example.SinceVersionFactsService$Factory</factory>
</service>
</extension>
Facts can also be statically specified for a given property by using @Fact annotation. Use @Facts annotation to specify multiple facts. The facts contained in these annotations are surfaced by an included FactsService implementation (id:Sapphire.FactsService.Static).
Example
// *** ExampleOne ***
@Fact( statement = "Important fact.")
ValueProperty PROP_EXAMPLE_ONE = new ValueProperty( TYPE, "ExampleOne" );
Value<String> getExampleOne();
void setExampleOne( String value );
// *** ExampleMultiple ***
@Facts( { @Fact( statement = "First important fact." ), @Fact( statement = "Second important fact." ) } )
ValueProperty PROP_EXAMPLE_MULTIPLE = new ValueProperty( TYPE, "ExampleMultiple" );
Value<String> getExampleMultiple();
void setExampleMultiple( String value );