Hulotte framework provides a general approach to designing domain-specific component frameworks. The framework is base on the state-of-the-art technologies, combining Component-based Software Engineering and Model-Driven Engineering, and Code-Generation techniques.

Overview

Domain-Specific Components Frameworks (DSCF) is composed of a component model and the tool support which permit assembling, deploying and executing demanded applications. Moreover, such component model defines the relevant architectural concepts, called domain-specific concepts, according to the requirements of the targeted application domain (e.g. to address the distribution support, embedded or real-time constraints, dynamic adaptability, etc).
We distinguish two types of development roles involved in the developement process of a DSCF --- application developer and framework developer. Application developer is responsible for development of functional components and specification of domain-specific requirements. The role of the framework developer is to design and implement the runtime platform, and the domain-specific requirements defined by the application developer.

The idea behind Hulotte is to propose an unified developement process based on a generic component model which is easily extendable towards different application domain and a set of high-level tools, methods, and patterns allowing framework developers to design runtime platforms according to concerns captured these component model extensions. The Hulotte developement process is illustrated in the following picture.

Hulotte Developement Process
A Generic Component Model

The generic component model used as a cornerstone of the Hulotte design process is given in the following picture:

Hulotte Component MetaModel

The model is based on the popular CBSE principles, containing the basic entities Component, Interface, Binding, Primitive and Composite component. Moreover, the component model adopts the sharing paradigm --- one specific component can be a subcomponent of more than one composite component.
A brand new entity that we introduce is Domain Component. The main purpose of domain components is to model domain-specific requirements in a unified way. Within our model, domain components are reified as composite components. The sharing paradigm allows developers to fully exploit this concept. By deploying subcomponents into a certain domain component, the application developer specifies that these subcomponents or the bindings between them support the domain-specific property represented by the domain component.
Each architectural artifacts (Component, Interface, Binding) could be annotated by Domain-Specific Annotations capturing and defining the parameters of the concerns dedicated to the targetted application domain by-pass the component framework.

An application example is sketched out in the following figure. It comes from a case-study using our generic component model to design RTSJ-based real-time and embedded systems. The domain component concept is used to represent RTSJ concerns. We define MemoryArea domain component to express different allocation areas of RTSJ systems - heap, scoped memory, and immortal memory. Furthermore, ThreadDomain component is defined to represent various execution concepts enforced by RTSJ - non-realtime, real-time and non-heap real-time, and to distinguish between active and passive functional components.
Hulotte Component MetaModel
Platform concepts

The role of the framework developer is to define and implement semantics of domain components. She/He designs and implements semantics of domain components using the platform-level concepts --- see the figure below, and the architectural patterns that we introduce further. Within our approach, the platform is built using component assemblies and is based an our generic component model.

Hulotte Platform MetaModel
When considering domain components and the functionality they express, they impact two core architectural concepts: Functional Component and Binding. We further refer to this phenomenon as architectural refinement of core-level concepts through the platform-level concepts. A functional component typically implements the business part --- a code provided by the application developer, and requires the platform part that implements the domain-specific services --- the container. By the Functional Component Refinement we mean that the set of domain specific services is determined by the domain components, consequently the container architecture of a functional component is refined with according platform concepts. A domain-specific service can also pose special requirements on the intercomponent communication (e.g. logging, broadcast communication management), in these cases we speak about Binding Refinement.
Architectural patterns

The key purpose of architectural patterns is to allow framework developers to define semantics of domain components and thus to refine the application architecture in a systematic and programmatic way. The patterns are designed to implement any type of a domain-specific service that can potentially be reflected by a container, they therefore define architecture invariants, design and composition rules for the platform-level. In the previous figure, the platform-level presents two architectural patterns: ChainComposite and ContainerComposite.

ChainComposite Pattern is defined as a composite component, the subcomponents of such a composite are special components --- interceptors. Within the ChainComposite pattern, the interceptor components are bounded via their incoming and outgoing interfaces in an acyclic list, as depicted in the following figure. Here, the IN and OUT interface signatures of the interceptors are not necessarily identical, this allows developers to identify interceptors as adaptors of the intercepted execution flow. The interceptor itself could be a composite component allowing framework developer to implement complex intercepting mechanisms. The ChainComposite component at the platform level refines a binding specified at the functional level (similar to the concept of the connector).

