org.squale.squalecommon.enterpriselayer.facade.rule.AuditComputing.java Source code

Java tutorial

Introduction

Here is the source code for org.squale.squalecommon.enterpriselayer.facade.rule.AuditComputing.java

Source

/**
 * Copyright (C) 2008-2010, Squale Project - http://www.squale.org
 *
 * This file is part of Squale.
 *
 * Squale is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or any later version.
 *
 * Squale is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Squale.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.squale.squalecommon.enterpriselayer.facade.rule;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.Session;

import org.squale.jraf.commons.exception.JrafDaoException;
import org.squale.jraf.helper.LoggingHelper;
import org.squale.jraf.provider.persistence.hibernate.SessionImpl;
import org.squale.jraf.spi.logging.ILogger;
import org.squale.jraf.spi.persistence.ISession;
import org.squale.squalecommon.daolayer.component.AbstractComponentDAOImpl;
import org.squale.squalecommon.daolayer.component.AuditDAOImpl;
import org.squale.squalecommon.daolayer.component.AuditGridDAOImpl;
import org.squale.squalecommon.daolayer.result.MarkDAOImpl;
import org.squale.squalecommon.daolayer.result.MeasureDAOImpl;
import org.squale.squalecommon.daolayer.result.QualityResultDAOImpl;
import org.squale.squalecommon.enterpriselayer.businessobject.component.AbstractComponentBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.AuditBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.AuditGridBO;
import org.squale.squalecommon.enterpriselayer.businessobject.component.ProjectBO;
import org.squale.squalecommon.enterpriselayer.businessobject.result.CriteriumResultBO;
import org.squale.squalecommon.enterpriselayer.businessobject.result.FactorResultBO;
import org.squale.squalecommon.enterpriselayer.businessobject.result.MarkBO;
import org.squale.squalecommon.enterpriselayer.businessobject.result.MeasureBO;
import org.squale.squalecommon.enterpriselayer.businessobject.result.PracticeResultBO;
import org.squale.squalecommon.enterpriselayer.businessobject.rule.AbstractFormulaBO;
import org.squale.squalecommon.enterpriselayer.businessobject.rule.CriteriumRuleBO;
import org.squale.squalecommon.enterpriselayer.businessobject.rule.FactorRuleBO;
import org.squale.squalecommon.enterpriselayer.businessobject.rule.PracticeRuleBO;
import org.squale.squalecommon.util.mapping.Mapping;

/**
 * Calcul d'un audit
 * Le calcul d'un audit s'appuie sur des rgles dcrites dans la grille qualit,
 * celle-ci est rattache  un projet. Les rgles sont exprimes en fonction de
 * mtriques obtenues par des outils comme mccabe par exemple.
 */
public class AuditComputing {
    /** Log */
    private static ILogger LOG = LoggingHelper.getInstance(AuditComputing.class);

    /**
     * Calcul d'un audit
     * Le calcul d'un audit se fait  partir des pratiques pour remonter vers les
     * facteurs
     * @param pSession session
     * @param pProject projet
     * @param pAudit audit
     * @throws JrafDaoException si erreur
     */
    public static void computeAuditResult(ISession pSession, ProjectBO pProject, AuditBO pAudit)
            throws JrafDaoException {
        try {
            LOG.info(RuleMessages.getString("computation.start"));
            // Dcomposition de la grille en facteurs, criteres, pratiques
            Map factors = new Hashtable();
            Map criteria = new Hashtable();
            Map practices = new Hashtable();
            // Les maps contiennent en clef la rgle et en valeur le rsultat calcul
            flattenQualitfyGrid(pSession, pProject, pAudit, factors, criteria, practices);

            // Le traitement se fait dans l'ordre hirarchique inverse
            // cel permet d'viter les calculs multiples pour des facteurs
            // ou des critres plusieurs fois prsents

            // Traitement des pratiques
            computePracticesResults(pSession, pProject, pAudit, practices);
            // Traitement des criteres
            computeCriteriaResults(pSession, criteria, practices);
            // Traitement des facteurs
            computeFactorsResults(pSession, factors, criteria, practices);
            // Ajout de la grille qualit
            AuditGridBO auditGrid = new AuditGridBO();
            auditGrid.setGrid(pProject.getQualityGrid());
            auditGrid.setProject(pProject);
            auditGrid.setAudit(pAudit);
            AuditGridDAOImpl.getInstance().create(pSession, auditGrid);
            // Ajout  l'audit
            pAudit.addAuditGrid(auditGrid);
            AuditDAOImpl.getInstance().save(pSession, pAudit);
        } finally {
            LOG.info(RuleMessages.getString("computation.end"));
        }
    }

