Squalix is the batch part of the main application which executes the audits planed in Squale-Web. As explained in the architecture part, the whole application is composed of three main parts. * Squale-web : in charge of configuring the audits and returning the results (the web portal) * Squale-core : in charge of the main aggregations * Squalix : in charge of the batch part [] In Squale an audit concerns an application. Each application could contain one or more projects. Squale audits the first project of the first planned application then the second one and so on. Please refer to the illustration bellow.

For Squalix, an audit on a project is a succession of tasks beginning from analysis tasks and ending with termination tasks. The tasks that squalix has to complete for an audit on a project depend on :
Profile and source recovery mode are configured by the user in squale-web for each project. The list of tasks that have to be completed for a profile and a source recovery can be found (and modified) in the file : squalix-config.xml ( Squale-core : src/main/config/). Only administrator can upload into Squale a new squalix-config.xml.
Each tool implemented in Squalix defines an analysis task and/or a termination task. Termination task is the part of the task which should be done after all analysis task. Example :
In general, analysis tasks represent the core part of a task, completing the main part of the job. The termination tasks complete the cleaning part.
Now we know how Squalix runs, let's see how to implement a new tool in Squale.
To implement a new tool, obviously you have to create an analysis task and/or a termination task and a bit more regarding the kind of task you wish to implement.
First answer this short list of questions, for each task :
Now let's see how create a task.
If you create a task to recover metric informations go to part II.1. Else go directly to part II.2.
List all the metric you want to recover and their level ( method, class, package, project, ...).
Then you should create a class tree like this scheme :

