BeanUtil.java

  1. /*
  2.  * Copyright (c) 2002-2022, City of Paris
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  *  1. Redistributions of source code must retain the above copyright notice
  10.  *     and the following disclaimer.
  11.  *
  12.  *  2. Redistributions in binary form must reproduce the above copyright notice
  13.  *     and the following disclaimer in the documentation and/or other materials
  14.  *     provided with the distribution.
  15.  *
  16.  *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
  17.  *     contributors may be used to endorse or promote products derived from
  18.  *     this software without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  24.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30.  * POSSIBILITY OF SUCH DAMAGE.
  31.  *
  32.  * License 1.0
  33.  */
  34. package fr.paris.lutece.util.bean;

  35. import fr.paris.lutece.portal.service.i18n.I18nService;
  36. import fr.paris.lutece.portal.service.util.AppException;
  37. import fr.paris.lutece.portal.service.util.AppLogService;
  38. import fr.paris.lutece.util.date.DateUtil;

  39. import org.apache.commons.beanutils.BeanUtilsBean;
  40. import org.apache.commons.beanutils.PropertyUtils;
  41. import org.apache.commons.beanutils.SuppressPropertiesBeanIntrospector;
  42. import org.apache.commons.beanutils.converters.DateConverter;
  43. import org.apache.commons.beanutils.converters.SqlTimeConverter;

  44. import java.lang.reflect.Field;
  45. import java.lang.reflect.InvocationTargetException;

  46. import java.sql.Date;
  47. import java.sql.Timestamp;
  48. import java.util.HashMap;
  49. import java.util.Locale;
  50. import java.util.Map;
  51. import java.util.Map.Entry;

  52. import javax.servlet.http.HttpServletRequest;

  53. /**
  54.  * Bean Utils
  55.  */
  56. public final class BeanUtil
  57. {
  58.     private static final char UNDERSCORE = '_';

  59.     static
  60.     {
  61.         PropertyUtils.addBeanIntrospector( SuppressPropertiesBeanIntrospector.SUPPRESS_CLASS );
  62.     }

  63.     private static Map<String, BeanUtilsBean> _mapBeanUtilsBeans;

  64.     /**
  65.      * BeanUtil initialization, considering Lutèce availables locales and date format properties
  66.      */
  67.     public static void init( )
  68.     {
  69.         _mapBeanUtilsBeans = new HashMap<>( );

  70.         for ( Locale locale : I18nService.getAdminAvailableLocales( ) )
  71.         {
  72.             BeanUtilsBean beanUtilsBean = new BeanUtilsBean( );
  73.             beanUtilsBean.getPropertyUtils( ).addBeanIntrospector( SuppressPropertiesBeanIntrospector.SUPPRESS_CLASS );

  74.             DateConverter dateConverter = new DateConverter( null );
  75.             dateConverter.setPatterns( new String[] { DateUtil.ISO_PATTERN_DATE, I18nService.getDateFormatShortPattern( locale ) } );
  76.             beanUtilsBean.getConvertUtils( ).register( dateConverter, Date.class );

  77.             SqlTimeConverter sqlTimeConverter = new SqlTimeConverter( null );
  78.             beanUtilsBean.getConvertUtils( ).register( sqlTimeConverter, Timestamp.class );

  79.             _mapBeanUtilsBeans.put( locale.getLanguage( ), beanUtilsBean );
  80.         }
  81.     }

  82.     /** Private constructor */
  83.     private BeanUtil( )
  84.     {
  85.     }

  86.     /**
  87.      * Populate a bean using parameters in http request
  88.      *
  89.      * @param bean
  90.      * @param request
  91.      */
  92.     public static void populate( Object bean, HttpServletRequest request )
  93.     {
  94.         populate( bean, request, null );
  95.     }

  96.     /**
  97.      * Populate a bean using parameters in http request, with locale date format controls
  98.      *
  99.      * @param bean
  100.      *            bean to populate
  101.      * @param request
  102.      *            http request
  103.      * @param locale
  104.      */
  105.     public static void populate( Object bean, HttpServletRequest request, Locale locale )
  106.     {
  107.         for ( Field field : bean.getClass( ).getDeclaredFields( ) )
  108.         {
  109.             try
  110.             {
  111.                 // for all boolean field, init to false
  112.                 if ( Boolean.class.isAssignableFrom( field.getType( ) ) || boolean.class.isAssignableFrom( field.getType( ) ) )
  113.                 {
  114.                     field.setAccessible( true );
  115.                     field.set( bean, false );
  116.                 }
  117.             }
  118.             catch( Exception e )
  119.             {
  120.                 String error = "La valeur du champ " + field.getName( ) + " de la classe " + bean.getClass( ).getName( ) + " n'a pas pu être récupéré ";
  121.                 AppLogService.error( error, e );
  122.                 throw new AppException( error, e );
  123.             }
  124.         }

  125.         try
  126.         {
  127.             BeanUtilsBean beanUtilsBean;
  128.             if ( locale != null && _mapBeanUtilsBeans != null )
  129.             {
  130.                 beanUtilsBean = _mapBeanUtilsBeans.get( locale.getLanguage( ) );
  131.             }
  132.             else
  133.             {
  134.                 beanUtilsBean = BeanUtilsBean.getInstance( );
  135.             }

  136.             beanUtilsBean.populate( bean, convertMap( request.getParameterMap( ) ) );
  137.         }
  138.         catch( InvocationTargetException | IllegalAccessException e )
  139.         {
  140.             AppLogService.error( "Unable to fetch data from request", e );
  141.         }
  142.     }

  143.     /**
  144.      * Convert map by casifying parameters names.
  145.      *
  146.      * @param mapInput
  147.      *            The input map
  148.      * @return The output map
  149.      */
  150.     public static Map<String, Object> convertMap( Map<String, String [ ]> mapInput )
  151.     {
  152.         Map<String, Object> mapOutput = new HashMap<>( );

  153.         for ( Entry<String, String [ ]> entry : mapInput.entrySet( ) )
  154.         {
  155.             mapOutput.put( convertUnderscores( entry.getKey( ) ), entry.getValue( ) );
  156.         }

  157.         return mapOutput;
  158.     }

  159.     /**
  160.      * Remove underscore and set the next letter in caps
  161.      *
  162.      * @param strSource
  163.      *            The source
  164.      * @return The converted string
  165.      */
  166.     public static String convertUnderscores( String strSource )
  167.     {
  168.         StringBuilder sb = new StringBuilder( );
  169.         boolean bCapitalizeNext = false;

  170.         for ( char c : strSource.toCharArray( ) )
  171.         {
  172.             if ( c == UNDERSCORE )
  173.             {
  174.                 bCapitalizeNext = true;
  175.             }
  176.             else
  177.             {
  178.                 if ( bCapitalizeNext )
  179.                 {
  180.                     sb.append( Character.toUpperCase( c ) );
  181.                     bCapitalizeNext = false;
  182.                 }
  183.                 else
  184.                 {
  185.                     sb.append( c );
  186.                 }
  187.             }
  188.         }

  189.         return sb.toString( );
  190.     }
  191. }