    /**
     * Mise  plat d'une grille qualit
     * La structure hirarchique de la grille qualit est mise  plat
     * sous la forme de 3 maps qui contiennent les rgles en fonction de leur
     * typologie
     * @param pSession session
     * @param pProject projet
     * @param pAudit audit
     * @param pFactors map des facteurs
     * @param pCriteria map des critres
     * @param pPractices map des pratiques
     * @throws JrafDaoException si erreur
     */
    private static void flattenQualitfyGrid(ISession pSession, ProjectBO pProject, AuditBO pAudit, Map pFactors,
            Map pCriteria, Map pPractices) throws JrafDaoException {
        // Le parcours consiste  construire 3 maps avec les facteurs, criteres et pratiques
        // Ce partionnement permet le traitement plus efficace d'au audit dans le cas o des critres
        // ou des pratiques apparaissent de faon multiple
        // On place aussi dans ces map, en tant que valeur le rsultat associ, par exemple
        // la map des facteurs contient les FactorRuleBO et les FactorResultBO
        Iterator factors = pProject.getQualityGrid().getFactors().iterator();
        // Parcours des facteurs
        while (factors.hasNext()) {
            FactorRuleBO factor = (FactorRuleBO) factors.next();
            // Cration du rsultat associ
            FactorResultBO fResult = new FactorResultBO();
            fResult.setRule(factor);
            fResult.setProject(pProject);
            fResult.setAudit(pAudit);
            pFactors.put(factor, fResult);
            QualityResultDAOImpl.getInstance().create(pSession, fResult);
            Iterator criteria = factor.getCriteria().iterator();
            // Parcours des critres
            while (criteria.hasNext()) {
                CriteriumRuleBO criterium = (CriteriumRuleBO) criteria.next();
                // Un critre peut tre prsent dans plusieurs facteurs
                // On ne le rajoute que si ncessaire
                if (pCriteria.get(criterium) == null) {
                    // Cration du rsultat associ
                    CriteriumResultBO cResult = new CriteriumResultBO();
                    cResult.setRule(criterium);
                    cResult.setProject(pProject);
                    cResult.setAudit(pAudit);
                    QualityResultDAOImpl.getInstance().create(pSession, cResult);
                    // Ajout dans la map
                    pCriteria.put(criterium, cResult);
                }
                Iterator practices = criterium.getPractices().iterator();
                // Parcours des pratiques
                while (practices.hasNext()) {
                    PracticeRuleBO practice = (PracticeRuleBO) practices.next();
                    // Une pratique peut tre prsente dans plusieurs critres
                    // On ne le rajoute que si ncessaire
                    if (pPractices.get(practice) == null) {
                        // Cration du rsultat associ
                        PracticeResultBO pResult = new PracticeResultBO();
                        pResult.setRule(practice);
                        pResult.setProject(pProject);
                        pResult.setAudit(pAudit);
                        QualityResultDAOImpl.getInstance().create(pSession, pResult);
                        // Ajout dans la map
                        pPractices.put(practice, pResult);
                    }
                }
            }
        }
    }

