# Sirius Architecture and Concepts

## Introduction

This document presents an overview of the internal architecture of Sirius, and the main concepts and APIs.

Sirius relies heavily on the Eclipse platform, and reuses (and extends) many of the standard Eclipse frameworks, in particular the Eclipse Modeling Platform. This document assumes that you are already familiar with these frameworks and libraries, in particular EMF and EMF Transaction, GEF and GMF for diagrams. Refer to these frameworks' own documentation for more details about them.

## Sessions

The central concept of Sirius’s API is the `Session`. In Sirius, all data is stored in EMF models: the semantic models themselves obviously, but also the representations (diagrams, tables) and the viewpoint configuration (the Viewpoint Specification Models). A session is a wrapper around a Transactional Editing Domain and its Resource Set. It ensures the consistency of the models inside the editing domain, from the platform’s point of view; for example it makes sure the representation files correctly reference all the semantic models they need to in order to handle the representations in the session. The session also provides high-level, Sirius-specific services through its own APIs and support classes and interfaces.

In the standard UI, each Modeling Project corresponds to exactly one `Session`, and each session contains its own Editing Domain and Resource Set. This means that sessions (and thus modeling projects) are isolated from each other.

The representation files ( `*.aird` files) can be though as the serialized form of a `Session`, and symmetrically a session is the runtime incarnation of a representation file (or more precisely of the unique top-level representation file in a modeling project).

A session, inside its resource set, contains three kinds of resources:

- the semantic resources, which contain the user’s semantic model;
- the representation resources, which correspond to the `aird` file(s), and contain representation data (e.g. diagrams);
- the Viewpoint Specification Models which contain all the viewpoints used by the representations inside the session. These are the `*.odesign` files, and are typically loaded from installed plug-in instead of from the workspace (except when using the dynamic mode to develop viewpoints).

The `SessionManager` is a global object which references all the sessions currently opened in the system. It can also be used to find which session is responsible for a given semantic element. This is very important because many Sirius APIs require that you provide a `Session` parameter. If what you have is an element from a user semantic model, you can use `SessionManager.INSTANCE.getSession(theSemanticElement)` to find in which of the opened session, if any, this object is loaded. Note that this method can be relatively costly, so do not call it in tight loops to avoid hurting performance.

To create a Session programmatically:

    URI sessionResourceURI = URI.createPlatformResourceURI("/Project/archi.aird", true);
    Session createdSession = SessionManager.INSTANCE.getSession(sessionResourceURI);
    createdSession.open();

The `Session` API provides several methods to manage the different kind of resources it contains: finding all the semantic resources and adding new ones, finding about all the referenced session resources (all the secondary `*.aird` files which are part of the same session), etc. Refer to the `Session` interface’s JavaDoc for details.

The `Session.getInterpreter()` method can be used to obtain an `IInterpreter` properly configured to query the models in that session. The interpreter it returns will handle expression from any of the supported query languages, and you can use it to run your own queries (see the `IInterpreter` API).

Another interesting method in `Session` is `Session.getEventBroker()`. It returns a `SessionEventBroker` object, which can be used to add trigger actions that will be performed whenever a change in the session’s model occurs. See `SessionEventBroker` and `ModelChangeTrigger` for details.

When you are finished working with a session, you must `close()` it. This will unload all the models in its resource set and free the corresponding memory. After a session has been close it can not be reopened, but you can open a new one on the same files if needed.

### Transactional Editing Domain

The editing domain associated to each session is an EMFT Transactional Editing Domain. In addition to basic undo/redo, it supports advanced features like atomicity and pre- and post-commit listeners, which are triggered after a command has been executed, and can be used to perform additional work (for pre-commit listeners) or to update external application data like UI state for post-commit listeners.

The `Session.getTransactionalEditingDomain()` will return the `TransactionlEditingDomain` for a session.

To modify a model element with a transactional editing domain, you must use a `RecordingCommand`. If you try to modify the models inside a session (semantic model or representations) outside the context of a recording command, you will get an exception. The proper usage pattern is:

    TransactionalEditingDomain ted = ...;
    ted.getCommandStack().execute(myCommand);

where `myCommand` is a `RecordingCommand`.

### Changing the Viewpoint Selection

Each session has its own set of Viewpoints enabled, which determine which representations and extension are available. Users can change that selection using the Viewpoint Selection action (for example on a Modeling Project). You can also change this selection programmatically.

The simplest way to do this is to use the `UserSession` API; for example:

    Session userSession = UserSession.from(createdSession);
    userSession.selectViewpoint("Design");

