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.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 fonctionnalits 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 = "-"; /** * dfini 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 considre qu'il n'y a pas eu d'volution */ private final static float BETTER = 0.05f; /** * dfini 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 prcdente * @return l'image reprsentant 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 prcdente peut etre null ou initialise 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, flche constante result = "images/pictos/ar_blueAF.gif"; } else if (Math.abs(diff) < MUCH_BETTER) { // changement peu significatif if (diff < 0) { // lgre dgradation result = "images/pictos/ar_blueAF_RD.gif"; } else { // lgre amlioration result = "images/pictos/ar_blueAF_RU.gif"; } } else { if (diff < 0) { // dgradation significative result = "images/pictos/ar_blueAF_D.gif"; } else { // amlioration significative result = "images/pictos/ar_blueAF_U.gif"; } } } return result; } /** * Affiche l'image. * * @param pNote la note. * @param pRequest la requte * @return le chemin de l'image */ public static String generatePictoWithTooltip(String pNote, HttpServletRequest pRequest) { // On rcupre l'index en fonction de la note tronque. 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\" />"; } /** * Rcupre 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 dfaut int i = IMG.length - 1; // Vrification 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 aprs 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 aprs 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 aprs la virgule ou "-" si la chaine ne peut pas etre correctement formate */ 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 aprs 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 aprs 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 associe 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 aprs 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 paramtre. * * @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 mthode Method setter = pObject.getClass().getMethod(pSetterName, paramsType); Object[] params = { null }; // Vrification du type de chane // 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 paramtre avec les valeurs donnes. * * @param pBean le bean remplir. * @param pAttributes la liste ordonne des attributs (String). * @param pValues la liste ordonne des valeurs (String). * @param pMessages prcise si les nom des attributs sont des cls rsoudre, ils sont alors suffixs 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 htrogne 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 spcifique 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 paramtres sont des String. * * @param pString la chaine complter. * @param pValue la liste des valeurs affecter. * @return la chane complte. */ 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 reprsantant 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 dfini par la cl. * * @param lang langue d'affichage * @param formatKey la cl du fichier de properties dfinissant le format de la date * @return une chaine reprsantant le date. */ public static String getTodayDate(Locale lang, String formatKey) { Calendar today = Calendar.getInstance(); return getFormattedDate(lang, today.getTime(), formatKey); } /** * Retourne la date formate selon le format dfini par la cl. * * @param lang langue d'affichage * @param pDate la date formater * @param formatKey la cl du fichier de properties dfinissant le format de la date * @return une chaine reprsantant 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 prcise si les valeurs suffixs sont des cls, auquel cas elles sont remplaces par les valeurs * associes. * @return un tableau de la mme taille avec les valeurs suffixs. */ 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 associe 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 associe la svrit de la rgle * * @param pSeverity la svrit * @return image correspondante la svrit */ 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 dfaut formatter = (DecimalFormat) DecimalFormat.getInstance(); // Si c'est en francais , on n'affiche pas les "," pour sparer les chiffres if (pRequest.getLocale().getLanguage().equals(Locale.FRENCH.toString())) { ((DecimalFormat) formatter).setGroupingUsed(false); } } catch (NumberFormatException nfe) { // en cas de problme rencontr, on renvoie le formatter par dfaut formatter = NumberFormat.getInstance(); } return formatter; } /** * @param pStrings la liste de String * @param pSeparator le sparateur * @return la string reprsentant le tableau dont les lement sont spars 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 caractres */ public static String formatStringForMenuItem(String pItem) { final int MAX_CHAR = 26; // Nombre de caractres 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 dcale de 3 caractres } return result.toString(); } /** * Rcupre la cl de configuration reprsentant le nombre minimum d'applications que doit avoir le menu pour tre * group * * @param request la requte * @return le nombre minimum d'applications que doit avoir le menu pour tre group (10 par dfaut) */ 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 rcupre 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 dfaut minApplis = MIN_APPLIS; } return minApplis; } /** * @param pRequest la requte * @param pTres la liste des tres * @return la lgende prcisant 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 reprsentant 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 rcuprer 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; } }