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
BaseClassifierToKernelHyperslicequi 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 :