Java tutorial
/** * 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.Date; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.FlushMode; import org.hibernate.HibernateException; import org.hibernate.Session; import org.squale.jraf.commons.exception.JrafDaoException; import org.squale.jraf.provider.persistence.hibernate.SessionImpl; 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.AuditDisplayConfDAOImpl; import org.squale.squalecommon.daolayer.component.AuditGridDAOImpl; import org.squale.squalecommon.daolayer.config.AdminParamsDAOImpl; 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.AuditDisplayConfBO; import org.squale.squalecommon.enterpriselayer.businessobject.component.AuditGridBO; import org.squale.squalecommon.enterpriselayer.businessobject.component.ProjectBO; import org.squale.squalecommon.enterpriselayer.businessobject.config.AdminParamsBO; import org.squale.squalecommon.enterpriselayer.businessobject.config.Profile_DisplayConfBO; 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.result.QualityResultCommentBO; 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.manualmark.TimeLimitationParser; 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 final class AuditComputing { /** Log */ private static Log LOG = LogFactory.getLog(AuditComputing.class); /** * Define whether or not we need at least two values to compute criterias or factors. * 1 if we need two values. * 0 if one is enough */ private static int MIN_NUMBER_OF_PRACTICES_OR_CRITERIAS = 1; /** * Define private constructor for utility class */ private AuditComputing() { } /** * 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 * @return true If the last mark for a manual practice is out of date * @throws JrafDaoException si erreur */ public static boolean computeAuditResult(ISession pSession, ProjectBO pProject, AuditBO pAudit) throws JrafDaoException { boolean warning = false; 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 // first : do we need at least two practices or two criterias to compute criterias or factors List adminParamsList = AdminParamsDAOImpl.getInstance().findByKey(pSession, AdminParamsBO.TWO_TO_COMPUTE); //we check if the parameter TWO_TO_COMPUTE exists if (adminParamsList.size() > 0) { AdminParamsBO paramsBO = (AdminParamsBO) adminParamsList.get(0); //we check the value and change the min number of criterias / practices if necessary if (paramsBO.getParamValue().equals("false")) { MIN_NUMBER_OF_PRACTICES_OR_CRITERIAS = 0; } else { MIN_NUMBER_OF_PRACTICES_OR_CRITERIAS = 1; } } // Traitement des pratiques warning = 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); // Ajout des configurations Collection confs = pProject.getProfile().getProfileDisplayConfs(); for (Iterator it = confs.iterator(); it.hasNext();) { AuditDisplayConfBO auditConf = new AuditDisplayConfBO(); auditConf.setDisplayConf(((Profile_DisplayConfBO) it.next()).getDisplayConf()); auditConf.setProject(pProject); auditConf.setAudit(pAudit); AuditDisplayConfDAOImpl.getInstance().create(pSession, auditConf); // Ajout l'audit pAudit.addAuditDisplayConf(auditConf); } AuditDAOImpl.getInstance().save(pSession, pAudit); } finally { LOG.info(RuleMessages.getString("computation.end")); } return warning; } /** * 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().keySet().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().keySet().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 sumOfCriteriaWeight = 0; float criteriaSum = 0; // Note cumule // Parcours des criteres du facteur Iterator it = factor.getCriteria().keySet().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()) { float criteriaWeight = ((Float) factor.getCriteria().get(criteriumResult.getRule())) .floatValue(); criteriaSum += criteriumResult.getMeanMark() * criteriaWeight; sumOfCriteriaWeight += criteriaWeight; nbCriteria++; } } // the value of MIN_NUMBER_OF_PRACTICES_OR_CRITERIAS depends on whether or not we // need at least two values to compute factors. This param is set in squale-config file if (nbCriteria > MIN_NUMBER_OF_PRACTICES_OR_CRITERIAS) { // calcul de la note du facteur result.setMeanMark(criteriaSum / sumOfCriteriaWeight); 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; float sumOfPracticesWeight = 0; float practicesSum = 0; // Note cumule // Parcours des pratiques du critre Iterator it = criterium.getPractices().keySet().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()) { float practiceWeight = ((Float) criterium.getPractices().get(praticeResult.getRule())) .floatValue(); practicesSum += praticeResult.getMeanMark() * practiceWeight; sumOfPracticesWeight += practiceWeight; nbPractices++; } } // the value of MIN_NUMBER_OF_PRACTICES_OR_CRITERIAS depends on whether or not we // need at least two values to compute criterias. This param is set in squale-config file if (nbPractices > MIN_NUMBER_OF_PRACTICES_OR_CRITERIAS) { // calcul de la note du facteur result.setMeanMark(practicesSum / sumOfPracticesWeight); 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 * @return true If the last mark for a manual practice is out of date * @throws JrafDaoException si erreur */ private static boolean computePracticesResults(ISession pSession, ProjectBO pProject, AuditBO pAudit, Map pPractices) throws JrafDaoException { boolean warning = false; // 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); // Processing of the manual practices warning = computeManualPractices(pSession, pProject, (Collection) kindPractices.remove(""), 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 Collection marks = computePracticeResults(pSession, pAudit, interpreter, practice, practiceResult, children); // Calcul de la note globale de la pratique computePracticeMark(practice, practiceResult, marks); } catch (FormulaException fe) { // 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() }), fe); } catch (WeightFunctionException wfe) { // Si une erreur se produit sur le calcul d'une formule // on stoppe le calcul pour cette pratique LOG.error( RuleMessages.getString("function.error", new Object[] { practice.getWeightFunction(), practice.getName() }), wfe); } // 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); } } } return warning; } /** * 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 * @param pMarks les notes des composants impliqus * @throws WeightFunctionException si erreur */ private static void computePracticeMark(PracticeRuleBO pPractice, PracticeResultBO pPracticeResult, Collection pMarks) throws WeightFunctionException { /* * Formule : meanMark = weigh^-1(1/N sum(weight(note(component)))) Cela revient faire la moyenne des notes * auxquelles on applique la fonction la fonction de pondration weight puis appliquer la fonction inverse */ // Moyenne des notes : 1/N * sum(weight(note(component)) float num = 0; float denum = 0; float average = -1; // Interpreteur python WeightFunctionInterpreter interpreter = new WeightFunctionInterpreter(); for (Iterator marksIt = pMarks.iterator(); marksIt.hasNext();) { // note(component) float mark = ((MarkBO) marksIt.next()).getValue(); // Si la note sur le composant a t calcul if (mark != MarkBO.NOT_NOTED_VALUE) { // weigth(note(component)) float weightMark = interpreter.exec(pPractice.getWeightFunction(), mark); num += weightMark; denum++; } } if (denum != 0) { // Moyenne average = num / denum; // weight^-1(average) Float meanMark = inverse(interpreter, pPractice.getWeightFunction(), average); pPracticeResult.setMeanMark(meanMark.floatValue()); } else { LOG.debug(RuleMessages.getString("nocomputation", new Object[] { pPractice.getName() })); } } /** * Fait le calcul de la fonction inverse. * * @param pInterpreter l'interprteur pour une fonction de pondration * @param pFunction la fonction de pondration * @param pY : pFunction(x) = pY * @return x tel que f(x) = pY * @throws WeightFunctionException si erreur */ private static Float inverse(WeightFunctionInterpreter pInterpreter, String pFunction, float pY) throws WeightFunctionException { // prcision de x : 10^-3 final double signi = 3; final double pow = 10; double epsilon = Math.pow(pow, -signi) / 2; // x est compris entre 0 et 3 final float minMark = 0; final float maxMark = 3; float x1 = minMark, x2 = (minMark + maxMark) / 2, x3 = maxMark; float fX1 = pInterpreter.exec(pFunction, x1), fX2 = pInterpreter.exec(pFunction, x2); float fX3 = pInterpreter.exec(pFunction, x3); float old = x1; // Tant que x n'est pas avec la prcision voulu while (Math.abs(x2 - old) > epsilon) { old = x2; // si y est entre fX1 et fX2 if ((fX1 <= pY && fX2 > pY) || (fX1 >= pY && fX2 < pY)) { // On se recale entre x1 et x2 x3 = x2; fX3 = fX2; } else { // On se recale entre x2 et x3 x1 = x2; fX1 = fX2; } // nouvelle valeur cible par dichotomie x2 = (x1 + x3) / 2; fX2 = pInterpreter.exec(pFunction, x2); } // Arrondie au nombre de chiffres significatifs final double round = 0.5; double num = (x2 * Math.pow(pow, signi) + round); return new Float((double) ((int) (x2 * Math.pow(pow, signi) + round)) / Math.pow(pow, signi)); } /** * 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 * @return les notes * @throws FormulaException si erreur * @throws JrafDaoException si erreur */ private static Collection 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(); // On stocke les notes ArrayList marks = new ArrayList(); 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.debug(RuleMessages.getString("missingmeasure", new Object[] { measureKinds[i], componentId, auditId })); } } // On calcul la note seulement si toutes les mesures requises sont bien prsentes if (measuresNotNull) { MarkBO mark = computeMark(pSession, pInterpreter, measures, pPractice, pPracticeResult, child); marks.add(mark); } } return marks; } /** * 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 * @return la note * @throws FormulaException si erreur * @throws JrafDaoException si erreur */ private static MarkBO 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(MarkBO.NOT_NOTED_VALUE); } else { mark.setValue(value.floatValue()); } // Mise jour de la rpartition des notes pPracticeResult.incrementRepartition(mark.getValue()); // Enregistrement de la note MarkDAOImpl.getInstance().save(pSession, mark); return mark; } /** * This method push into the base, for the current audit, the manual mark which are filled and still valid * * @param session Hibernate session * @param project The project * @param manualPractices collection of practice without level (manual practice) * @param practicesMap map of all the practice. * @return true If the last mark for a manual practice is out of date * @throws JrafDaoException Exception happened during hibernate work */ private static boolean computeManualPractices(ISession session, ProjectBO project, Collection manualPractices, Map practicesMap) throws JrafDaoException { boolean warning = false; if (manualPractices != null) { try { QualityResultDAOImpl dao = QualityResultDAOImpl.getInstance(); // For each manual practice we try to set a mark for the audit Iterator<PracticeRuleBO> practicesIt = manualPractices.iterator(); while (practicesIt.hasNext()) { PracticeRuleBO practice = practicesIt.next(); LOG.info(RuleMessages.getString("computation.practice", new Object[] { practice.getName() })); // search of the last manual mark inserted PracticeResultBO manualPraticeResult = dao.findLastManualMark(session, project.getId(), practice.getId()); // If there is one manual mark inserted if (manualPraticeResult != null) { // recovering of the PracticeResultBO which will recorded PracticeResultBO practiceResult = (PracticeResultBO) practicesMap.get(practice); /* * If the current date is before the date of creation of the manual mark plus the period of * validity then we put the mark for the current audit. */ if (isMarkValid(practice, manualPraticeResult)) { practiceResult.setMeanMark(manualPraticeResult.getMeanMark()); practiceResult.setCreationDate(manualPraticeResult.getCreationDate()); //We add the comments if it exists if (manualPraticeResult.getManualMarkComment() != null) { QualityResultCommentBO practiceResultComments = new QualityResultCommentBO(); practiceResultComments.setQualityResult(practiceResult); practiceResultComments .setComments(manualPraticeResult.getManualMarkComment().getComments()); practiceResult.setManualMarkComment(practiceResultComments); } dao.save(session, practiceResult); } else { warning = true; } } } } catch (HibernateException e) { throw new JrafDaoException(e); } } return warning; } /** * This method determine whether the mark is valid (according to the period validity) * * @param practice The practice for the current audit * @param manualPraticeResult The last manualPratice inserted * @return true if the the mark is valid */ private static boolean isMarkValid(PracticeRuleBO practice, PracticeResultBO manualPraticeResult) { boolean valid = true; // Date of creation of the manual mark Date creationDate = manualPraticeResult.getCreationDate(); // The validity period String validityPeriod = practice.getTimeLimitation(); // Test the validity of the mark valid = TimeLimitationParser.isMarkValid(validityPeriod, creationDate); return valid; } }