/** * 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.daolayer.result; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.squale.jraf.commons.exception.JrafDaoException; import org.squale.jraf.provider.persistence.hibernate.AbstractDAOImpl; import org.squale.jraf.spi.persistence.ISession; import org.squale.squalecommon.daolayer.DAOMessages; import org.squale.squalecommon.datatransfertobject.result.PracticeEvolutionDTO; import org.squale.squalecommon.enterpriselayer.businessobject.component.AbstractComponentBO; import org.squale.squalecommon.enterpriselayer.businessobject.component.ProjectBO; import org.squale.squalecommon.enterpriselayer.businessobject.result.MarkBO; import org.squale.squalecommon.enterpriselayer.businessobject.result.PracticeResultBO; /** * @author M400843 */ public final class MarkDAOImpl extends AbstractDAOImpl { /** * Instance singleton */ private static MarkDAOImpl instance = null; /** log */ private static Log LOG; /** initialisation du singleton */ static { instance = new MarkDAOImpl(); } /** * Constructeur prive * * @throws JrafDaoException */ private MarkDAOImpl() { initialize( MarkBO.class ); LOG = LogFactory.getLog( MarkDAOImpl.class ); } /** * Retourne un singleton du DAO * * @return singleton du DAO */ public static MarkDAOImpl getInstance() { return instance; } /** * Supprime toutes les notes appartenant � l'application * * @param pSession la session * @param pProject le projet * @throws JrafDaoException si une erreur � lieu */ public void removeWhereProject( ISession pSession, ProjectBO pProject ) throws JrafDaoException { String whereClause = "where "; whereClause += getAlias() + ".practice.project.id = " + pProject.getId(); // il reste un probl�me sur la m�thode remove where, // il faut donc faire un find where puis un remove // sur chaque �l�ment de la collection List temp = findWhere( pSession, whereClause ); for ( int i = 0; i < temp.size(); i++ ) { remove( pSession, temp.get( i ) ); } } /** * Supprime toutes les notes li�es au composant * * @param pSession la session * @param pComponent le composant * @throws JrafDaoException si une erreur � lieu */ public void removeWhereComponent( ISession pSession, AbstractComponentBO pComponent ) throws JrafDaoException { String whereClause = "where "; whereClause += getAlias() + ".component.id = " + pComponent.getId(); removeWhere( pSession, whereClause ); } /** * Permet de r�cup�rer les notes en fonction d'une liste de noms de TREs * * @param pSession session Hibernate * @param pComponentID identifiant du composant * @param pAuditID identifiant de l'audit * @param pRuleIds identificateurs des r�gles qualit� * @return liste des valeurs ordonn�s par raopport a la liste des TREs * @throws JrafDaoException exception DAO */ public List findWhere( ISession pSession, Long pComponentID, Long pAuditID, List pRuleIds ) throws JrafDaoException { List marks = new ArrayList(); Iterator it = pRuleIds.iterator(); while ( it.hasNext() ) { Long ruleId = (Long) it.next(); marks.add( load( pSession, pComponentID, pAuditID, ruleId ) ); } return marks; } /** * Permet de r�cup�rer une note en fonction d'un audit * * @param pSession session Hibernate * @param pComponentID identifiant du composant * @param pAuditID identifiant de l'audit * @param pRuleId id du TRE * @return la note associ�e au type de r�sultat, au composant et � l'audit * @throws JrafDaoException exception DAO */ public MarkBO load( ISession pSession, Long pComponentID, Long pAuditID, Long pRuleId ) throws JrafDaoException { String whereClause = "where "; whereClause += getAlias() + ".practice.rule.id = " + pRuleId; whereClause += " and "; whereClause += getAlias() + ".component.id = '" + pComponentID + "'"; whereClause += " and "; whereClause += getAlias() + ".practice.audit.id = '" + pAuditID + "'"; MarkBO mark = null; Collection col = findWhere( pSession, whereClause ); if ( col.size() >= 1 ) { mark = (MarkBO) col.iterator().next(); if ( col.size() > 1 ) { String tab[] = { pAuditID.toString(), pComponentID.toString(), pRuleId.toString() }; LOG.warn( DAOMessages.getString( "mark.many.audit_component_tre", tab ) ); } } return mark; } /** * Permet de r�cup�rer la liste des notes d'une pratique pour d'un audit donn� * * @param pSession session Hibernate * @param pAuditID identifiant de l'audit * @param pRuleId id du TRE * @return la liste des notes associ�es au type de r�sultat et � l'audit * @throws JrafDaoException exception DAO */ @SuppressWarnings( "unchecked" ) public Collection<MarkBO> load( ISession pSession, Long pAuditID, Long pRuleId ) throws JrafDaoException { String whereClause = "where "; whereClause += getAlias() + ".practice.rule.id = " + pRuleId; whereClause += " and "; whereClause += getAlias() + ".practice.audit.id = '" + pAuditID + "'"; return (Collection<MarkBO>) findWhere( pSession, whereClause ); } /** * Retrouve les notes qui ont pour type pTreClass, pour id d'audit pauditId et pour valeur pValue * * @param pSession session Hibernate * @param pAuditId identifiant de l'audit * @param pProjectId id du projet * @param pTreId classe du TRE * @param pValue valeur de la note * @param pMax Nombre maximum de composants retourn� * @return les notes associ�es * @throws JrafDaoException exception DAO */ public Collection findWhere( ISession pSession, Long pAuditId, Long pProjectId, Long pTreId, Integer pValue, Integer pMax ) throws JrafDaoException { String whereClause = "where "; whereClause += getAlias() + ".practice.rule.id = " + pTreId; whereClause += " and "; whereClause += getAlias() + ".practice.audit.id = '" + pAuditId + "'"; whereClause += " and "; whereClause += getAlias() + ".practice.project.id = " + pProjectId; whereClause += " and "; whereClause += whereValueClause( pValue ); Collection ret = (Collection) findWhereScrollable( pSession, whereClause, pMax.intValue(), 0, false ); return ret; } /** * Retrouve les notes qui ont pour type pTreClass, pour id d'audit pauditId et pour valeur pValue * * @param pSession session Hibernate * @param pAuditId identifiant de l'audit * @param pProjectId id du projet * @param pTreId classe du TRE * @param pValueMin valeur min de l'intervalle * @param pValueMax valeur max de l'intervalle * @param pMax Nombre maximum de composants retourn� * @return les notes associ�es * @throws JrafDaoException exception DAO */ public Collection findWhereInterval( ISession pSession, Long pAuditId, Long pProjectId, Long pTreId, Double pValueMin, Double pValueMax, Integer pMax ) throws JrafDaoException { String whereClause = "where "; whereClause += getAlias() + ".practice.rule.id = " + pTreId; whereClause += " and "; whereClause += getAlias() + ".practice.audit.id = '" + pAuditId + "'"; whereClause += " and "; whereClause += getAlias() + ".practice.project.id = " + pProjectId; whereClause += " and "; whereClause += whereValueClause( pValueMin.doubleValue(), pValueMax.doubleValue() ); Collection ret = (Collection) findWhereScrollable( pSession, whereClause, pMax.intValue(), 0, false ); return ret; } /** * @param pValue la valeur de l'index * @return le crit�re de recher sur la note pour la clause where */ private String whereValueClause( Integer pValue ) { // Si il n'y a pas de statut associ� � l'index, le composant est non not� (-->value=-1) String result = getAlias() + ".value = " + -1; if ( pValue.intValue() == PracticeResultBO.REFUSED_MIN ) { result = getAlias() + ".value >= " + PracticeResultBO.REFUSED_MIN; result += " and " + getAlias() + ".value < " + PracticeResultBO.REFUSED_MAX; } else if ( pValue.intValue() == PracticeResultBO.NEARLY_ACCEPTED_MIN ) { result = getAlias() + ".value >= " + PracticeResultBO.NEARLY_ACCEPTED_MIN; result += " and " + getAlias() + ".value < " + PracticeResultBO.NEARLY_ACCEPTED_MAX; } else if ( pValue.intValue() == PracticeResultBO.ACCEPTED_MIN ) { result = getAlias() + ".value >= " + PracticeResultBO.ACCEPTED_MIN; result += " and " + getAlias() + ".value < " + PracticeResultBO.ACCEPTED_MAX; } else if ( pValue.intValue() == PracticeResultBO.EXCELLENT ) { result = getAlias() + ".value = " + PracticeResultBO.EXCELLENT; } return result; } /** * @param pValueMin la valeur min de l'intervalle * @param pValueMax la valeur max de l'intervalle * @return le crit�re de recherche pour l'intervalle pour la clause where */ private String whereValueClause( double pValueMin, double pValueMax ) { // Si il n'y a pas de statut associ� � l'index, le composant est non not� (-->value=-1) String result = getAlias() + ".value = " + -1; if ( pValueMin >= 0 ) { result = getAlias() + ".value >= " + pValueMin; // On ne prend la borne sup�rieure de l'intervalle que si c'est 3 if ( pValueMax != PracticeResultBO.EXCELLENT ) { result += " AND " + getAlias() + ".value < " + pValueMax; } else { result += " AND " + getAlias() + ".value <= " + pValueMax; } } return result; } /** * Obtention de toutes les notes sur un composant et un audit * * @param pSession session * @param pComponentID composant * @param pAuditID audit * @return notes associ�es * @throws JrafDaoException si erreur */ public Collection findWhere( ISession pSession, Long pComponentID, Long pAuditID ) throws JrafDaoException { String whereClause = "where "; whereClause += getAlias() + ".component.id = '" + pComponentID + "'"; whereClause += " and "; whereClause += getAlias() + ".practice.audit.id = '" + pAuditID + "'"; MarkBO mark = null; Collection col = findWhere( pSession, whereClause ); if ( col.size() >= 1 ) { mark = (MarkBO) col.iterator().next(); if ( col.size() > 1 ) { String tab[] = { pAuditID.toString(), pComponentID.toString(), "" }; LOG.warn( DAOMessages.getString( "mark.many.audit_component_tre", tab ) ); } } return col; } /** * @param pSession session * @param pAuditId l'id de l'audit * @param pPreviousId l'id de l'audit pr�c�dent * @return le nombre de corrections correspondant au nombre de composants qui �taient � z�ro et qui ne le sont plus. * @throws JrafDaoException si erreur */ public int findCorrectionsWithProgessions( ISession pSession, Long pAuditId, Long pPreviousId ) throws JrafDaoException { String requete = "select count(m1.id) from MarkBO as m1, MarkBO as m2"; String whereClause = " where "; whereClause += "(m1.practice.audit.id = '" + pPreviousId + "' and m1.value=0)"; whereClause += " and "; whereClause += "(m2.practice.audit.id = '" + pAuditId + "' and m2.value>0)"; whereClause += " and "; whereClause += "m1.component.id=m2.component.id"; whereClause += " and "; whereClause += "m1.practice.rule.id=m2.practice.rule.id"; LOG.debug( "requete : " + requete + whereClause ); List result = find( pSession, requete + whereClause ); return ( (Integer) result.get( 0 ) ).intValue(); } /** * @param pSession la session * @param pAuditId l'id de l'audit * @param pPreviousId l'id de l'audit pr�c�dent * @return le nombre de corrections correspondant au nombre de composants qui avaient une note � 0 et qui n'existent * plus. * @throws JrafDaoException si erreur */ public int findCorrectionsWithSuppressions( ISession pSession, Long pAuditId, Long pPreviousId ) throws JrafDaoException { String requete = "select count(m1.component.id) from MarkBO as m1"; requete += " where "; requete += "(m1.practice.audit.id=" + pPreviousId + " and m1.value=0)"; requete += " and "; requete += "(m1.component.id not in "; requete += "(select m2.component.id from MarkBO as m2"; requete += " where "; requete += " m1.practice.rule.id=m2.practice.rule.id "; requete += " and "; requete += "m2.practice.audit.id=" + pAuditId + "))"; LOG.debug( "requete : " + requete ); List result = find( pSession, requete ); return ( (Integer) result.get( 0 ) ).intValue(); } /** * Donne la requ�te qui donne la liste des notes sur les nouveaux composants. NB : Cette m�thode sert aussi � * retouver les composants supprim�s (on inverse les ids des audits) * * @param pSession la session * @param pAuditId l'audit courant * @param pPreviousId l'audit de comparaison * @param pProjectId l'id du projet * @return la requ�te * @throws JrafDaoException si erreur */ private String getDeletedOrNewComponentsWhereClause( ISession pSession, Long pAuditId, Long pPreviousId, Long pProjectId ) throws JrafDaoException { String whereClause = "where "; whereClause += getAlias() + ".practice.project.id = '" + pProjectId + "'"; whereClause += " and "; whereClause += getAlias() + ".practice.audit.id = '" + pPreviousId + "'"; whereClause += " and " + getAlias() + ".component.id not in (" + getComponentIdsWhere( pSession, pProjectId, pAuditId ) + ")"; return whereClause; } /** * @param pSession la session * @param pProjectId l'id du projet * @param pAuditId l'id de l'audit * @return la requ�te r�cup�rant les ids des composants du projet d'id <code>pProjectId</code> not�s lors de l'audit * d'id <code>pAuditId</code> * @throws JrafDaoException si erreur */ private String getComponentIdsWhere( ISession pSession, Long pProjectId, Long pAuditId ) throws JrafDaoException { String select = "select m.component.id from MarkBO as m where "; select += "m.practice.project.id = '" + pProjectId + "'"; select += " and "; select += "m.practice.audit.id = '" + pAuditId + "'"; return select; } /** * Donne la liste des notes sur les nouveaux composants. NB : Cette m�thode sert aussi � retouver les composants * supprim�s (on inverse les ids des audits) * * @param pSession la session * @param pAuditId l'audit courant * @param pPreviousId l'audit de comparaison * @param pProjectId l'id du projet * @param pFilter le filtre * @param pLimit le nombre de r�sultats � remonter * @return la liste des nouveaux composants entre <code>pAuditId</code> et <code>pPreviousId</code> * @throws JrafDaoException si erreur */ public Collection findDeletedComponents( ISession pSession, Long pAuditId, Long pPreviousId, Long pProjectId, Object[] pFilter, int pLimit ) throws JrafDaoException { String whereClause = getDeletedOrNewComponentsWhereClause( pSession, pAuditId, pPreviousId, pProjectId ); if ( null != pFilter[PracticeEvolutionDTO.ONLY_PRACTICES_ID] ) { String[] practices = (String[]) pFilter[PracticeEvolutionDTO.ONLY_PRACTICES_ID]; // On r�cup�re que les notes des pratiques qui sont dans pPractices int nbPractices = practices.length; if ( nbPractices > 0 ) { // s�curit� pour le code car aucun int�r�t si il n'y a pas de pratique. whereClause += " and " + getAlias() + ".practice.rule.name in "; whereClause += getPracticesInClause( practices ); } } if ( null != pFilter[PracticeEvolutionDTO.THRESHOLD_ID] ) { String[] thresholdFilter = (String[]) pFilter[PracticeEvolutionDTO.THRESHOLD_ID]; // On convertit le seuil en int final float maxMark = 3; float limit; try { limit = Float.parseFloat( thresholdFilter[1] ); } catch ( NumberFormatException nfe ) { // l'utilisateur a donn� une mauvais seuil // on met la seuil max limit = maxMark; } whereClause += " and "; whereClause += getAlias() + ".value " + thresholdFilter[0] + " " + limit; } // On ordonne par type et nom de composant whereClause += " order by " + getAlias() + ".component.class, " + getAlias() + ".component.name asc"; LOG.debug( whereClause ); return (Collection) findWhereScrollable( pSession, whereClause, pLimit, 0, false ); } /** * @param pPractices les pratiques * @return les pratiques s�par�es par des virgules pour une clause in */ private String getPracticesInClause( String[] pPractices ) { String inClause = "("; int limit = pPractices.length - 1; for ( int i = 0; i < limit; i++ ) { inClause += "'" + pPractices[i] + "', "; } inClause += "'" + pPractices[limit] + "')"; return inClause; } /** * @param pSession la session * @param pAuditId l'id de l'audit de r�f�rence * @param pPreviousId l'id de l'audit de comparaison * @param pProjectId l'id du projet * @param pFilter le filtre * @param pLimit le nombre de r�sultats � remonter * @return une liste de tableau � deux �l�ments de MarkBO repr�sentant toutes les notes qui sont diff�rentes entre * les deux audits pour un m�me composant une m�me r�gle. * @throws JrafDaoException si erreur */ public Collection findChangedComponentWhere( ISession pSession, Long pAuditId, Long pPreviousId, Long pProjectId, Object[] pFilter, int pLimit ) throws JrafDaoException { String query = getEvolutionQuery( pAuditId, pPreviousId, pProjectId ); query += " and "; query += "m1.value != m2.value"; // On filtre if ( null != pFilter[PracticeEvolutionDTO.ONLY_UP_OR_DOWN_ID] ) { if ( ( (String) pFilter[PracticeEvolutionDTO.ONLY_UP_OR_DOWN_ID] ).equals( PracticeEvolutionDTO.ONLY_UP ) ) { query += " and "; // On r�cup�re les composants dont la note s'est am�lior�e ou si le composant // n'est plus not� query += "(m1.value > m2.value or (m1.value = " + MarkBO.NOT_NOTED_VALUE + " and m2.value != " + MarkBO.NOT_NOTED_VALUE + "))"; } else { query += " and "; // On r�cup�re les composants dont la note s'est d�grad�e (si le composant // n'est plus not� il s'agit d'une am�lioration) query += "((m1.value < m2.value or m2.value = " + MarkBO.NOT_NOTED_VALUE + ") and m1.value != " + MarkBO.NOT_NOTED_VALUE + ")"; } } if ( null != pFilter[PracticeEvolutionDTO.ONLY_PRACTICES_ID] ) { String[] practices = (String[]) pFilter[PracticeEvolutionDTO.ONLY_PRACTICES_ID]; // On r�cup�re que les notes des pratiques qui sont dans pPractices int nbPractices = practices.length; if ( nbPractices > 0 ) { // s�curit� pour le code car aucun int�r�t si il n'y a pas de pratique. query += " and m1.practice.rule.name in "; query += getPracticesInClause( practices ); } } // On ordonne par type et nom de composant; on limite le nombre de r�sultat // On r�cup�re la bonne string en fonction de la base de donn�e utilis�e query += " order by m1.component.class, m1.component.name asc "; LOG.debug( query ); return (List) findScrollable( pSession, query, pLimit, 0 ); } /** * @param pAuditId l'id de l'audit de r�f�rence * @param pPreviousId l'id de l'audit de comparaison * @param pProjectId l'id du projet * @return le d�but de la requ�te pour trouver les �volutions */ private String getEvolutionQuery( Long pAuditId, Long pPreviousId, Long pProjectId ) { String query = "select m1.component, m1.practice, m1.value, m2.value from MarkBO as m1, MarkBO as m2 "; String whereClause = "where "; whereClause += "m1.practice.project.id = '" + pProjectId + "'"; whereClause += " and "; whereClause += "m1.practice.audit.id = '" + pAuditId + "'"; whereClause += " and "; whereClause += "m1.component.id = m2.component.id"; whereClause += " and "; whereClause += "m1.practice.rule.id = m2.practice.rule.id"; whereClause += " and "; whereClause += "m2.practice.audit.id = '" + pPreviousId + "'"; return query + whereClause; } /** * Retrouve les <code>pMax</code> plus mauvaises notes (inf�rieur � <code>pMark</code>+1)qui ont pour id d'audit * <code>pAuditId</code> pour la pratique d'id <code>pPracticeId</code> et dont le composant n'est pas exclu du plan * d'action. * * @param pSession session Hibernate * @param pPracticeId l'id de la pratique * @param pMark la note de la pratique * @param pMax Nombre maximum de composants retourn� * @return les notes associ�es * @throws JrafDaoException exception DAO */ public Collection findWorstWhere( ISession pSession, Long pPracticeId, float pMark, Integer pMax ) throws JrafDaoException { String whereClause = getWorstWhereClause( pPracticeId, pMark ); // On ordonne par note whereClause += " order by " + getAlias() + ".value asc"; Collection ret = (Collection) findWhereScrollable( pSession, whereClause, pMax.intValue(), 0, false ); return ret; } /** * Compte les plus mauvaises notes (inf�rieur � <code>pMark</code>+1)qui ont pour id d'audit <code>pAuditId</code> * pour la pratique d'id <code>pPracticeId</code> et dont le composant n'est pas exclu du plan d'action. * * @param pSession session Hibernate * @param pPracticeId l'id de la pratique * @param pMark la note de la pratique * @return le nombre des plus mauvais composants pour cette pratique * @throws JrafDaoException exception DAO */ public int countWorstWhere( ISession pSession, Long pPracticeId, float pMark ) throws JrafDaoException { String whereClause = getWorstWhereClause( pPracticeId, pMark ); return countWhere( pSession, whereClause ).intValue(); } /** * @param pPracticeId l'id de la pratique * @param pMark la note de la pratique * @return la clause where pour r�cup�rer les plus mauvais composants */ private String getWorstWhereClause( Long pPracticeId, float pMark ) { String whereClause = "where "; whereClause += getAlias() + ".practice.id=" + pPracticeId; // On ne prend pas en compte les composants non not�s whereClause += " and "; whereClause += getAlias() + ".value!=" + MarkBO.NOT_NOTED_VALUE; // ni les composants exclus (0=false, 1=true) whereClause += " and "; whereClause += getAlias() + ".component.excludedFromActionPlan = 0"; // Condition sur la note whereClause += " and " + getAlias() + ".value < " + pMark + 1; return whereClause; } /** * This method is specific for the remediation by critcality feature. This method retrieves all the practices * involved in the audit given in argument for the components which belong to the module given in argument and are * not "excluded from the action plan". This method return a list of arrays. Each array contains : * <ul> * <li>0 - The component linked to the practice ({@link AbstractComponentBO})</li> * <li>1 - The practice id (Long)</li> * <li>2 - The practice name (String)</li> * <li>3 - The practice criticality (Integer)</li> * <li>4 - The practice mark (Float)</li> * </ul> * * @param session The hiberntae session * @param auditId The audit id * @param moduleId The module id * @return a list of arrays * @throws JrafDaoException exception occurs during the search */ @SuppressWarnings( "unchecked" ) public List<Object[]> getByAudit( ISession session, Long auditId, long moduleId ) throws JrafDaoException { List<Object[]> result = new ArrayList<Object[]>(); StringBuffer request = new StringBuffer( "select component, rule.id, rule.name, rule.criticality, rule.effort, mark.value " ); request.append( "from AbstractComponentBO as component, QualityRuleBO as rule, MarkBO as mark " ); request.append( "where component = mark.component " ); request.append( "and rule = mark.practice.rule " ); request.append( "and mark.practice.audit.id = " ); request.append( auditId ); request.append( "and mark.component.project.id = " ); request.append( moduleId ); request.append( "and component.excludedFromActionPlan = false" ); request.append( " order by mark.component.id" ); result = find( session, request.toString() ); return result; } }