    /**
     * Calcul des facteurs
     * Chaque facteur est calcul en fonction des critres qui le composent
     * @param pSession session
     * @param pFactors facteurs
     * @param pCriteria critres
     * @param pPractices pratiques
     * @throws JrafDaoException si erreur
     */
    private static void computeFactorsResults(ISession pSession, Map pFactors, Map pCriteria, Map pPractices)
            throws JrafDaoException {
        // On parcourt chaque facteur et on calcule son rsultat
        Iterator factors = pFactors.keySet().iterator();
        while (factors.hasNext()) {
            // Rcupration du facteur et du rsultat
            FactorRuleBO factor = (FactorRuleBO) factors.next();
            LOG.info(RuleMessages.getString("computation.factor", new Object[] { factor.getName() }));
            FactorResultBO result = (FactorResultBO) pFactors.get(factor);
            // Le calcul se fait par une moyenne simple sur les critres
            // calculs si au moins 2 criteres ont t calculs
            int nbCriteria = 0; // Nombre de criteres calculs
            float criteriaSum = 0; // Note cumule
            // Parcours des criteres du facteur
            Iterator it = factor.getCriteria().iterator();
            // Pour chaque critre, on rcupre les valeurs calcules
            while (it.hasNext()) {
                CriteriumResultBO criteriumResult = (CriteriumResultBO) pCriteria.get(it.next());
                // Nota : criteriumResult ne peut pas tre null
                if (-1 != criteriumResult.getMeanMark()) {
                    criteriaSum += criteriumResult.getMeanMark();
                    nbCriteria++;
                }
            }
            // Calcul seulement s'il existe au moins deux rsultats
            if (nbCriteria > 1) {
                // calcul de la note du facteur
                result.setMeanMark(criteriaSum / nbCriteria);
                QualityResultDAOImpl.getInstance().save(pSession, result);
            } else {
                LOG.debug(RuleMessages.getString("nocomputation", new Object[] { factor.getName() }));
            }
        }
    }

    /**
     * Calcul des critres
     * Chaque critre est calcul en fonction des rsultats de ses pratiques
     * @param pSession session
     * @param pCriteria critres
     * @param pPractices pratiques
     * @throws JrafDaoException si erreur
     */
    private static void computeCriteriaResults(ISession pSession, Map pCriteria, Map pPractices)
            throws JrafDaoException {
        // On parcourt chaque critre et on calcule son rsultat
        Iterator criteria = pCriteria.keySet().iterator();
        while (criteria.hasNext()) {
            // Rcupration du critre et de son rsultat
            CriteriumRuleBO criterium = (CriteriumRuleBO) criteria.next();
            LOG.info(RuleMessages.getString("computation.criterium", new Object[] { criterium.getName() }));
            CriteriumResultBO result = (CriteriumResultBO) pCriteria.get(criterium);
            // La moyenne se fait par un moyenne simple sur les pratiques
            // calculs si au moins deux pratiques ont t calcules
            int nbPractices = 0; // Nombre de criteres calculs
            float practicesSum = 0; // Note cumule
            // Parcours des pratiques du critre
            Iterator it = criterium.getPractices().iterator();
            // Pour chaque critre, on rcupre les valeurs calcules
            while (it.hasNext()) {
                PracticeResultBO praticeResult = (PracticeResultBO) pPractices.get(it.next());
                // Nota : criteriumResult ne peut pas tre null
                if (-1 != praticeResult.getMeanMark()) {
                    practicesSum += praticeResult.getMeanMark();
                    nbPractices++;
                }
            }
            // Calcul seulement s'il existe au moins deux rsultats
            if (nbPractices > 1) {
                // calcul de la note du facteur
                result.setMeanMark(practicesSum / nbPractices);
                QualityResultDAOImpl.getInstance().save(pSession, result);
            } else {
                LOG.debug(RuleMessages.getString("nocomputation", new Object[] { criterium.getName() }));
            }
        }
    }