For the class tree :
Contents of these classes ?
All these classes extends MeasureBO.java which contains a map. The main aim of these classes is to put elements into this map. Example :
private static final String SUMVG = "sumVg";
public JavancssClassMetricsBO()
{
super();
// getMetric() recover the map define in MeasureBO
// We put element in this map
getMetrics().put( CLASSES, new IntegerMetricBO() );
getMetrics().put( METHODS, new IntegerMetricBO() );
getMetrics().put( MAXVG, new IntegerMetricBO() );
getMetrics().put( SUMVG, new IntegerMetricBO() );
}
public Integer getSumVg()
{
return (Integer) ( (IntegerMetricBO) getMetrics().get( SUMVG ) ).getValue();
}
public void setSumVg( int pSumVg )
{
( (IntegerMetricBO) getMetrics().get( SUMVG ) ).setValue( pSumVg );
}
You should define :
Now we could create the task.
All the tasks are in the package src/main/java/org/squale/squalix/tools/
In this package create a new package which name will be taskName. (In general the name of the task is the name of the tool which will compute the metrics). Put in this package all the classes you created especially for this task.
To create an analysis task go to part II.2.b. To create a termination task go to part II.2.c.
For an analysis task you should create a class.
In the following of the document mName correspond to : taskNameTask.
For a termination task, you should create a class.
Bellow in the document the reference mName correspond to : taskNameyyyTask.
We recommend that a task work in three separate step
see part I.3 for more information on specification regarding the execution of the task.
How Squalix know that a class correspond to an analysis task and another correspond to a termination task ?
In fact this is defined in the squalix-config.xml file.
A complete specification on how to create more generic tools (especially tools which do recover metrics) is in progress. More detail soon
In this part you will recover all informations of configuration.
//Recovering of the map of parameter
MapParameterBO taskParam = (MapParameterBO) mProject.getParameter( ParametersConstants.SCM );
//Recovering of the parameters
ListParameterBO pathToAudit =
(ListParameterBO) taskParam.getParameters().get( ParametersConstants.SCMLOCATION );
StringParameterBO password =
(StringParameterBO) pTaskParam.getParameters().get( ParametersConstants.SCMPASSWORD );
More informations on the static variables of ParametersConstants used here in the part III.4
This part of the code is the one which does the job. Example for a source recovering tool, it's in this part that we will recover the code. We encourage you to use already existent code. For example if for the software you want use, an ant task exists, then try to use this ant task, than to rewrite a launcher.
For task which does recover metrics that will be pushed in the database, results should be saved in a file (xml, csv).
We advise against do the execution and push in the database in the same time without pass by a file result.
This part is dedicated to task which recovers metrics. This part should, if possible, run separately from the previous step. This part should take a result file ( file which comes from the execution or is external ) and parse it.
It's here, that we will use the xxxMetricBO that we have created above. We fill it by using informations from the parsing operation.
To search and create the componentBO (applicationBO, packageBO, classBO, methodBO ) use the code already existent in Squale.
// Completion of the package level BO and recording of new components
/* With the parsing we have create an arraylist of JavancssPackageMetricsBO
* fill with the information from the parse.
*/
ArrayList packageResults = parsingResult.getPackageResult();
for ( int i = 0; i < packageResults.size(); i++ )
{
JavancssPackageMetricsBO packageMetrics =
(JavancssPackageMetricsBO) packageResults.get( i );
/* We create the packageBO corresponding to the component name
* include in the JavancssPackageMetricsBO
*/
PackageBO packBO = parser.getPackage( packageMetrics.getComponentName() );
packageMetrics.setAudit( getAudit() );
/* repository.persisteComponent( packBO ) permit to persit the packageBO
* (and its parents) if is(are) not already exist.
*/
packageMetrics.setComponent( repository.persisteComponent( packBO ) );
packageMetrics.setTaskName( getName() );
}
// Recording of the package level results.
MeasureDAOImpl.getInstance().saveAll( getSession(), parsingResult.getPackageResult() );
A generic squalix-config.xml file could be found in : squale-core/src/main/config.
Define in Squalix-config.xml the new task, and modify the profile define in this file to take into account new tasks.
Only administrator has the needed authorisation to put into squale the new squalix-config file.
We need the list of informations of configuration that the user should enter.
The new jsp that we create, will be called by config_project.jsp (Squale-web/src/main/webapp/jsp/admin/project). Config_project.jsp will include our jsp in a dropdown panel by using a <jsp:include> tag.
Extract of code of config_project.jsp.
<logic:iterate id="task" scope="session" name="createProjectForm" property="advancedTasks">
<bean:define name="task" property="name" id="taskName" type="String" />
<%expanded = false;%>
<logic:equal name="toolBean" value="<%=taskName%>">
<%expanded = true; %>
</logic:equal>
<%
// recuperation des clés
String keyTask = "task." + taskName.toLowerCase() + ".configuration";
// récupération de la page
String pageTask = "add_project_" + taskName.toLowerCase() + "_conf.jsp";%>
<af:dropDownPanel titleKey="<%=keyTask%>"
headerStyle="padding-left:20px;" contentStyle="padding:5px;"
lazyLoading="false" expanded="<%=expanded%>">
<c:import url="/${taskName}.do?action=fill&${org.squale.squaleweb.
applicationlayer.action.accessRights.BaseDispatchAction.DO_NOT_RESET_FORM}=true" />
<div id="conteneur"><jsp:include page="<%=pageTask%>" /></div>
</af:dropDownPanel>
</logic:iterate>
Steps to create the form bean class :
Now creation of the jsp.
That JSP will be used in a <jsp:include> tag in the jsp config_project.jsp (See extract of the code above)
// For one parameter :
<tr class="fondClair">
<af:field key="project_creation.field.login" name="scmForm"
property="login" isRequired="false" styleClassLabel="td1" size="60"
disabled="<%=disabled%>" />
</tr>
// For a list of parameter (here paths to the sources ; we could have more one path) :
<tr>
<af:field styleClassLabel="td1"
key="project_creation.field.pathToAudit" property="location"
value="" size="60" />
</tr>
<squale:iteratePaths name="scmForm"
key="project_creation.field.pathToAudit" property="location"
isRequired="true" disabled="<%=disabled%>" />
<%-- Readers can't update the configuration --%>
<bean:define id="userProfile"
name="<%=org.squale.welcom.struts.util.WConstants.USER_KEY%>"
property='<%="profile("+applicationId+")"%>' />
<%-- All the fields --%>
<%boolean disabled = false; // Used to grant writing %>
<logic:equal name="userProfile"
value="<%=ProfileBO.READER_PROFILE_NAME%>">
<%disabled = true;%>
</logic:equal>
For all details, take example on the already existent jsp (ex : add_project_scmTask_conf.jsp ) to create yours.
Steps to create the action class
Let's see the ParametersConstants
For each parameter of configuration that has to be recovered, create a new public static final variable in the class ParametersConstants (squale-core/src/main/java/org/squale/squalecommon/enterpriselayer/businessobject/component/parameters).
Steps to create the transformer :
public WActionForm objToForm( Object[] pObject )
throws WTransformerException
{
ScmForm scmForm = new ScmForm();
objToForm( pObject, scmForm );
return scmForm;
}
public void objToForm( Object[] pObject, WActionForm pForm )
throws WTransformerException
{
MapParameterDTO projectParams = (MapParameterDTO) pObject[0];
MapParameterDTO params =
(MapParameterDTO) projectParams.getParameters().get( ParametersConstants.SCM );
if ( params != null )
{
// Fill the form
ScmForm scmForm = (ScmForm) pForm;
Map ccParams = params.getParameters();
// User profile to connect to the remote repository
StringParameterDTO login =
(StringParameterDTO) ccParams.get( ParametersConstants.SCMLOGIN );
scmForm.setLogin( login.getValue() );
// Location of paths to audit
ListParameterDTO locationsDTO =
(ListParameterDTO) ccParams.get( ParametersConstants.SCMLOCATION );
List locationsList = locationsDTO.getParameters();
Iterator it = locationsList.iterator();
String[] locations = new String[locationsList.size()];
int index = 0;
while ( it.hasNext() )
{
StringParameterDTO location = (StringParameterDTO) it.next();
if (location.getValue() == null) {
locations[index] = " ";
} else {
locations[index] = location.getValue();
}
index++;
}
scmForm.setLocation( locations );
}
}
Add <form-bean> and <action> taggs in struts-config.xml
For the action, the name should be mName . This means that we call the action with : mName.do. This is necessary in config_project.jsp (squale-web : src/main/webapp/jsp/admin/project). See the extract of code above.
Add the new keys used in the JSP in the document ApplicationRessource.properties, do not forget to translate the key/value couple in English/French and is derivative in different language (squale-web : src/main/java/org/squale/squaleweb/ressources/). Warning some of this key need a special name. See the extract of code above.
Now we have recovered the metric informations and pushed them in the database. But it's not enough, we want to use these informations in the results of the audit.
For this :
A new grid quality which take the new metrics into account should be wrote. This quality grid for Squale is an xml file which uses the dtd : org/squale/squalecommon/dtd/grid-1.1.dtd. Example of quality grid could be found in squale-core/src/main/config.
Only administrator can put into squale the new grid.
Squalix-config.xml should be modified in order to take into account the new quality grid. A generic squalix-config.xml file could be found in : squale-core/src/main/config.
Only administrator can put into squale the new squalix-config file.
Labels for the new measures appearing in the squale results page. Add the new elements needed in the messages.xml (Squale-core : src/main/config/).
Modify the file Mapping.java ( squale-core : src/main/java/org/squale/squalecommon/util/mapping/ )