/**
* 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.squaleweb.util;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.squale.squalecommon.enterpriselayer.businessobject.component.AuditBO;
import org.squale.squalecommon.enterpriselayer.businessobject.result.ErrorBO;
import org.squale.squalecommon.enterpriselayer.businessobject.result.MarkBO;
import org.squale.squalecommon.util.ConstantRulesChecking;
import org.squale.squaleweb.resources.WebMessages;
/**
* Fournit des fonctionnalit�s utiles � plusieurs actions.
*
* @author M400842
*/
public class SqualeWebActionUtils
{
/**
* Logger
*/
private static Log log = LogFactory.getLog( SqualeWebActionUtils.class );
/**
* Images en fonction de la note 0..3
*/
public static final String[] IMG =
{ "images/pictos/bad.png", "images/pictos/good.png", "images/pictos/best.png",
"images/pictos/super.png", "images/pictos/na.gif" };
/**
* Constante "-" pour l'affichage
*/
public static final String DASH = "-";
/**
* d�fini une valeur de seuil significatif pour une variation de la tendance de constante � un peux mieux Tant que
* la variation de la note est en dessous de ce seuil, on consid�re qu'il n'y a pas eu d'�volution
*/
private final static float BETTER = 0.05f;
/**
* d�fini une valeur de seuil significatif pour une variation de la tendance de constante � beaucoup mieux
*/
private final static float MUCH_BETTER = 0.3f;
/**
* @param currentMark la note courante
* @param predecessorMark la note pr�c�dente
* @return l'image repr�sentant l'�volution entre currentMark et predecessorMark
*/
public static String getImageForTrend( String currentMark, String predecessorMark )
{
String result = "images/pictos/na.gif";
// Dans ce cas, c'est simple: il n'y a pas eu d'�volution
// la note pr�c�dente peut etre null ou initialis�e � la chaine vide (pour le form)
if ( isValidMark( currentMark ) && isValidMark( predecessorMark ) )
{
float diff =
Float.parseFloat( currentMark.replace( ',', '.' ) )
- Float.parseFloat( predecessorMark.replace( ',', '.' ) );
if ( Math.abs( diff ) < BETTER )
{
// l'�volution n'est pas significative, fl�che constante
result = "images/pictos/ar_blueAF.gif";
}
else if ( Math.abs( diff ) < MUCH_BETTER )
{
// changement peu significatif
if ( diff < 0 )
{ // l�g�re d�gradation
result = "images/pictos/ar_blueAF_RD.gif";
}
else
{ // l�g�re am�lioration
result = "images/pictos/ar_blueAF_RU.gif";
}
}
else
{
if ( diff < 0 )
{ // d�gradation significative
result = "images/pictos/ar_blueAF_D.gif";
}
else
{ // am�lioration significative
result = "images/pictos/ar_blueAF_U.gif";
}
}
}
return result;
}
/**
* Affiche l'image.
*
* @param pNote la note.
* @param pRequest la requ�te
* @return le chemin de l'image
*/
public static String generatePictoWithTooltip( String pNote, HttpServletRequest pRequest )
{
// On r�cup�re l'index en fonction de la note tronqu�e.
int imgIndex = generatePicto( pNote );
String pictureHelp = WebMessages.getString( pRequest, "project.results.mark.status_" + imgIndex );
if ( imgIndex != IMG.length - 1 )
{
int imgIndexRound = Integer.parseInt( formatFloat( pNote ).substring( 0, 1 ) );
if ( imgIndexRound > imgIndex )
{
pictureHelp +=
" (" + WebMessages.getString( pRequest, "project.results.mark.nearly.status_" + imgIndexRound )
+ ")";
}
}
// on remplace ' par \' pour le javascript
return "<img src=\"" + IMG[imgIndex] + "\"title=\"" + pictureHelp.replaceAll( "'", "\\\\'" )
+ "\" border=\"0\" />";
}
/**
* R�cup�re le pictogramme associ� � une note
*
* @param pNote la note.
* @return le chemin de l'image
*/
public static int generatePicto( String pNote )
{
// initialisation � l'image Na par d�faut
int i = IMG.length - 1;
// V�rification simpliste de la note pour �viter des exceptions
// lors de sa conversion
Float currentMark;
if ( isValidMark( pNote ) )
{
i = Integer.parseInt( truncFloat( pNote ).substring( 0, 1 ) );
i = ( i > IMG.length - 1 ? IMG.length - 1 : i );
}
return i;
}
/**
* @param aFloat la note sous forme de String � tronquer
* @return la note sous sa forme flottante en la tronquant � un chiffre apr�s la virgule
*/
private static String truncFloat( String aFloat )
{
final int toTrunc = 10;
String result = DASH;
float mark = stringToFloat( aFloat );
if ( mark != MarkBO.NOT_NOTED_VALUE )
{
// on tronque et garde que un chiffre apr�s la virgule.
mark = mark * toTrunc;
mark = (int) mark;
result = "" + mark / toTrunc;
}
return result;
}
/**
* @param pNote La note de 0 � 3 ou non valide (i.e vide (?))
* @return un boolean indiquant que la chaine est bien une note (non vide)
*/
public static boolean isValidMark( String pNote )
{
return pNote != null && pNote.length() > 0 && Character.isDigit( pNote.charAt( 0 ) );
}
/**
* @param aFloat le float � formatter
* @return le float arrondi � un chiffre apr�s la virgule ou "-" si la chaine ne peut pas etre correctement format�e
*/
public static String formatFloat( String aFloat )
{
String result = DASH;
float mark = stringToFloat( aFloat );
if ( mark != MarkBO.NOT_NOTED_VALUE )
{
// on ne garde que un chiffre apr�s la virgule.
result = formatFloat( mark );
}
return result;
}
/**
* @param aFloat la note sous forme de String
* @return la note sous sa forme flottante en l'arrondissant � un chiffre apr�s la virgule
*/
private static float stringToFloat( String aFloat )
{
float result = MarkBO.NOT_NOTED_VALUE;
if ( isValidMark( aFloat ) )
{
// Remplacement du "." par une ","
result = Float.parseFloat( aFloat.replace( ',', '.' ) );
}
return result;
}
/**
* Factorisation de code, aucun test n'est fait
*
* @param pFloat le float � formater
* @return la chaine associ�e au float
*/
private static String formatFloat( float pFloat )
{
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits( 1 );
nf.setMinimumFractionDigits( 1 );
String result = nf.format( pFloat );
return result;
}
/**
* @param aFloat le nombre � formatter
* @return le float formatt� en String avec un chiffre apr�s la virgule
*/
public static String formatFloat( Float aFloat )
{
String result = DASH;
if ( aFloat != null && aFloat.floatValue() != MarkBO.NOT_NOTED_VALUE )
{
result = formatFloat( aFloat.floatValue() );
}
return result;
}
/**
* Donne une valeur � un attribut de l'objet.<br>
* La classe de l'objet doit avoir le setter associ� au nom de l'attribut : setMonAttribut et doit prendre une
* String en param�tre.
*
* @param pObject l'objet � remplir.
* @param pSetterName le nom du setter de l'attribut.
* @param pValue la nouvelle valeur de l'attribut.
*/
public static void setValue( final Object pObject, final String pSetterName, final String pValue )
{
Class[] paramsType = { String.class };
try
{
// Obtention de la m�thode
Method setter = pObject.getClass().getMethod( pSetterName, paramsType );
Object[] params = { null };
// V�rification du type de cha�ne
// TODO voir si le test sur un nombre est pertinent - redondance entre la regexp et le parseInt
if ( null != pValue
&& ( ( pValue.matches( "-?[0-9]*" ) && Integer.parseInt( pValue ) != -1 ) || !pValue.matches( "-?[0-9]*" ) ) )
{
params[0] = pValue;
}
setter.invoke( pObject, params );
}
catch ( Exception e )
{
log.error( e, e );
}
}
/**
* Remplit le bean pass� en param�tre avec les valeurs donn�es.
*
* @param pBean le bean � remplir.
* @param pAttributes la liste ordonn�e des attributs (String).
* @param pValues la liste ordonn�e des valeurs (String).
* @param pMessages pr�cise si les nom des attributs sont des cl�s � r�soudre, ils sont alors suffix�s de
* ".attribute".
*/
public static void fullFillBean( final Object pBean, final List pAttributes, final List pValues,
final boolean pMessages )
{
String attributeName = null;
String setterName = null;
for ( int i = 0; null != pBean && i < pAttributes.size(); i++ )
{
if ( pMessages )
{
attributeName = WebMessages.getString( (String) pAttributes.get( i ) + ".attribute" );
}
else
{
attributeName = (String) pAttributes.get( i );
}
setterName = "set" + attributeName.substring( 0, 1 ).toUpperCase() + attributeName.substring( 1 );
setValue( pBean, setterName, (String) pValues.get( i ) );
}
}
/**
* Retourne une liste h�t�rog�ne sous la forme d'une liste de String.
*
* @param pList la liste � transformer.
* @return une liste de String.
*/
public static List getAsStringsList( final List pList )
{
LinkedList result = null;
if ( null != pList )
{
result = new LinkedList();
Iterator it = pList.iterator();
Object value = null;
// Parcours de la collection et conversion de chaque valeur
while ( it.hasNext() )
{
value = it.next();
if ( null != value )
{
// Conversion sp�cifique pour un nombre flottant
if ( value.getClass().equals( Float.class ) )
{
result.addLast( formatFloat( (Float) value ) );
}
else
{
result.addLast( value.toString() );
}
}
else
{
// On conserve la valeur null initiale
result.addLast( null );
}
}
}
return result;
}
/**
* Equivalent de la fonction sprintf du C.<br>
* Ne fonctionne que pour les %s, puisque les param�tres sont des String.
*
* @param pString la chaine � compl�ter.
* @param pValue la liste des valeurs � affecter.
* @return la cha�ne compl�t�e.
*/
public static String sprintf( final String pString, final String[] pValue )
{
String result = pString;
for ( int i = 0; i < pValue.length; i++ )
{
result.replaceFirst( "%s", pValue[i] );
}
return result;
}
/**
* Retourne une chaine formattant la date.
*
* @param pDate la date � formatter.
* @param lang langue d'affichage
* @return une chaine repr�santant le date.
*/
public static String getFormattedDate( Date pDate, Locale lang )
{
DateFormat df = DateFormat.getDateInstance( DateFormat.LONG, lang );
return df.format( pDate );
}
/**
* Retourne la date d'aujourd'hui selon le format d�fini par la cl�.
*
* @param lang langue d'affichage
* @param formatKey la cl� du fichier de properties d�finissant le format de la date
* @return une chaine repr�santant le date.
*/
public static String getTodayDate( Locale lang, String formatKey )
{
Calendar today = Calendar.getInstance();
return getFormattedDate( lang, today.getTime(), formatKey );
}
/**
* Retourne la date format�e selon le format d�fini par la cl�.
*
* @param lang langue d'affichage
* @param pDate la date � formater
* @param formatKey la cl� du fichier de properties d�finissant le format de la date
* @return une chaine repr�santant le date.
*/
public static String getFormattedDate( Locale lang, Date pDate, String formatKey )
{
SimpleDateFormat sdf = new SimpleDateFormat( WebMessages.getString( lang, formatKey ), lang );
return sdf.format( pDate );
}
/**
* Suffixe toutes les valeurs du tableau.
*
* @param pArray le tableau � transformer.
* @param pSuffix la suffixe � ajouter.
* @param pKey pr�cise si les valeurs suffix�s sont des cl�s, auquel cas elles sont remplac�es par les valeurs
* associ�es.
* @return un tableau de la m�me taille avec les valeurs suffix�s.
*/
public static String[] suffixString( final String[] pArray, final String pSuffix, boolean pKey )
{
String[] result = new String[pArray.length];
for ( int i = 0; i < pArray.length; i++ )
{
if ( pKey )
{
result[i] = WebMessages.getString( pArray[i] + pSuffix );
}
else
{
result[i] = pArray[i] + pSuffix;
}
}
return result;
}
/**
* Obtention de l'image associ�e � un niveau d'erreur
*
* @param pErrorLevel le niveau d'erreur
* @return image correspondante au niveau d'erreur
*/
public static String getImageForErrorLevel( String pErrorLevel )
{
String result;
if ( pErrorLevel.equals( ErrorBO.CRITICITY_FATAL ) )
{
result = "images/pictos/error.png";
}
else if ( pErrorLevel.equals( ErrorBO.CRITICITY_WARNING ) )
{
result = "images/pictos/warning.png";
}
else
{
result = "images/pictos/info.png";
}
return result;
}
/**
* Obtention de l'image associ�e � la s�v�rit� de la r�gle
*
* @param pSeverity la s�v�rit�
* @return image correspondante � la s�v�rit�
*/
public static String getImageForRuleSeverity( String pSeverity )
{
String result;
if ( pSeverity.equals( ConstantRulesChecking.ERROR_LABEL ) )
{
result = "images/pictos/error.png";
}
else if ( pSeverity.equals( ConstantRulesChecking.WARNING_LABEL ) )
{
result = "images/pictos/warning.png";
}
else
{
result = "images/pictos/info.png";
}
return result;
}
/**
* Retourne le contenu de pValues sans les valeurs vides.
*
* @param pValues la tableau des valeurs � nettoyer
* @return un tableau de String propre
*/
public static String[] cleanValues( final String[] pValues )
{
String[] result = null;
// Nettoyage des noms
ArrayList temp = new ArrayList();
for ( int i = 0; i < pValues.length; i++ )
{
if ( pValues[i].trim().length() > 0 )
{
temp.add( pValues[i] );
}
}
String[] type = new String[0];
result = (String[]) temp.toArray( type );
return result;
}
/**
* @param pRequest la requete http
* @return le formatter de nombre correspondant � la locale
*/
public static NumberFormat getNumberFormat( HttpServletRequest pRequest )
{
NumberFormat formatter = null;
try
{
// En anglais par d�faut
formatter = (DecimalFormat) DecimalFormat.getInstance();
// Si c'est en francais , on n'affiche pas les "," pour s�parer les chiffres
if ( pRequest.getLocale().getLanguage().equals( Locale.FRENCH.toString() ) )
{
( (DecimalFormat) formatter ).setGroupingUsed( false );
}
}
catch ( NumberFormatException nfe )
{
// en cas de probl�me rencontr�, on renvoie le formatter par d�faut
formatter = NumberFormat.getInstance();
}
return formatter;
}
/**
* @param pStrings la liste de String
* @param pSeparator le s�parateur
* @return la string repr�sentant le tableau dont les �lement sont s�par�s pas <code>separator</code>
*/
public static String formatArray( Collection pStrings, String pSeparator )
{
String result = "";
for ( Iterator it = pStrings.iterator(); it.hasNext(); )
{
result += (String) it.next();
if ( it.hasNext() )
{
result += pSeparator;
}
}
return result;
}
/**
* Permet d'aller � la ligne dans un menu pour pouvoir afficher le nom en entier au lieu qu'il soit tronqu� car la
* charte graphique impose une taille fixe
*
* @param pItem l'item a couper
* @return l'item avec des '\n' tous les n caract�res
*/
public static String formatStringForMenuItem( String pItem )
{
final int MAX_CHAR = 26; // Nombre de caract�res qu'on suppose affichable
StringBuffer result = new StringBuffer( pItem );
int nbInsertion = result.length() / MAX_CHAR;
for ( int i = 1; i <= nbInsertion; i++ )
{
result.insert( i * MAX_CHAR, "... " ); // On d�cale de 3 caract�res
}
return result.toString();
}
/**
* R�cup�re la cl� de configuration repr�sentant le nombre minimum d'applications que doit avoir le menu pour �tre
* group�
*
* @param request la requ�te
* @return le nombre minimum d'applications que doit avoir le menu pour �tre group� (10 par d�faut)
*/
public static int getApplicationMenuKey( HttpServletRequest request )
{
// On groupe les applications si on en a plus de 10 dans le menu
final int MIN_APPLIS = 10;
// On r�cup�re le nombre minimum d'applications que doit avoir le menu pour �tre group�
String minApplisForGrouping = WebMessages.getString( request, "nbApplisForGrouping" );
int minApplis;
try
{
minApplis = Integer.parseInt( minApplisForGrouping );
}
catch ( NumberFormatException nfe )
{
// Si erreur de cl�, on met le nombre par d�faut
minApplis = MIN_APPLIS;
}
return minApplis;
}
/**
* @param pRequest la requ�te
* @param pTres la liste des tres
* @return la l�gende pr�cisant la signification des tres
*/
public static String getLegendForTres( HttpServletRequest pRequest, List pTres )
{
String legend = "<ul>";
for ( int i = 0; i < pTres.size(); i++ )
{
String tre = (String) pTres.get( i );
String acronyme = tre;
int lastDot = tre.lastIndexOf( "." );
if ( lastDot > 0 )
{
acronyme = tre.substring( lastDot + 1 );
}
legend += "<li>" + acronyme + " = " + WebMessages.getString( pRequest, tre ) + "</li>";
}
return legend + "</ul>";
}
/**
* @param pStatus le statut de l'audit
* @return le type servant � la cl� repr�sentant le statut de l'audit.
*/
public static String getAuditKind( int pStatus )
{
// TODO : Il faudrait exploiter le statut de l'audit
// --> faire une passe sur la cl� "kind" pour la remplacer par
// un int et r�cup�rer la string par les fichiers de properties
String result = "terminated";
if ( pStatus == AuditBO.FAILED )
{
result = "failed";
}
else if ( pStatus == AuditBO.PARTIAL )
{
result = "partial";
}
return result;
}
}