    /**
     * Calcul des pratiques
     * Chaque pratique est calcule, son rsultat est crit en base de donnes
     * @param pSession session
     * @param pProject projet
     * @param pAudit audit
     * @param pPractices pratiques
     * @throws JrafDaoException si erreur
     */
    private static void computePracticesResults(ISession pSession, ProjectBO pProject, AuditBO pAudit,
            Map pPractices) throws JrafDaoException {
        // Les pratiques sont tries par par type
        // de composant pour eviter les appels multiples de recuperation des
        // composants du projet
        Map kindPractices = splitPracticesByKind(pPractices);
        // On traite sparement les pratiques de niveau projet
        computeProjectPractices(pSession, pProject, pAudit, (Collection) kindPractices.remove("project"),
                pPractices);
        Iterator kinds = kindPractices.keySet().iterator();
        while (kinds.hasNext()) {
            String kind = (String) kinds.next();
            LOG.info(RuleMessages.getString("computation.kind", new Object[] { kind }));
            // sauvegarde du mode actuel de flush
            Session hibernateSession = ((SessionImpl) pSession).getSession();
            FlushMode oldFlushMode = hibernateSession.getFlushMode();
            // On ne traite pas les pratiques qui n'ont pas de composant associ
            // (elles n'ont pas de formule)
            if (kind.length() > 0) {
                try {
                    // flush de la session
                    hibernateSession.flush();
                    // le flush automatique est dsactiv pendant tout le calcul de chaque notes
                    hibernateSession.setFlushMode(FlushMode.NEVER);

                    // Recupration des enfants de bons niveaux... 
                    Collection children = AbstractComponentDAOImpl.getInstance().findProjectChildren(pSession,
                            pProject, pAudit, Mapping.getComponentClass("component." + kind));
                    Iterator practices = ((Collection) kindPractices.get(kind)).iterator();
                    while (practices.hasNext()) {
                        PracticeRuleBO practice = (PracticeRuleBO) practices.next();
                        LOG.info(RuleMessages.getString("computation.practice",
                                new Object[] { practice.getName() }));
                        PracticeResultBO practiceResult = (PracticeResultBO) pPractices.get(practice);
                        // Vrification de la formule
                        FormulaInterpreter interpreter = new FormulaInterpreter();
                        try {
                            // Vrification de la syntaxe de la formule
                            // un exception est leve si elle est incorrecte
                            interpreter.checkSyntax(practice.getFormula());
                            // Calcul de notes pour chaque enfant
                            computePracticeResults(pSession, pAudit, interpreter, practice, practiceResult,
                                    children);
                            // Calcul de la note globale de la pratique
                            computePracticeMark(practice, practiceResult);
                        } catch (FormulaException e) {
                            // Si une erreur se produit sur le calcul d'une formule
                            // on stoppe le calcul pour cette pratique
                            LOG.error(RuleMessages.getString("formula.error", new Object[] { practice.getName() }),
                                    e);
                        }
                        // Sauvegarde des rsultats de la pratique
                        QualityResultDAOImpl.getInstance().save(pSession, practiceResult);
                    }
                } catch (HibernateException e) {
                    // Cette erreur est lie  la gestion du flushmode, dans ce cas on se contente de remonter
                    // une exception JRAF
                    throw new JrafDaoException(e);
                } finally {
                    // Remise du mode de flush au mode prcedent
                    hibernateSession.setFlushMode(oldFlushMode);
                }
            }
        }
    }

    /**
     * Traitement des pratiques de niveau projet
     * Les pratiques calcules au niveau d'un projet sont traites de faon
     * spcifique, la formule donne une note directement sans avoir  collecter des notes
     * pour chaque composant (comme c'est le cas au niveau de classes ou des mthodes)
     * @param pSession session
     * @param pProject projet
     * @param pAudit audit
     * @param pProjectPractices pratiques de niveau projet
     * @param pPractices pratiques
     * @throws JrafDaoException si erreur
     */
    private static void computeProjectPractices(ISession pSession, ProjectBO pProject, AuditBO pAudit,
            Collection pProjectPractices, Map pPractices) throws JrafDaoException {
        if (pProjectPractices != null) {
            try {
                Iterator practices = pProjectPractices.iterator();
                while (practices.hasNext()) {
                    PracticeRuleBO practice = (PracticeRuleBO) practices.next();
                    LOG.info(RuleMessages.getString("computation.practice", new Object[] { practice.getName() }));
                    PracticeResultBO practiceResult = (PracticeResultBO) pPractices.get(practice);
                    // Vrification de la formule
                    FormulaInterpreter interpreter = new FormulaInterpreter();
                    try {
                        // Vrification de la syntaxe de la formule
                        // un exception est leve si elle est incorrecte
                        interpreter.checkSyntax(practice.getFormula());
                        // Calcul de la note globale de la pratique
                        computeProjectPracticeMark(pSession, pProject, pAudit, interpreter, practice,
                                practiceResult);
                    } catch (FormulaException e) {
                        // Si une erreur se produit sur le calcul d'une formule
                        // on stoppe le calcul pour cette pratique
                        LOG.error(RuleMessages.getString("formula.error", new Object[] { practice.getName() }), e);
                    }
                    // Sauvegarde des rsultats de la pratique
                    QualityResultDAOImpl.getInstance().save(pSession, practiceResult);
                }
            } catch (HibernateException e) {
                // Cette erreur est lie  la gestion du flushmode, dans ce cas on se contente de remonter
                // une exception JRAF
                throw new JrafDaoException(e);
            }
        }

    }

