AdminDashboardService.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.portal.service.dashboard.admin;

  35. import java.util.ArrayList;
  36. import java.util.Collections;
  37. import java.util.HashMap;
  38. import java.util.List;
  39. import java.util.Map;

  40. import javax.servlet.http.HttpServletRequest;

  41. import org.apache.commons.collections.CollectionUtils;

  42. import fr.paris.lutece.portal.business.dashboard.AdminDashboardFactory;
  43. import fr.paris.lutece.portal.business.dashboard.AdminDashboardFilter;
  44. import fr.paris.lutece.portal.business.dashboard.AdminDashboardHome;
  45. import fr.paris.lutece.portal.business.user.AdminUser;
  46. import fr.paris.lutece.portal.service.dashboard.DashboardComponentEntry;
  47. import fr.paris.lutece.portal.service.plugin.Plugin;
  48. import fr.paris.lutece.portal.service.util.AppLogService;
  49. import fr.paris.lutece.portal.service.util.AppPropertiesService;

  50. /**
  51.  *
  52.  * AdminDashboardService
  53.  *
  54.  */
  55. public final class AdminDashboardService
  56. {
  57.     /**
  58.      * admindashboard.columnCount
  59.      */
  60.     private static final String PROPERTY_COLUMN_COUNT = "admindashboard.columnCount";
  61.     private static final String ALL = "ALL";
  62.     private static final int CONSTANTE_FIRST_ORDER = 1;
  63.     private static final int CONSTANTE_DEFAULT_COLUMN_COUNT = 2;
  64.     private static AdminDashboardService _singleton = new AdminDashboardService( );

  65.     /**
  66.      * Private Constructor
  67.      */
  68.     private AdminDashboardService( )
  69.     {
  70.         // nothing
  71.     }

  72.     /**
  73.      * Return the unique instance
  74.      *
  75.      * @return The instance
  76.      */
  77.     public static AdminDashboardService getInstance( )
  78.     {
  79.         return _singleton;
  80.     }

  81.     /**
  82.      * Returns the column count, with {@link AdminDashboardService#PROPERTY_COLUMN_COUNT}. Default is
  83.      * {@link AdminDashboardService#CONSTANTE_DEFAULT_COLUMN_COUNT}
  84.      *
  85.      * @return the column count
  86.      */
  87.     public int getColumnCount( )
  88.     {
  89.         return AppPropertiesService.getPropertyInt( PROPERTY_COLUMN_COUNT, CONSTANTE_DEFAULT_COLUMN_COUNT );
  90.     }

  91.     /**
  92.      * All known dashboards as declared in SpringContext
  93.      *
  94.      * @return dashboards list
  95.      */
  96.     public List<IAdminDashboardComponent> getAllAdminDashboardComponents( )
  97.     {
  98.         return AdminDashboardFactory.getAllAdminDashboardComponents( );
  99.     }

  100.     /**
  101.      *
  102.      * @param nColumn
  103.      *            the column id
  104.      * @return all dashboards for this column
  105.      */
  106.     public List<IAdminDashboardComponent> getAdminDashboardComponents( int nColumn )
  107.     {
  108.         AdminDashboardFilter filter = new AdminDashboardFilter( );
  109.         filter.setFilterColumn( nColumn );

  110.         return AdminDashboardHome.findByFilter( filter );
  111.     }

  112.     /**
  113.      * Register a Dashboard Component
  114.      *
  115.      * @param entry
  116.      *            The DashboardComponent entry defined in the plugin's XML file
  117.      * @param plugin
  118.      *            The plugin
  119.      */
  120.     public void registerDashboardComponent( DashboardComponentEntry entry, Plugin plugin )
  121.     {
  122.         try
  123.         {
  124.             IAdminDashboardComponent dc = (IAdminDashboardComponent) Class.forName( entry.getComponentClass( ) ).newInstance( );

  125.             dc.setName( entry.getName( ) );
  126.             dc.setPlugin( plugin );

  127.             boolean bRegistered = AdminDashboardFactory.registerDashboardComponent( dc );

  128.             if ( bRegistered )
  129.             {
  130.                 AppLogService.info( "New Admin Dashboard Component registered : {}", entry.getName( ) );
  131.             }
  132.             else
  133.             {
  134.                 AppLogService.error( " Admin Dashboard Component not registered : {} : {}", entry.getName( ), entry.getComponentClass( ) );
  135.             }
  136.         }
  137.         catch( ClassNotFoundException | InstantiationException | IllegalAccessException e )
  138.         {
  139.             AppLogService.error( "Error registering an Admin DashboardComponent : {}", e.getMessage( ), e );
  140.         }
  141.     }

  142.     /**
  143.      * Moves the dashboard.
  144.      *
  145.      * @param dashboard
  146.      *            to move, with new values
  147.      * @param nOldColumn
  148.      *            previous column id
  149.      * @param nOldOrder
  150.      *            previous order
  151.      * @param bCreate
  152.      *            <code>true</code> if this is a new dashboard, <code>false</code> otherwise.
  153.      */
  154.     public void doMoveDashboard( IAdminDashboardComponent dashboard, int nOldColumn, int nOldOrder, boolean bCreate )
  155.     {
  156.         int nColumn = dashboard.getZone( );
  157.         int nOrder = dashboard.getOrder( );

  158.         // find the dashboard already with this order and column
  159.         AdminDashboardFilter filter = new AdminDashboardFilter( );
  160.         filter.setFilterColumn( nColumn );

  161.         List<IAdminDashboardComponent> listColumnDashboards = AdminDashboardHome.findByFilter( filter );

  162.         if ( CollectionUtils.isNotEmpty( listColumnDashboards ) )
  163.         {
  164.             if ( AppLogService.isDebugEnabled( ) )
  165.             {
  166.                 AppLogService.debug( "Reordering admin dashboard column " + dashboard.getZone( ) );
  167.             }

  168.             // sort by order
  169.             Collections.sort( listColumnDashboards );

  170.             int nMaxOrder = listColumnDashboards.get( listColumnDashboards.size( ) - 1 ).getOrder( );

  171.             if ( ( nOldColumn == 0 ) || ( nOldColumn != nColumn ) )
  172.             {
  173.                 // was not in this column before, put to the end
  174.                 dashboard.setOrder( nMaxOrder + 1 );
  175.             }
  176.             else
  177.             {
  178.                 updateDashboardComponents( dashboard, listColumnDashboards, nOldOrder );

  179.                 // dashboard are singletons, values are modified by getting it from database
  180.                 dashboard.setOrder( nOrder );
  181.                 dashboard.setZone( nColumn );
  182.             }
  183.         }
  184.         else
  185.         {
  186.             dashboard.setOrder( 1 );
  187.         }

  188.         if ( bCreate )
  189.         {
  190.             // create dashboard
  191.             AdminDashboardHome.create( dashboard );
  192.         }
  193.         else
  194.         {
  195.             // update dashboard
  196.             AdminDashboardHome.update( dashboard );
  197.         }
  198.     }

  199.     private void updateDashboardComponents( IAdminDashboardComponent dashboard, List<IAdminDashboardComponent> listColumnDashboards, int nOldOrder )
  200.     {
  201.         int nOrder = dashboard.getOrder( );
  202.         if ( nOrder < nOldOrder )
  203.         {
  204.             for ( IAdminDashboardComponent dc : listColumnDashboards )
  205.             {
  206.                 int nCurrentOrder = dc.getOrder( );

  207.                 if ( !dc.equals( dashboard ) && ( nCurrentOrder >= nOrder ) && ( nCurrentOrder < nOldOrder ) )
  208.                 {
  209.                     dc.setOrder( nCurrentOrder + 1 );
  210.                     AdminDashboardHome.update( dc );
  211.                 }
  212.             }
  213.         }
  214.         else
  215.             if ( nOrder > nOldOrder )
  216.             {
  217.                 for ( IAdminDashboardComponent dc : listColumnDashboards )
  218.                 {
  219.                     int nCurrentOrder = dc.getOrder( );

  220.                     if ( !dc.equals( dashboard ) && ( nCurrentOrder <= nOrder ) && ( nCurrentOrder > nOldOrder ) )
  221.                     {
  222.                         dc.setOrder( nCurrentOrder - 1 );
  223.                         AdminDashboardHome.update( dc );
  224.                     }
  225.                 }
  226.             }
  227.     }

  228.     /**
  229.      * Returns all dashboards with no column/order set
  230.      *
  231.      * @return all dashboards with no column/order set
  232.      */
  233.     public List<IAdminDashboardComponent> getNotSetDashboards( )
  234.     {
  235.         List<IAdminDashboardComponent> listDashboards = AdminDashboardHome.findAll( );
  236.         List<IAdminDashboardComponent> listSpringDashboards = getAllAdminDashboardComponents( );

  237.         List<IAdminDashboardComponent> listUnsetDashboards = new ArrayList<>( );

  238.         for ( IAdminDashboardComponent dashboard : listSpringDashboards )
  239.         {
  240.             if ( !listDashboards.contains( dashboard ) )
  241.             {
  242.                 listUnsetDashboards.add( dashboard );
  243.             }
  244.         }

  245.         return listUnsetDashboards;
  246.     }

  247.     /**
  248.      * Finds all dashboard with column and order set.
  249.      *
  250.      * @return a map where key is the column id, and value is the column's dashboard list.
  251.      */
  252.     public Map<String, List<IAdminDashboardComponent>> getAllSetDashboards( )
  253.     {
  254.         Map<String, List<IAdminDashboardComponent>> mapDashboardComponents = new HashMap<>( );

  255.         List<IAdminDashboardComponent> listDashboards = AdminDashboardHome.findAll( );

  256.         for ( IAdminDashboardComponent dashboard : listDashboards )
  257.         {
  258.             int nColumn = dashboard.getZone( );

  259.             String strColumn = Integer.toString( nColumn );

  260.             // find this column list
  261.             List<IAdminDashboardComponent> listDashboardsColumn = mapDashboardComponents.computeIfAbsent( strColumn, s -> new ArrayList<>( ) );

  262.             // add dashboard to the list
  263.             listDashboardsColumn.add( dashboard );
  264.         }

  265.         return mapDashboardComponents;
  266.     }

  267.     /**
  268.      * Gets Data from all components of the zone
  269.      *
  270.      * @param user
  271.      *            The user
  272.      * @param nColumn
  273.      *            The dasboard column
  274.      * @param request
  275.      *            HttpServletRequest
  276.      * @return Data of all components of the zone
  277.      */
  278.     public String getDashboardData( AdminUser user, int nColumn, HttpServletRequest request )
  279.     {
  280.         StringBuilder sbDashboardData = new StringBuilder( );

  281.         for ( IAdminDashboardComponent dc : getAdminDashboardComponents( nColumn ) )
  282.         {
  283.             boolean bRight = ( dc.getRight( ) == null ) || user.checkRight( dc.getRight( ) ) || dc.getRight( ).equalsIgnoreCase( ALL );

  284.             if ( dc.isEnabled( ) && bRight )
  285.             {
  286.                 sbDashboardData.append( dc.getDashboardData( user, request ) );
  287.             }
  288.         }

  289.         return sbDashboardData.toString( );
  290.     }

  291.     /**
  292.      * Reorders column's dashboard
  293.      *
  294.      * @param nColumn
  295.      *            the column to reorder
  296.      */
  297.     public void doReorderColumn( int nColumn )
  298.     {
  299.         int nOrder = CONSTANTE_FIRST_ORDER;

  300.         for ( IAdminDashboardComponent dc : getAdminDashboardComponents( nColumn ) )
  301.         {
  302.             dc.setOrder( nOrder++ );
  303.             AdminDashboardHome.update( dc );
  304.         }
  305.     }

  306.     /**
  307.      * Builds the map to with column id as key, and <code>true</code> as value if column is well ordered, <code>false</code> otherwise.
  308.      *
  309.      * @return the map
  310.      */
  311.     public Map<String, Boolean> getOrderedColumnsStatus( )
  312.     {
  313.         Map<String, Boolean> mapOrderedStatus = new HashMap<>( );
  314.         List<Integer> listColumns = AdminDashboardHome.findColumns( );

  315.         for ( Integer nIdColumn : listColumns )
  316.         {
  317.             mapOrderedStatus.put( nIdColumn.toString( ), isWellOrdered( nIdColumn ) );
  318.         }

  319.         return mapOrderedStatus;
  320.     }

  321.     /**
  322.      * Determines if the column is well ordered
  323.      *
  324.      * @param nColumn
  325.      *            the column id
  326.      * @return true if well ordered, <code>false</code> otherwise.
  327.      */
  328.     private boolean isWellOrdered( int nColumn )
  329.     {
  330.         int nOrder = CONSTANTE_FIRST_ORDER;

  331.         for ( IAdminDashboardComponent dc : getAdminDashboardComponents( nColumn ) )
  332.         {
  333.             if ( nOrder != dc.getOrder( ) )
  334.             {
  335.                 return false;
  336.             }

  337.             nOrder++;
  338.         }

  339.         return true;
  340.     }
  341. }