## Editing Sessions

An editing session, represented by an instance of `org.eclipse.sirius.ui.business.api.session.IEditingSession`, manages the graphical editors associated to a session. A session can exist without an associated editing session, but some operations require that an editing session is explicitly opened. At most one editing session can exist for a given session.

To retrieve the editing session associated to a session or create a new one, use the `org.eclipse.sirius.ui.business.api.session.SessionUIManager` API. The manager serves both as a factory for editing sessions and as a registry of all the ones which are opened at a given time and which session they correspond to.

The main services offered by an editing session are to open, close, save, and generally manage the lifecycle of the Eclipse editors associated with a session. Every time a representation (e.g. a diagram) is opened on a model, it happens through the corresponding editing session.

You can use the editing session’s APIs yourself to open representations, check their dirty states, save them, etc. Refer to the `EditingSession`'s JavaDoc for details.

You can also register `IEditingSessionListeners` on an editing session, to be notified of state changes in the session, in particular when it becomes dirty, meaning that it contains unsaved changes.

## The Model Accessor

The semantic models inside a session are never manipulated directly by Sirius. All access to these models is mediated through the session’s `ModelAccessor` instead of directly through the normal EMF reflective APIs. This accessor serves two purposes:

- It enables seamless extension (or restriction) of how the session views the semantic model. For example a model accessor could give access to virtual elements or properties, which do not exist “physically” inside the semantic model; it could also decide to hide some parts of the semantic model to viewpoint.
- It allows the verification of any access or modification using the associated `IPermissionAuthorithy`. The permission authority is used to lock model elements (both diagram and semantic elements), and to check if you have read and/or write access to each element and feature before access or modification.

You can obtain the model accessor associated to a session using the `Session.getModelAccessor()` method, and the permission authority using `ModelAccessor.getPermissionAuthority()`. If you extend Sirius, you should make sure to use the model accessor API to read and write the semantic model, and to use the permission authority to check any change you want to perform beforehand.

## Dialects

Sirius supports different kinds of representations: diagrams, tables and trees. These are all dialects, which are supported by default by the platform. The core of the platform only deals with the abstract notion of a dialect, and each one is simply an extension.

The `DialectManager` ( `org.eclipse.sirius.business.api.dialect.DialectManager`) offers some general APIs which can be used to manipulate representations in a uniform way, independently of which concrete dialect provides them. The `DialectManager` can be used to:

- create new representations;
- synchronize representations;
- delete representations;
- find existing representations.

The `DialectManager` is a global object but the services it offers work on representations inside sessions, so all the methods it provides require a `Session` object as argument.

In the same way as sessions are split in a core `Session` API and an `EditingSession` API to handle UI-specific services, the `DialectManager` is complemented with the `DialectUIManager` ( `org.eclipse.sirius.ui.business.api.dialect.DialectUIManager`), which offers generic APIs to representations services which depend on the UI. The main ones are:

- opening and closing editors;
- exporting representations into external files (e.g. images).

## The Viewpoint Registry

The `ViewpointRegistry` is a global object which knows about all the Viewpoint definitions available in the system at every time.

When a plug-in containing properly packaged VSMs is deployed, the registry will be notified (through the `org.eclipse.sirius.componentization` extension point) and register all the viewpoints defined in any of these VSMs. The registry also listens to changes in the Eclipse workspace to detect the creation, modification and deletion of any `*.odesign` files; this is (part of) what enables dynamic development of VSMs, with no need for a costly deployment of plug-ins to test your changes: the latest version of a Viewpoint definition from the workspace is always known from the registry.

You can use the registry to discover about all the viewpoint definitions which are available, and introspect the corresponding models. However be aware that the Viewpoint registry maintains its own editing domain and EMF `ResourceSet` in which the viewpoints are loaded. The model loaded in the registry are not the same as the ones loaded in a session that uses a given viewpoint. It is a different instance of the same model. This means you must be careful when comparing or passing around elements from a viewpoint definition. For example if you have defined a viewpoint named A, and have two different sessions where A is enabled, you will have three equivalent but different instances of A: one in each of the sessions' `ResourceSet`, and one in the `ViewpointRegistry`'s private `ResourceSet`.

You can register listeners on the `ViewpointRegistry` to be notified when Viewpoints are registered, unregistered, or when the definition of a viewpoint changes (for example because it was defined from an `*.odesign` file in the workspace that you have just modified, and the registry detected it and reloaded the new definition);