AdminDashboardService.java
/*
* Copyright (c) 2002-2022, City of Paris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice
* and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* License 1.0
*/
package fr.paris.lutece.portal.service.dashboard.admin;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.collections.CollectionUtils;
import fr.paris.lutece.portal.business.dashboard.AdminDashboardFactory;
import fr.paris.lutece.portal.business.dashboard.AdminDashboardFilter;
import fr.paris.lutece.portal.business.dashboard.AdminDashboardHome;
import fr.paris.lutece.portal.business.user.AdminUser;
import fr.paris.lutece.portal.service.dashboard.DashboardComponentEntry;
import fr.paris.lutece.portal.service.plugin.Plugin;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
/**
*
* AdminDashboardService
*
*/
public final class AdminDashboardService
{
/**
* admindashboard.columnCount
*/
private static final String PROPERTY_COLUMN_COUNT = "admindashboard.columnCount";
private static final String ALL = "ALL";
private static final int CONSTANTE_FIRST_ORDER = 1;
private static final int CONSTANTE_DEFAULT_COLUMN_COUNT = 2;
private static AdminDashboardService _singleton = new AdminDashboardService( );
/**
* Private Constructor
*/
private AdminDashboardService( )
{
// nothing
}
/**
* Return the unique instance
*
* @return The instance
*/
public static AdminDashboardService getInstance( )
{
return _singleton;
}
/**
* Returns the column count, with {@link AdminDashboardService#PROPERTY_COLUMN_COUNT}. Default is
* {@link AdminDashboardService#CONSTANTE_DEFAULT_COLUMN_COUNT}
*
* @return the column count
*/
public int getColumnCount( )
{
return AppPropertiesService.getPropertyInt( PROPERTY_COLUMN_COUNT, CONSTANTE_DEFAULT_COLUMN_COUNT );
}
/**
* All known dashboards as declared in SpringContext
*
* @return dashboards list
*/
public List<IAdminDashboardComponent> getAllAdminDashboardComponents( )
{
return AdminDashboardFactory.getAllAdminDashboardComponents( );
}
/**
*
* @param nColumn
* the column id
* @return all dashboards for this column
*/
public List<IAdminDashboardComponent> getAdminDashboardComponents( int nColumn )
{
AdminDashboardFilter filter = new AdminDashboardFilter( );
filter.setFilterColumn( nColumn );
return AdminDashboardHome.findByFilter( filter );
}
/**
* Register a Dashboard Component
*
* @param entry
* The DashboardComponent entry defined in the plugin's XML file
* @param plugin
* The plugin
*/
public void registerDashboardComponent( DashboardComponentEntry entry, Plugin plugin )
{
try
{
IAdminDashboardComponent dc = (IAdminDashboardComponent) Class.forName( entry.getComponentClass( ) ).newInstance( );
dc.setName( entry.getName( ) );
dc.setPlugin( plugin );
boolean bRegistered = AdminDashboardFactory.registerDashboardComponent( dc );
if ( bRegistered )
{
AppLogService.info( "New Admin Dashboard Component registered : {}", entry.getName( ) );
}
else
{
AppLogService.error( " Admin Dashboard Component not registered : {} : {}", entry.getName( ), entry.getComponentClass( ) );
}
}
catch( ClassNotFoundException | InstantiationException | IllegalAccessException e )
{
AppLogService.error( "Error registering an Admin DashboardComponent : {}", e.getMessage( ), e );
}
}
/**
* Moves the dashboard.
*
* @param dashboard
* to move, with new values
* @param nOldColumn
* previous column id
* @param nOldOrder
* previous order
* @param bCreate
* <code>true</code> if this is a new dashboard, <code>false</code> otherwise.
*/
public void doMoveDashboard( IAdminDashboardComponent dashboard, int nOldColumn, int nOldOrder, boolean bCreate )
{
int nColumn = dashboard.getZone( );
int nOrder = dashboard.getOrder( );
// find the dashboard already with this order and column
AdminDashboardFilter filter = new AdminDashboardFilter( );
filter.setFilterColumn( nColumn );
List<IAdminDashboardComponent> listColumnDashboards = AdminDashboardHome.findByFilter( filter );
if ( CollectionUtils.isNotEmpty( listColumnDashboards ) )
{
if ( AppLogService.isDebugEnabled( ) )
{
AppLogService.debug( "Reordering admin dashboard column " + dashboard.getZone( ) );
}
// sort by order
Collections.sort( listColumnDashboards );
int nMaxOrder = listColumnDashboards.get( listColumnDashboards.size( ) - 1 ).getOrder( );
if ( ( nOldColumn == 0 ) || ( nOldColumn != nColumn ) )
{
// was not in this column before, put to the end
dashboard.setOrder( nMaxOrder + 1 );
}
else
{
updateDashboardComponents( dashboard, listColumnDashboards, nOldOrder );
// dashboard are singletons, values are modified by getting it from database
dashboard.setOrder( nOrder );
dashboard.setZone( nColumn );
}
}
else
{
dashboard.setOrder( 1 );
}
if ( bCreate )
{
// create dashboard
AdminDashboardHome.create( dashboard );
}
else
{
// update dashboard
AdminDashboardHome.update( dashboard );
}
}
private void updateDashboardComponents( IAdminDashboardComponent dashboard, List<IAdminDashboardComponent> listColumnDashboards, int nOldOrder )
{
int nOrder = dashboard.getOrder( );
if ( nOrder < nOldOrder )
{
for ( IAdminDashboardComponent dc : listColumnDashboards )
{
int nCurrentOrder = dc.getOrder( );
if ( !dc.equals( dashboard ) && ( nCurrentOrder >= nOrder ) && ( nCurrentOrder < nOldOrder ) )
{
dc.setOrder( nCurrentOrder + 1 );
AdminDashboardHome.update( dc );
}
}
}
else
if ( nOrder > nOldOrder )
{
for ( IAdminDashboardComponent dc : listColumnDashboards )
{
int nCurrentOrder = dc.getOrder( );
if ( !dc.equals( dashboard ) && ( nCurrentOrder <= nOrder ) && ( nCurrentOrder > nOldOrder ) )
{
dc.setOrder( nCurrentOrder - 1 );
AdminDashboardHome.update( dc );
}
}
}
}
/**
* Returns all dashboards with no column/order set
*
* @return all dashboards with no column/order set
*/
public List<IAdminDashboardComponent> getNotSetDashboards( )
{
List<IAdminDashboardComponent> listDashboards = AdminDashboardHome.findAll( );
List<IAdminDashboardComponent> listSpringDashboards = getAllAdminDashboardComponents( );
List<IAdminDashboardComponent> listUnsetDashboards = new ArrayList<>( );
for ( IAdminDashboardComponent dashboard : listSpringDashboards )
{
if ( !listDashboards.contains( dashboard ) )
{
listUnsetDashboards.add( dashboard );
}
}
return listUnsetDashboards;
}
/**
* Finds all dashboard with column and order set.
*
* @return a map where key is the column id, and value is the column's dashboard list.
*/
public Map<String, List<IAdminDashboardComponent>> getAllSetDashboards( )
{
Map<String, List<IAdminDashboardComponent>> mapDashboardComponents = new HashMap<>( );
List<IAdminDashboardComponent> listDashboards = AdminDashboardHome.findAll( );
for ( IAdminDashboardComponent dashboard : listDashboards )
{
int nColumn = dashboard.getZone( );
String strColumn = Integer.toString( nColumn );
// find this column list
List<IAdminDashboardComponent> listDashboardsColumn = mapDashboardComponents.computeIfAbsent( strColumn, s -> new ArrayList<>( ) );
// add dashboard to the list
listDashboardsColumn.add( dashboard );
}
return mapDashboardComponents;
}
/**
* Gets Data from all components of the zone
*
* @param user
* The user
* @param nColumn
* The dasboard column
* @param request
* HttpServletRequest
* @return Data of all components of the zone
*/
public String getDashboardData( AdminUser user, int nColumn, HttpServletRequest request )
{
StringBuilder sbDashboardData = new StringBuilder( );
for ( IAdminDashboardComponent dc : getAdminDashboardComponents( nColumn ) )
{
boolean bRight = ( dc.getRight( ) == null ) || user.checkRight( dc.getRight( ) ) || dc.getRight( ).equalsIgnoreCase( ALL );
if ( dc.isEnabled( ) && bRight )
{
sbDashboardData.append( dc.getDashboardData( user, request ) );
}
}
return sbDashboardData.toString( );
}
/**
* Reorders column's dashboard
*
* @param nColumn
* the column to reorder
*/
public void doReorderColumn( int nColumn )
{
int nOrder = CONSTANTE_FIRST_ORDER;
for ( IAdminDashboardComponent dc : getAdminDashboardComponents( nColumn ) )
{
dc.setOrder( nOrder++ );
AdminDashboardHome.update( dc );
}
}
/**
* Builds the map to with column id as key, and <code>true</code> as value if column is well ordered, <code>false</code> otherwise.
*
* @return the map
*/
public Map<String, Boolean> getOrderedColumnsStatus( )
{
Map<String, Boolean> mapOrderedStatus = new HashMap<>( );
List<Integer> listColumns = AdminDashboardHome.findColumns( );
for ( Integer nIdColumn : listColumns )
{
mapOrderedStatus.put( nIdColumn.toString( ), isWellOrdered( nIdColumn ) );
}
return mapOrderedStatus;
}
/**
* Determines if the column is well ordered
*
* @param nColumn
* the column id
* @return true if well ordered, <code>false</code> otherwise.
*/
private boolean isWellOrdered( int nColumn )
{
int nOrder = CONSTANTE_FIRST_ORDER;
for ( IAdminDashboardComponent dc : getAdminDashboardComponents( nColumn ) )
{
if ( nOrder != dc.getOrder( ) )
{
return false;
}
nOrder++;
}
return true;
}
}