<
aspect xmlns:cpp="
http://www.sdml.info/srcML/cpp"
xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
xmlns="
http://control.ee.ethz.ch/XWeaver/AspectX"
xmlns:src="
http://www.sdml.info/srcML/src"
xsi:schemaLocation="
http://control.ee.ethz.ch/XWeaver/AspectX ../../../../src/xsd/aspectX.xsd"
name="
ParameterDatabaseByPointer">
<
description>
Sample aspect program that modifies the component to access all its parameters from
a <
i>
parameter database by pointer</
i>
.
This aspect program shows an example of how the implementation of selected classes in
a certain base code
can be modified to change the way in which member variables are handled. In this example, all
member variables in the base code are moved to a dedicated object called <
i>
parameter database</
i>
(see <
a href="
http://www.pnp-software.com/ObsFramework/doc/ParameterDatabase.html">
Parameter
Database Design Pattern</
a>
).
<
p />
The
<
a href="
http://www.pnp-software.com/ObsFramework/doc/doxygen/html/classDC__BasicDatabase.html">
<
code>
DC_BasicDatabase</
code></
a>
is used as a component that stores the parameter data of the target class.
The <
code>
DC_BasicDatabase</
code>
class extends the abstract class
<
a href="
http://www.pnp-software.com/ObsFramework/doc/doxygen/html/classParameterDatabase.html">
<
code>
ParameterDatabase</
code></
a>
.
Both classes are defined and implemented in
<
a href="
http://www.pnp-software.com/ObsFramework/">
OBS Framework</
a>
.
<
p />
This aspect program replaces all member variables in class <
code>
SampleClass</
code>
by the respective pointers to the the instance of class
<
code>
DC_BasicDatabase</
code>
. In this example it is assumed that member variable names
starts with underline (<
code>
_ </
code>
) character.
For each member variable there is as <
i>
parameter identifier</
i>
woven in the base code.
Parameter identifier is a constant in the form <
code>
PDxxx</
code>
where
"xxx" is member variable name in upper case. Parameter identifiers are used
to uniquely identify the parameters stored in the parameter database.
Methods <
code>
getParameterPointerXXX()</
code>
defined in <
code>
ParameterDatabase</
code>
class
take the <
i>
parameter identifiers</
i>
as their parameters.
The "XXX" stands for parameter <
i>
type</
i>
.
<
p />
This aspect contains advice that
<
i>
replaces</
i>
the occurences of member variables in class <
code>
SampleClass</
code>
by
pointers that points to the parameter database. Other advices add parameter database variable declaration
and initialization code to the base code. Yet another advice adds necessary <
code>
#include</
code>
preprocessor directives.
This aspect program uses pointcuts defined in file <
code>
PointcutLibrary.xml</
code>
. It also
defines two additional pointcuts <
code>
targetParameterUsage</
code>
and
<
code>
targetParameterDeclaration</
code>
.
<
author>
A. Pasetti, O. Rohlik</
author>
<
see>
PointcutLibrary</
see>
</
description>
<
include href="
PointcutLibrary.ax" />
<
pointcut name="
targetClassDeclaration"
type="
src:unit" />
<
pointcut name="
anySampleClassExpr"
type="
src:expr" />
<
pointcut name="
targetClass"
type="
src:class" />
<
pointcut name="
targetParameterUsage"
type="
src:name"
constraint="
starts-with(text(),'_')">
<
description>
Points to <
i>
occurrences</
i>
of member variables used in expression within methods, constructors
and destructors of the target class. Member variables are identified as identifiers that
starts with <
i>
underline</
i>
character ( <
code>
_</
code>
).
</
description>
<
restriction type="
within">
<
pointcutRef ref="
anySampleClassExpr"
type="
src:expr"
aspect="
PointcutLibrary" />
</
restriction>
</
pointcut>
<
pointcut name="
targetParameterDeclaration"
type="
src:name"
constraint="
starts-with(text(),'_')">
<
description>
Points to <
i>
declarations</
i>
of member variables of the target class.
Member variables declarations are identified as identifiers that
starts with <
i>
underline</
i>
character ( <
code>
_</
code>
) but <
i>
does not</
i>
appear
in the methods, constructors or destructors of the target class.
</
description>
<
not>
<
restriction type="
within">
<
pointcutRef ref="
anySampleClassExpr"
type="
src:expr"
aspect="
PointcutLibrary" />
</
restriction>
</
not>
</
pointcut>
<
advice name="
addConstants"
type="
add">
<
description>
Add constants to the class declaration. Constants represent the parameter identifiers
of all the entries in parameter database that are used in the target class. The name of every
constant is derived from the member variable name and is constructed as <
code>
PDxxx</
code>
where "xxx" is member
variable name in upper case. For example constant <
code>
PD_WIDTH</
code>
is the parameter identifier of
the member variable <
code>
_width</
code>
.
</
description>
<
pointcutRef ref="
targetClassDeclaration"
aspect="
PointcutLibrary"
type="
src:unit" />
<
codeModifier type="
declaration">
<
text>
const TD_DatabaseId PD_WIDTH = 0; // added by aspect</
text>
<
text>
const TD_DatabaseId PD_HEIGHT = 4; // added by aspect</
text>
<
text>
const TD_DatabaseId PD_FLT = 8; // added by aspect</
text>
<
text />
</
codeModifier>
</
advice>
<
advice name="
addIncludesToDeclaration"
type="
add">
<
description>
Add the <
code>
#include</
code>
preprocessor instructions.
Declaration of class <
code>
TD_DatabaseId</
code>
is needed in order to define parameter identifiers,
this data type is defined in header file <
code>
GeneralInclude/BasicTypes.h</
code>
. The pointer to
parameter database has to be defined in the class definition. Therefore the header file
<
code>
Data/DC_BasicDatabase.h</
code>
has to be included as well.
</
description>
<
pointcutRef ref="
targetClassDeclaration"
aspect="
PointcutLibrary"
type="
src:unit" />
<
codeModifier type="
include">
<
text>
#include "Data/DC_BasicDatabase.h" // added by aspect </
text>
<
text>
#include "GeneralInclude/BasicTypes.h" // added by aspect </
text>
</
codeModifier>
</
advice>
<
advice name="
addDatabaseReference"
type="
add">
<
description>
Add declaration of pointer to parameter database to target class. The pointer is of type
<
code>
DC_BasicDatabase*</
code>
and is named <
code>
pDB</
code>
. It is declared as private.
</
description>
<
pointcutRef ref="
targetClass"
aspect="
PointcutLibrary"
type="
src:class" />
<
codeModifier type="
declaration">
<
accessModifier type="
private" />
<
text>
DC_BasicDatabase* pDB; // added by aspect</
text>
</
codeModifier>
</
advice>
<
advice name="
targetFloatVarInitialization"
type="
begin">
<
description>
Initialize <
code>
float*</
code>
pointers to the parameter database
by value returned by the method <
code>
pDB->getParameterPointerFloat(PDxxx)</
code>
where "xxx" is member variable name in upper case. Note that the parameter of the method
represents the <
i>
parameter identifier</
i>
used
to uniquely identify the parameters stored in the parameter database.
<
p />
For example member variable <
code>
_flt</
code>
is initialized to value
returned by the method call
<
code>
pDB->getParameterPointerFloat(DB_FLT)</
code>
where the substring
<
code>
_FLT</
code>
is automatically generated from the variable name.
<
p />
It is important to initialize <
i>
all</
i>
pointers to the parameter database
defined in the target class. This advice initializes all pointers of type
<
code>
float*</
code>
. All <
code>
float*</
code>
pointers are accessed using
two construtcs of the XSL language: <
code>
xsl:for-each</
code>
and
<
code>
xsl:value-of</
code>
. Variable <
code>
filename</
code>
defined in the code modifier
contains the name of the current unit (without extension).
The <
code>
filename</
code>
is later used to define the <
code>
path</
code>
to the file where the target class is defined. The set of all float member
variable names defined in the target class can be then obtained using (relatively
complicated) XPath expression with <
code>
doc()</
code>
function of XSL language:
<
code>
doc($path)//src:class[src:name=$filename]//src:decl_stmt/src:decl[src:type/src:name='float']/src:name</
code>
.
</
description>
<
pointcut type="
src:constructor"
constraint="
src:name='SampleClass::SampleClass'" />
<
codeModifier type="
codeFragment">
<
text />
<
xsl>
<
xsl:
variable name="
filename"
select="
substring-before(substring-after(escape-uri(base-uri(), false()),'/srcML/src/'),'.')" />
<
xsl:
variable name="
path"
select="
concat(util:getFolder(escape-uri(base-uri(/), false())), $filename,'.h.xml')" />
<
xsl:
variable name="
set"
select="
doc($path)//src:class[src:name=$filename]//src:decl_stmt/src:decl[src:type/src:name='float']/src:name" />
<
xsl:
text>
// initialization of float* pointers to the parameter database</
xsl:
text>
<
xsl:
for-each select="
$set">
<
xsl:
text>
</
xsl:
text>
<
xsl:
text>
_p</
xsl:
text>
<
xsl:
value-of select="
text()" />
<
xsl:
text>
= pDB->getParameterPointerFloat(PD</
xsl:
text>
<
xsl:
value-of select="
upper-case(current())" />
<
xsl:
text>
);</
xsl:
text>
</
xsl:
for-each>
</
xsl>
<
text />
</
codeModifier>
</
advice>
<
advice name="
targetIntVarInitialization"
type="
begin">
<
description>
Initialize <
code>
int*</
code>
pointers to the parameter database
by value returned by the method <
code>
pDB->getParameterPointerInt(PDxxx)</
code>
where "xxx" is member variable name in upper case. Note that the parameter of the method
represents the <
i>
parameter identifier</
i>
used
to uniquely identify the parameters stored in the parameter database.
<
p />
For example member variable <
code>
_width</
code>
is initialized to value
returned by the method call
<
code>
pDB->getParameterPointerInt(DB_WIDTH)</
code>
where the substring
<
code>
_WIDTH</
code>
is automatically generated from the variable name.
<
p />
It is important to initialize <
i>
all</
i>
pointers to the parameter database
defined in the target class. This advice initializes all pointers of type
<
code>
int*</
code>
. All <
code>
int*</
code>
pointers are accessed using
two construtcs of the XSL language: <
code>
xsl:for-each</
code>
and
<
code>
xsl:value-of</
code>
. Variable <
code>
filename</
code>
defined in the code modifier
contains the name of the current unit (without extension).
The <
code>
filename</
code>
is later used to define the <
code>
path</
code>
to the file where the target class is defined. The set of all integer member
variable names defined in the target class can be then obtained using (relatively
complicated) XPath expression with <
code>
doc()</
code>
function of XSL language:
<
code>
doc($path)//src:class[src:name=$filename]//src:decl_stmt/src:decl[src:type/src:name='int']/src:name</
code>
.
</
description>
<
pointcut type="
src:constructor"
constraint="
src:name='SampleClass::SampleClass'" />
<
codeModifier type="
codeFragment">
<
text />
<
xsl>
<
xsl:
variable name="
filename"
select="
substring-before(substring-after(escape-uri(base-uri(), false()),'/srcML/src/'),'.')" />
<
xsl:
variable name="
path"
select="
concat(util:getFolder(escape-uri(base-uri(/), false())), $filename,'.h.xml')" />
<
xsl:
variable name="
set"
select="
doc($path)//src:class[src:name=$filename]//src:decl_stmt/src:decl[src:type/src:name='int']/src:name" />
<
xsl:
text>
// initialization of int* pointers to the parameter database</
xsl:
text>
<
xsl:
for-each select="
$set">
<
xsl:
text>
</
xsl:
text>
<
xsl:
value-of select="
concat('_p', text())" />
<
xsl:
text>
= pDB->getParameterPointerInt(PD</
xsl:
text>
<
xsl:
value-of select="
upper-case(current())" />
<
xsl:
text>
);</
xsl:
text>
</
xsl:
for-each>
</
xsl>
<
text />
</
codeModifier>
</
advice>
<
advice name="
addDatabaseInicialization"
type="
begin">
<
description>
Add code fragment that initialize the parameter database. The database has to be initialized before
it is first used. The initialization code is discussed in documentation of the
<
a href="
http://www.pnp-software.com/ObsFramework/doc/doxygen/html/classTestCaseBasicDatabase__1.html">
TestCaseBasicDatabase_1</
a>
class (a part of the <
a href="
http://www.pnp-software.com/ObsFramework/">
OBS Framework</
a>
).
Purpose of the initialization is to:
<
ol>
<
li>
initialize the data structure to simulate the default table</
li>
<
li>
initialize the data structure to simulate the operational table</
li>
<
li>
instantiate the basic database object (<
code>
pDB</
code>
)</
li>
<
li>
set the parameter database length</
li>
<
li>
set the default and operational tables of the parameter database</
li>
<
li>
reset the database</
li>
</
ol>
</
description>
<
pointcut type="
src:constructor"
constraint="
src:name='SampleClass::SampleClass'" />
<
codeModifier type="
codeFragment">
<
text>
// Initialize the parameter database (this and 14 lines below were added by aspect)</
text>
<
text>
// Data structure to simulate the default table</
text>
<
text>
double* shadowDefaultTable = new double[3];</
text>
<
text>
unsigned int* defaultTable = (unsigned int*)shadowDefaultTable;</
text>
<
text>
// Data structure to simulate the operational table</
text>
<
text>
double* shadowOperationalTable = new double[3];</
text>
<
text>
int* operationalTable = (int*)shadowOperationalTable;</
text>
<
text>
// Instantiate basic database</
text>
<
text>
pDB = new DC_BasicDatabase();</
text>
<
text>
// Set the table length</
text>
<
text>
pDB->setTableLength(12);</
text>
<
text>
// Complete configuration of the database</
text>
<
text>
pDB->setDefaultTable((char*)defaultTable);</
text>
<
text>
pDB->setOperationalTable((char*)operationalTable);</
text>
<
text>
pDB->reset();</
text>
</
codeModifier>
</
advice>
<
advice name="
replaceParametersByPointers"
type="
replace">
<
description>
Replace occurences of member variables with the dereferences of pointers
to the parameter database. Each member variable is replaced by the code
<
code>
(*_pXXX)</
code>
where XXX stands for the name of the variable being replaced.
For example member variable <
code>
_width</
code>
is replaced with
<
code>
(*_p_width)</
code>
.
</
description>
<
pointcutRef ref="
targetParameterUsage"
type="
src:name" />
<
codeModifier type="
codeFragment">
<
xsl>
(*_p<
xsl:
value-of select="
current()" />
)</
xsl>
</
codeModifier>
</
advice>
<
advice name="
replaceParameterDeclarationsByPointers"
type="
replace">
<
description>
Replace declarations of member variables with the declarations of pointers
to the parameter database. Each member variable declaration is replaced by the code
<
code>
*_pXXX</
code>
where XXX stands for the name of the variable being replaced.
For example the declaration of member variable <
code>
_width</
code>
is replaced with
the declaration of <
code>
*_p_width</
code>
.
</
description>
<
pointcutRef ref="
targetParameterDeclaration"
type="
src:name" />
<
codeModifier type="
codeFragment">
<
xsl>
*_p<
xsl:
value-of select="
current()" /></
xsl>
</
codeModifier>
</
advice>
</
aspect>
v