/**
* 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.squalix.tools.ruleschecking;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.squale.squalecommon.enterpriselayer.businessobject.result.IntegerMetricBO;
import org.squale.squalecommon.enterpriselayer.businessobject.result.rulechecking.CheckstyleTransgressionBO;
import org.squale.squalecommon.enterpriselayer.businessobject.result.rulechecking.RuleCheckingTransgressionBO;
import org.squale.squalecommon.enterpriselayer.businessobject.result.rulechecking.RuleCheckingTransgressionItemBO;
import org.squale.squalecommon.enterpriselayer.businessobject.rulechecking.checkstyle.CheckstyleModuleBO;
import org.squale.squalecommon.enterpriselayer.businessobject.rulechecking.checkstyle.CheckstyleRuleBO;
import org.squale.squalecommon.enterpriselayer.businessobject.rulechecking.checkstyle.CheckstyleRuleSetBO;
import com.puppycrawl.tools.checkstyle.api.SeverityLevel;
/**
* Persistance des r�sultats g�n�r�s par CheckStyle
*/
public class CheckStylePersistor
implements ReportHandler
{
/** Logger */
private static final Log LOGGER = LogFactory.getLog( CheckStylePersistor.class );
/** Transgression */
private CheckstyleTransgressionBO mTransgression;
/** RuleSet */
private CheckstyleRuleSetBO mRuleSet;
/** Liste des codes avec leur nombre d'occurence */
private HashMap mCode;
/** La liste des modules */
private HashSet mModules;
/** La map contenant toutes les r�gles */
private Map mRules;
/**
* Constructeur
*
* @param pRuleSet jeu de r�gles
*/
public CheckStylePersistor( CheckstyleRuleSetBO pRuleSet )
{
mRuleSet = pRuleSet;
mRules = pRuleSet.getRules();
// Cr�ation de la transgression
mTransgression = new CheckstyleTransgressionBO();
mTransgression.setRuleSet( pRuleSet );
Collection col = mRules.values();
Iterator it = col.iterator();
// Parcours des r�gles pour stocker dans une map le nombre de violations
// On utilise une autre Map pour y stocker les modules
mCode = new HashMap();
mModules = new HashSet();
while ( it.hasNext() )
{
CheckstyleRuleBO rule = (CheckstyleRuleBO) it.next();
mCode.put( rule.getCode(), new IntegerWrapper() );
mModules.addAll( rule.getModules() );
}
}
/**
* Fabrication de la transgression Les donn�es collect�es pendant l'analyse du rapport checkstyle sont plac�es dans
* la transgression
*
* @return transgression
*/
public CheckstyleTransgressionBO computeTransgression()
{
Collection col = mCode.keySet();
Iterator it = col.iterator();
while ( it.hasNext() )
{
String code = (String) it.next();
IntegerWrapper nbOccur = (IntegerWrapper) mCode.get( code );
IntegerMetricBO metric = new IntegerMetricBO();
metric.setName( code );
metric.setValue( nbOccur.getValue() );
metric.setMeasure( mTransgression );
mTransgression.putMetric( metric );
}
return mTransgression;
}
/**
* {@inheritDoc}
*
* @see org.squale.squalix.tools.ruleschecking.ReportHandler#processError(java.lang.String, java.lang.String,
* java.lang.String, java.lang.String, java.lang.String, java.lang.String)
*/
public void processError( String pFileName, String pLine, String pColumn, String pSeverity, String pMessage,
String pSource )
{
final int MAX_LENGTH = 3000;
if ( !SeverityLevel.IGNORE.getName().equals( pSeverity ) )
{
// recup�re le code de l'erreur
CheckstyleRuleBO rule = getRuleForModule( pSource, pMessage );
if ( rule != null )
{
IntegerWrapper nbOccur = (IntegerWrapper) mCode.get( rule.getCode() );
nbOccur.increment();
// Les messages trop longs bloquent le Commit, ils sont donc tronqu�s
StringBuffer detail = new StringBuffer();
detail.append( RulesCheckingMessages.getString( "transgression.detail", new Object[] {
RuleCheckingTransgressionItemBO.PATH_KEY, RuleCheckingTransgressionItemBO.LINE_KEY, pColumn,
pMessage } ) );
if ( detail.length() > MAX_LENGTH )
{
detail.setLength( MAX_LENGTH - 1 );
}
// Ajout du d�tail de la transgression
RuleCheckingTransgressionItemBO item = new RuleCheckingTransgressionItemBO();
item.setMessage( detail.toString() );
item.setRule( rule );
item.setComponentFile( pFileName );
item.setLine( Integer.parseInt( pLine ) );
// On ajoute l'item seulement si son nombre d'occurences <= 100
if ( nbOccur.mValue <= RuleCheckingTransgressionBO.MAX_DETAILS )
{
mTransgression.getDetails().add( item );
}
}
}
}
/**
* Determine le nom du code associ� � l'erreur
*
* @param pModule le nom du module(rule)
* @param pMessage message de l'erreur
* @return la r�gle associ�e au module
*/
private CheckstyleRuleBO getRuleForModule( String pModule, String pMessage )
{
CheckstyleRuleBO result = null;
Set modules = getCorrespondingModules( pModule );
CheckstyleModuleBO module = null;
if ( modules.size() > 0 )
{
if ( modules.size() > 1 )
{ // cas de plusieurs modules avec
module = raiseAmbiguity( modules, pMessage );
if ( module != null )
{
result = (CheckstyleRuleBO) module.getRule();
}
else
{
LOGGER.error( RulesCheckingMessages.getString( "exception.rulesChecking.module.notfound",
new Object[] { pModule, pMessage } ) );
}
}
else
{
Iterator it = modules.iterator();
module = (CheckstyleModuleBO) it.next();
result = (CheckstyleRuleBO) module.getRule();
}
}
return result;
}
/**
* Trouve les modules du r�f�rentiel ayant le m�me nom que le nom de la transgression renvoy�e par checkstyle
*
* @param pModule nom de la transgression renvoy�e par Checkstyle
* @return une liste de modules du r�f�rentiel
*/
private Set getCorrespondingModules( String pModule )
{
HashSet modules = new HashSet();
CheckstyleModuleBO module = null;
Iterator it = mModules.iterator();
while ( it.hasNext() )
{
module = (CheckstyleModuleBO) it.next();
if ( pModule.equals( module.getName() ) )
{
modules.add( module );
}
}
return modules;
}
/**
* L�ve l'ambig�it� pour une trangression
*
* @param pModules Liste des modules du r�f�rentiel
* @param pMessage Le message de la transgression donn� par checkstyle
* @return Le module correspondant au message
*/
private CheckstyleModuleBO raiseAmbiguity( Set pModules, String pMessage )
{
boolean status = true;
CheckstyleModuleBO module = null;
CheckstyleModuleBO bufferModule = null;
Iterator it = pModules.iterator();
while ( status && it.hasNext() )
{
bufferModule = (CheckstyleModuleBO) it.next();
if ( bufferModule.getMessage().matches( pMessage ) )
{
module = bufferModule;
status = false;
}
}
return module;
}
/**
* Encapsulation d'un entier
*/
static class IntegerWrapper
{
/** Valeur */
private int mValue = 0;
/**
* @return valeur
*/
public int getValue()
{
return mValue;
}
/**
* Incr�ment
*/
public void increment()
{
mValue++;
}
}
}