• Aucun résultat trouvé

Hyper/J est celui encapsulant les classes et interfaces de base impactées par les préoccupations

hn, hmn: String;

checkonly domain aspectModel p: Package {ownedElement = cc: CrosscuttingConcern {}}; enforce domain hyperJModel h: Hyperspace { name = hn,

dimension = d: Dimension {name = ‘Concern’}}; enforce domain hyperJModel hm: Hypermodule { name = hmn,

compositionStrategy = ‘overrideByName’}; }

Création de la préoccupation de base. Le premier hyperslice à créer dans le cas d’une transformation vers

Hyper/J est celui encapsulant les classes et interfaces de base impactées par les préoccupations

transversales. Pour ce faire, nous avons défini la relation

BaseClassifierToKernelHyperslice

qui fait appel

à son tour aux règles transformant les classes et/ou interfaces mises en jeu tout en les reliant à

l’hyperspace ainsi créé. Cette règle fait appel également aux règles transformant les relations qui existent

entre ces classificateurs.

top relation BaseClassifierToKernelHyperslice {

pn: String;

checkonly domain aspectModel p: Package {name = pn}; enforce domain hyperJModel hm : Hypermodule

{ composableHyperslice = kh: Hyperslice { name = ‘kernel’,

composablePackage = tp: Package {name = pn}, owner = d: Dimension {owner = h: Hyperslice { }} }; when{ HyperspaceAndConcernDimension(hs, d, hm); } where{ ClassToClass(p, tp, hs); InterfaceToInterface(p, tp, hs);

//appels aux règles transformant les associations, généralisations, réalisations, etc.} }

top relation ClassToClass {

pn, cn: String;

ckeckonly domain aspectModel c: Class {namespace = p: Package {name = pn}, name = cn}; enforce domain hyperJModel tc: Class { namespace = tp: Package {name = pn},

name = cn,

hyperspace = hs: Hyperspace {}} ;

when{

BaseClassifierToKernelHyperslice(p, tp, hs) } where{

//appels aux règles transformant attributs et opération de classes } }

Transformation des préoccupations transversales. Toute préoccupation transversale (instance de

CrosscuttingConcern

) est transformée vers un hyperslice et un paquetage lié à cet hyperslice. Le

paquetage à créer doit contenir une nouvelle définition pour chaque classe entrecroisée par la

préoccupation transversale considérée. Toute règle transformant une préoccupation transversale vers un

hyperslice et un paquetage doit faire appel aux règles transformant les introductions, les déclarations de

parenté et les éléments d’altération propres à cette préoccupation, comme le montre la règle ci-dessous.

top relation CrosscuttingConcernToHyperslice {

ccn, pn: String;

checkonly domain aspectModel p: Package { ownedElement = cc : CrosscuttingConcern {name = ccn},

name = pn };

enforce domain hyperJModel ch: Hyperslice { name = ccn,

composablePackage = tp: Package {name = pn},

owner = d : Dimension {owner = hs: Hyperspace{ }}, integrationContext = hm: Hypermodule { } }; when{ HyperspaceAndConcernDimension(hs, d, hm); } where{ IntroductionToFeature(cc, tp) ; ParentDeclarationToRelationship(cc, tp);

AlteringElementToOperation(cc, tp); //utilise les spécifications d’entrecroisement } }

Transformation des introductions. Comme dans le cas des transformations vers AspectJ, les règles

transformant les introductions considèrent deux types de sous-règles spécifiques respectivement, aux

transformations des introductions d’attributs et opérations. Nous présentons ci-dessous un exemple de

règle transformant une introduction d’un attribut de type primitif dans une classe.

relation IntroductionToFeature {

checkonly domain aspectModel cc : CrosscuttingConcern { }; enforce domain HyperJModel tp: Package { };

where { AttributeIntroductionToAttribute(cc, tp); OperationIntroductionToOperation(cc, tp); } } relation AttributeIntroductionToAttribute

{ //introduction d’un attribute de type primitif dans une classe (target->size()=1) an, av, tn, pn, cn : String ;

checkonly domain aspectModel cc: CrosscuttingConcern { crosscuttingElement = i : Introduction

{ feature = a : Attribute { name = an, visibility = av, type = t: Primitive {name = tn}}, target = c: Class { namespace = p: Package {name = pn}, name = cn }

}};

enforce domain hyperJModel tp: Package { name = pn,

ownedElement = tc: Class { name = cn,

feature = ta: Attribute { name = an, visibility = av, type = tt : Primitive {name = tn} } }

}; // Si tc existe déjà ta est tout simplement ajouté à tc when {

Transformation des éléments d’altération. Les éléments d’altération sont transformés vers des opérations.

Remarquons que les spécifications d’entrecroisement n’ont pas de correspondants directs dans

HyperJ/UML. Elles sont utilisées cependant par les règles transformant les éléments d’altération. Voici

ci-dessous un exemple de règle transformant un élément d’altération dans un contexte d’intégration utilisant

la stratégie de composition générale

overrideByName

.

relation AlteringElementToOperation {

// Transformation d’un élément d’altération vers une opération (ou plusieurs) dans la classe cible d’impact // par respect des propriétés de sa spécification (CrosscuttingElement)

aet, aeb, cst, os, ov, eb, pn, cn, teb : String ;

checkonly domain aspectModel cc: CrosscuttingConcern { crosscuttingElement = ae: AlteringElement

{ type = aet,

body = aee: AlteringElementExpression {body = aeb}, specification = cs: CrosscuttingSpecification

{ isAbstract = ‘false’,

type = cst,

target = o: Operation

{ specification = os, isAbstract= ‘false’, visibility = ov, method = m: Method

{body = mb: ProcedureExpression {body = eb}}, owner = c: Class

{ namespace = p: Package {name = pn}, name =cn}

} } } };

enforce domain hyperJModel tp: Package { name = pn,

ownedElement = tc: Class { name = cn,

feature = to: Operation { specification = os, //même spécification que l’op impactée

isAbstract= ‘false’, visibility = ov,

method = tm: Method

{body = tmb: ProcedureExpression {body = teb}}

} } }; when { CrosscuttingConcernToHyperslice(cc, tp); } where{

cst = ‘call’ || cst = ‘set’ || cst = ‘get’;

teb = AlteringElementBodyToMethodBody(aet);

OperationToOperation(cc, tp, ae, tc); //ajout des opérations appelées par l’ae dans la cn impactée } }

OperationToOperation {

sos, ov, eb : String

checkonly domain aspectModel cc: CrosscuttingConcern { crosscuttingElement = ae: AlteringElement

{ supplier = so: Operation

{ owner = cc: CrosscuttingConcern {},

specification = sos, isAbstract = ‘false’, visibility = ov,

method = m: Method

{body = mb: ProcedureExpression {body = eb}} }

} };

enforce domain hyperJModel tp: Package { ownedElement = tc: Class

{ feature = to: Operation { specification = sos,

isAbstract= ‘false’, visibility = ov,

method = tm: Method

{body = tmb: ProcedureExpression {body = eb}}

}}; when{ AlteringElementToOperation(cc, tp) ; } }

function AlteringElementBodyToMethodBody(type: String) : String { if (type=‘before’) then aeb+eb

else if (type=‘after’) then eb+aeb else aeb

endif endif; }

3.4.2 Modèle HyperJ du patron Stratégie

La figure 4.34 montre la structure de Stratégie conforme au métamodèle spécifique à Hyper/J, obtenue

par transformation de celle présentée par la figure 4.32, en appliquant l’ensemble des règles de

transformation explicitées ci-dessus.

StrategicContext: overrideByName <<hypermodule>> Concern::ContextStrategies <<hyperslice>> Context - strategy : int = 0 + Context(int stg) + defaultAlgorithm() + algorithm1() + algorithm2() + ...() + algorithmn() + algorithmInterface() Concern::Kernel <<hyperslice>> Context + algorithmInterface() <<integrate>> <<integrate>> algorithmInterface { switch(strategy) { case 1: algorithm1(); case n: algorithmn(); ... default: defaultAlgorithm();}} 1 : 2 :

Figure 4.34. Modèle de Stratégie, spécifique à Hyper/J

L’instance

ContextStrategies

de

CrosscuttingConcern

est transformée en une instance d’

Hyperslice

appelée

Concern::ContextStrategies

, dont

Concern

est le nom de la dimension des préoccupations et

ContextStrategies

représente le nom de la préoccupation transversale. Cet hyperslice consiste en une

nouvelle instance de

Class

(

Context

) qui détient l’attribut

strategy

et le constructeur

Context(int stg)

,

destinés à être introduits dans la classe

Context

référencée par l’hyperslice

Concern::Kernel

représentant

la préoccupation de base. Par ailleurs, l’instance de

AlteringElement

est transformée en l’opération

algorithmInterface()

détenue aussi par la nouvelle classe

Context

. Le nom de cette opération est déterminé

par le nom de l’opération liée à la spécification d’entrecroisement

PerformAlgorithm

(cf. figure 4.32).

Notons également que la nouvelle classe

Context

détient les différentes définitions de l’algorithme

considéré, qui sont appelées par l’élément d’altération ainsi transformé. Comparativement à la structure de

Stratégie présentée par la figure 4.32, on peut essentiellement remarquer que peu d’informations liant les

préoccupations de base et transversale apparaissent : la règle d’intégration générale

overideByName

détenue par l’hypermodule

StrategicContext

suffit dans cet exemple à définir les conditions

Documents relatifs