    /**
     * Calcul de la note sur un projet
     * Le calcul de la note sur un projet se fait directement au moyen de la formule associe
     * @param pSession session
     * @param pProject projet
     * @param pAudit audit
     * @param pInterpreter interprte
     * @param pPractice pratique
     * @param pPracticeResult rsultat
     * @throws FormulaException si erreur
     * @throws JrafDaoException si erreur
     */
    private static void computeProjectPracticeMark(ISession pSession, ProjectBO pProject, AuditBO pAudit,
            FormulaInterpreter pInterpreter, PracticeRuleBO pPractice, PracticeResultBO pPracticeResult)
            throws JrafDaoException, FormulaException {
        // Rcupration des types de mesure traits par la formule
        AbstractFormulaBO formula = pPractice.getFormula();
        String[] measureKinds = new String[formula.getMeasureKinds().size()];
        formula.getMeasureKinds().toArray(measureKinds);
        MeasureBO measures[] = new MeasureBO[formula.getMeasureKinds().size()];
        Long projectId = new Long(pProject.getId());
        // Rcupration de chaque mesure
        boolean measuresNotNull = true;
        Long auditId = new Long(pAudit.getId());
        for (int i = 0; i < measureKinds.length; i++) {
            MeasureBO measure = (MeasureBO) MeasureDAOImpl.getInstance().load(pSession, projectId, auditId,
                    Mapping.getMeasureClass(measureKinds[i] + "." + formula.getComponentLevel()));
            measures[i] = measure;
            // Une mesure peut tre absente, ce qui serait li  un problme de cration des mesures
            // dans la phase qui prcde le calcul des notes
            if (measure == null) {
                measuresNotNull = false;
                // On indique le type de mesure qui n'est pas trouv ainsi que le composant concern
                LOG.warn(RuleMessages.getString("missingmeasure",
                        new Object[] { measureKinds[i], projectId, auditId }));
            }
        }
        // On calcul la note seulement si toutes les mesures requises sont bien prsentes
        if (measuresNotNull) {
            // Calcul de la note
            // L'exception dans le calcul est remonte telle quelle
            Number value = pInterpreter.evaluate(pPractice.getFormula(), measures);
            // On place une note -1 si la formule n'a pu tre calcule
            if (value != null) {
                pPracticeResult.setMeanMark(value.floatValue());
            }
        }
    }

    /**
     * Calcul de la note d'une pratique
     * @param pPractice pratique
     * @param pPracticeResult rsultats de la pratique
     */
    private static void computePracticeMark(PracticeRuleBO pPractice, PracticeResultBO pPracticeResult) {
        /*
        * Formule : 
        *             0*nb0*pond0 + 1*nb1*pond1 + 2*nb2*pond2 + 3*nb3*pond3
        * meanMark = -------------------------------------------------------
        *                 nb0*pond0 + nb1*pond1 + nb2*pond2 + nb3*pond3
        */
        float num = 0;
        float denum = 0;
        Iterator coefs = pPractice.getCoefficients().iterator();
        int i = 0;
        while (coefs.hasNext()) {
            Float coef = (Float) coefs.next();
            num += i * pPracticeResult.getRepartition()[i].intValue() * coef.floatValue();
            denum += pPracticeResult.getRepartition()[i].intValue() * coef.floatValue();
            i++;
        }
        if (denum != 0) {
            pPracticeResult.setMeanMark(num / denum);
        } else {
            LOG.debug(RuleMessages.getString("nocomputation", new Object[] { pPractice.getName() }));
        }
    }