ChainComposite Architectural Pattern


ContainerComposite Pattern, initially introduced in FAC, is also specified as a composite component and reifies a container of a functional component. It is composed of ChainComposite components and Controller components.
The ContainerComposite pattern is applied on a primitive or composite functional component from the core-level as follows:
  • A set of Controller components implementing various domain-specific services and meta-data influencing the whole component (e.g. lifecycle management, reconfiguration management) is composed in the container. Moreover, a special control interfaces are provided to allow an access to these services from outside of the component.
  • For each interface of the functional component a ChainComposite pattern is used. ChainComposite components can be interconnected by TRAP interfaces with the controllers, thus allowing centralized management of strategies for interception mechanisms.
ContainerComposite Architectural Pattern
Architectural refinement process

Once we specify the functional architecture containing domain components and also architectural patterns for these domain components we employ the architecture refinement process -- a process where the core-level architecture specified by the application developer is refined into an architecture where both functional architecture and runtime platform architecture are designed using the platform-level concepts.
As a result of this process we obtain a runtime platform architecture where both functional and domain-specific concerns are represented. The crucial point of the architecture refinement process is therefore the propagation of domain-specific concerns into the architecture.

Hulotte framework architecture

The Hulotte framework is an extensible tool-set that we have developed to implement the architecture refinement process. However, rather than to implement the whole process in a single transformation step that can be error-prone and hard to extend, we employ a step-wise refinement process in order to refine the high-level concepts in our architecture gradually in several stages. This technology allows framework developers to easily modify and extend this process with new domain-component definitions and semantics. Consequently, we employ methods of generative programming to compose functional code implemented by the application developer with the runtime platform implementation.

The framework, depicted in the following figure, consists of three main units: front-end processing a description of a functional architecture stored in ADL, middle-end responsible for a step-by-step architecture refinement, and backend which serves as a target domain specific implementation generator.

Hulotte Framework Architecture

Front-end implements the translation layer that proceeds an architecture description, in our case given in an extended FRACTAL-ADL, and transforms it into an internal EMF-model based representation.
The translation process gradually proceeds ADL artifacts (component, interface, domain component, binding) and for each applies a dedicated translation component responsible for extracting the information and building an appropriate representation in the internal model. The translation process can be extended by appending a new translator component. The new translator typically reflects a domain-specific extension of ADL.

Middle-end is the central part of the Hulotte framework and implements the refinement process. Its task is to process the architecture description in the form of the EMF model produced by the front-end, apply defined architecture refinements, creating, connecting, or merging model elements according to employed transformations. Internally, the middle-end is composed of three processing units, PlatformBuilder, Validator, and Optimizer.
  • PlatformBuilder is responsible for the model refinement and consists of a chain of component builders (for implementations of interceptors, controllers, and components) where each chain participates in the refinement process. From the builders the runtime platform components are instantiated either by loading definitions from an off-the-shelf component library or programmatically, via the high-level API provided by the framework. The selection and execution order of chains is controlled by MainBuilder Dispatcher that recursively explores the platform architecture and applies appropriate builder chains. Moreover, refining the internal structure as a chain of ComponentBuilders encourages extensibility of the whole process, since a new domain-specific builder can be easily introduced.
  • Validator verifies that resulting platform architectures are in conformance to the architectural constraints and invariants of domain components. The task is not only to verify whether the architectural patterns were applied correctly but also to assert that domain components were specified with respect to their constraints (more information about the Validator).
  • Optimizer introduces optimization heuristics in order to mitigate the common overhead of component-based applications. The heuristics focus on reducing interceptions in inter-component communication which usually causes performance overhead, and on merging architecture elements in order to decrease memory footprint.
Back-end part of the framework is also highly configurable to reflect current target domain and chosen implementation language. In the case of our implementation of Hulotte, the back-end is a collection of Java code generators generating Java classes from particular model elements.