The AdapterService provides means to extend the behavior of the adapt method in a given context.

For example, out of the box, Sapphire can adapt IModelElement to IProject assuming that the model is using
an IFile for the underlying resource store. However, in some cases there may be no underlying IFile, so the
default logic will no be able to find IProject. To solve this problem, we can introduce an adapter service to
provide a custom method for adopting IModelElement to IProject.

The ContentProposalService provides a conduit for content assist in property editors. If a property
has this service, content assist will be automatically enabled in the property editor. The manner in which
content assist is presented is specific to the presentation, but usually involves a popup window with
proposals, activated by some combination of key strokes (such as CTRL+SPACE).

The framework provides an implementation of ContentProposalService for properties with @PossibleValues
annotation or a custom PossibleValuesService, but this service can also be implemented directly by
adopters.

The ConversionService converts an object to the specified type. One common application is to convert
an input (such as a file) to a resource when instantiating the model.

Sapphire.ConversionService.IFileToWorkspaceFileResourceStore

Capable of converting an IFile to a WorkspaceFileResourceStore or a ByteArrayResourceStore.

Sapphire.ConversionService.ByteArrayResourceStoreToXmlResource

Capable of converting a ByteArrayResourceStore to an XmlResource or a Resource. Conversion is only
performed if resource store corresponds to a file with "xml" extension or if the context element type
has XML binding annotations.

A ConversionService can delegate to other conversion services to create a conversion chain. In fact,
a common conversion of IFile to XmlResource is a chain of two ConversionService implementations.

Example

In the purchase order sample, a custom ConversionService is used because the
default file extension for purchase order files is "po" rather than "xml" and PurchaseOrder element does not
have XML binding annotations. The combination of these two factors prevent the framework-provided ConversionService
implementations from engaging.

Note the use of chaining as part of the presented ConversionService implementation. The
input could be any number of things, but as long as another ConversionService implementation knows how to convert it
to a ByteArrayResourceStore, this implementation will take the conversion the rest of the way to a Resource.

The DependenciesAggregationService combines the data from all applicable dependencies services in order to produce
a single set of dependencies. A dependency is a model paths that points to parts of the model that the property depends on.
A property listens on all of its dependencies and triggers refresh when any of the dependencies change.

An implementation of this service is provided with Sapphire. This service is not intended to
be implemented by adopters. See DependenciesService instead.

The DependenciesService produces the set of model paths that point to parts of the model that the property
depends on. A property listens on all of its dependencies and triggers refresh when any of the dependencies change.

Although custom implementations are supported, in most cases the supplied implementation that is
configured via @DependsOn annotation should be sufficient.

Other annotations, such as @NoDuplicates can also inject implied dependencies (via their own DependenciesService
implementations). For instance, placing @NoDuplicates annotation on a Name property automatically
adds "#/Name" dependency.

If declarative approach is not sufficient, a custom DependenciesService implementation can be supplied.

The DiagramLayoutPersistenceService is responsible for persisting layout of the diagram, such a location and
size of nodes, connection bend points, etc.

Unlike other services, DiagramLayoutPersistenceService is not defined by methods that must be
implemented, but rather by its expected behavior.

During service initialization, the implementation is expected to load layout information and transfer it to
diagram parts using API such as DiagramNodePart.setNodeBounds().

After initialization, the implementation is expected to listen for changes to diagram parts and persist
layout information. Persistence can happen immediately or be deferred until the save event is received.

If implementation defers layout persistence until save, it is expected to implement dirty() method and to
issue DirtyStateEvent when this state changes.

Example

The architecture sample provides a comprehensive example of a custom
implementation that persists layout in the same file as data.

The EqualityService provides means to implement equals() and hashCode() methods when the context object doesn't support
implementing these methods directly. One such context is model elements, where the framework does not rely on a particular
implementation of these methods, but having these methods behave in a way consistent with semantics of the data being modeled
can be useful for other purposes.

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.

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).

The FileExtensionsService produces the list of file extensions that are allowed for a path value
property.

Although custom implementations are supported, in most cases the supplied implementation that
is configured via @FileExtensions annotation should be sufficient. In many cases, specifying
file extensions is as simple as listing them with a comma in between.

The InitialValueService produces a value to assign to a property when the containing model element is
created.

The concept of an initial value is different from a default value. The initial value is explicitly
assigned to the property during containing model element's creation. This includes writing to the backing resource
(such as an XML document). In comparison, the default value is used when null is read for a property from the
backing resource. As such, the default value is only visible to model consumers (such as the user interface),
while the initial value is persisted.

Whether you use an initial value or a default value is frequently dictated by the requirements of the
backing resource. As an example, let's consider an XML document that stores phone numbers. In this XML document,
the phone number element has a type child element which contains a value like home, mobile, work, etc.
Let's further say that semantically, we wish to use mobile phone number type unless specified differently.
Now, if the XML schema dictates that the phone number type element is required, we would need to specify
"mobile" as the initial value. If the phone number type element is optional, it would be better to specify
"mobile" as the default value.

In many situations, the initial value is static and should be configured using @InitialValue annotation.

The JavaTypeConstraintService describes constraints on the Java type that a property can reference, such as the kind of
type (class, interface, etc.) and the types that the type must extend or implement. The information provided by this
service is used for validation, content assist and other needs.

In majority of situations, the Java type constraint is static and should be configured using @JavaTypeConstraint
annotation. The framework provides an implementation of JavaTypeConstraintService that works with this annotation.

The ListSelectionService functions as a conduit between the presentation layer and anything that may want to see or
change the selection. The presentation layer pushes selection changes made by the user to ListSelectionService and at
the same time listens for changes to selection coming from ListSelectionService.

An implementation of this service is provided with Sapphire. This service is not intended to be implemented by adopters.

Example

In this example, an action handler attaches a listener to the ListSelectionService to
refresh action handler's enablement state when selection changes.

The MasterConversionService converts an object to the specified type by delegating to available ConversionService
implementations. If object is null or is already of desired type, the object is returned unchanged.

An implementation of this service is provided with Sapphire. This service is not intended to
be implemented by adopters. See ConversionService instead.

Example

In this example, an IFile is converted to a Resource as part of instantiating the model.
Note how this code is not aware of the details of the conversion or what type of a resource is created.

The PossibleTypesService enumerates the possible child element types for a list or an element property. Each
returned type is required to derive from the property's base type.

In majority of situations, the set of possible types is static and should be configured using @Type annotation.
The framework provides an implementation of PossibleTypesService that works with this annotation.

If the set of possible types is not specified via @Type annotation or via a custom PossibleTypesService
implementation, the set of possible types is defined to be a singleton set composed of the property's base
type.

When more control is necessary, a custom implementation of VersionCompatibilityService can be provided. A
typical implementation will utilize VersionCompatibilityTargetService to determine the current version.

VersionCompatibilityTargetService produces the version compatibility target to be referenced
by VersionCompatibilityService.

When looking for the version compatibility target, the framework will first check the property, then the containing
element, then the parent property and the parent element, etc. The search continues until version compatibility target
is found or the model root is reached.

In most situations, version compatibility target can be expressed using an @VersionCompatibilityTarget annotation,
which supports the expression language.