    /**
     * Sparation des pratiques par type de composant
     * @param pPractices pratiques
     * @return map de la forme (string,collection) o string donne le type de composant
     * et collection la liste des pratiques sur ce type de composant (string peut tre "")
     */
    private static Map splitPracticesByKind(Map pPractices) {
        Hashtable result = new Hashtable();
        Iterator practices = pPractices.keySet().iterator();
        while (practices.hasNext()) {
            PracticeRuleBO practice = (PracticeRuleBO) practices.next();
            // Les pratiques sans formule sont regroupes
            // avec un kind vide
            String kind = "";
            if (practice.getFormula() != null) {
                kind = practice.getFormula().getComponentLevel();
            }
            Collection practicesKind = (Collection) result.get(kind);
            if (practicesKind == null) {
                practicesKind = new ArrayList();
                result.put(kind, practicesKind);
            }
            practicesKind.add(practice);
        }
        return result;
    }

    /**
     * Calcul des pratiques sur les composants
     * @param pSession session
     * @param pAudit audit
     * @param pInterpreter interprteur
     * @param pPractice pratique
     * @param pPracticeResult rsultat
     * @param pChildren composants fils
     * @throws FormulaException si erreur
     * @throws JrafDaoException si erreur 
     */
    private static void computePracticeResults(ISession pSession, AuditBO pAudit, FormulaInterpreter pInterpreter,
            PracticeRuleBO pPractice, PracticeResultBO pPracticeResult, Collection pChildren)
            throws FormulaException, JrafDaoException {
        // Reinitialisation des rpartitions
        pPracticeResult.resetRepartitions();
        // Rcupration des types de mesure traits par la formule
        AbstractFormulaBO formula = pPractice.getFormula();
        String[] measureKinds = new String[formula.getMeasureKinds().size()];
        formula.getMeasureKinds().toArray(measureKinds);
        MeasureBO measures[] = new MeasureBO[formula.getMeasureKinds().size()];
        Long componentId = null;
        // Traitement de la note pour chaque composant
        Iterator it = pChildren.iterator();
        while (it.hasNext()) {
            AbstractComponentBO child = (AbstractComponentBO) it.next();
            componentId = new Long(child.getId());
            // Rcupration de chaque mesure
            boolean measuresNotNull = true;
            for (int i = 0; i < measureKinds.length; i++) {
                Long auditId = new Long(pAudit.getId());
                MeasureBO measure = (MeasureBO) MeasureDAOImpl.getInstance().load(pSession, componentId, auditId,
                        Mapping.getMeasureClass(measureKinds[i] + "." + formula.getComponentLevel()));
                measures[i] = measure;
                // Une mesure peut tre absente, ce qui serait li  un problme de cration des mesures
                // dans la phase qui prcde le calcul des notes
                if (measure == null) {
                    measuresNotNull = false;
                    // On indique le type de mesure qui n'est pas trouv ainsi que le composant concern
                    LOG.warn(RuleMessages.getString("missingmeasure",
                            new Object[] { measureKinds[i], componentId, auditId }));
                }
            }
            // On calcul la note seulement si toutes les mesures requises sont bien prsentes
            if (measuresNotNull) {
                computeMark(pSession, pInterpreter, measures, pPractice, pPracticeResult, child);
            }
        }
    }

    /**
     * Calcul d'une note sur un composant
     * @param pSession session
     * @param pInterpreter interprte
     * @param pMeasures mesures
     * @param pPractice pratique
     * @param pPracticeResult rsultat de pratique
     * @param pChild composant
     * @throws FormulaException si erreur
     * @throws JrafDaoException si erreur
     */
    private static void computeMark(ISession pSession, FormulaInterpreter pInterpreter, MeasureBO[] pMeasures,
            PracticeRuleBO pPractice, PracticeResultBO pPracticeResult, AbstractComponentBO pChild)
            throws FormulaException, JrafDaoException {
        MarkBO mark = new MarkBO();
        mark.setComponent(pChild);
        mark.setPractice(pPracticeResult);
        // Calcul de la note
        // L'exception dans le calcul est remonte telle quelle
        Number value = pInterpreter.evaluate(pPractice.getFormula(), pMeasures);
        // On place une note -1 si la formule n'a pu tre calcule
        if (value == null) {
            mark.setValue(-1);
        } else {
            mark.setValue(value.intValue());
        }
        // Mise  jour de la rpartition des notes
        if (mark.getValue() >= 0) {
            pPracticeResult.incrementRepartition(mark.getValue());
        }
        // Enregistrement de la note
        MarkDAOImpl.getInstance().save(pSession, mark);
    }

}