View Javadoc
1   /*
2    * Copyright (c) 2002-2014, Mairie de 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  
36  import fr.paris.lutece.portal.business.dashboard.AdminDashboardFactory;
37  import fr.paris.lutece.portal.business.dashboard.AdminDashboardFilter;
38  import fr.paris.lutece.portal.business.dashboard.AdminDashboardHome;
39  import fr.paris.lutece.portal.business.user.AdminUser;
40  import fr.paris.lutece.portal.service.dashboard.DashboardComponentEntry;
41  import fr.paris.lutece.portal.service.plugin.Plugin;
42  import fr.paris.lutece.portal.service.util.AppLogService;
43  import fr.paris.lutece.portal.service.util.AppPropertiesService;
44  
45  import java.util.ArrayList;
46  import java.util.Collections;
47  import java.util.HashMap;
48  import java.util.List;
49  import java.util.Map;
50  
51  import javax.servlet.http.HttpServletRequest;
52  
53  
54  /**
55   *
56   * AdminDashboardService
57   *
58   */
59  public final class AdminDashboardService
60  {
61      /**
62       * admindashboard.columnCount
63       */
64      private static final String PROPERTY_COLUMN_COUNT = "admindashboard.columnCount";
65      private static final String ALL = "ALL";
66      private static final int CONSTANTE_FIRST_ORDER = 1;
67      private static final int CONSTANTE_DEFAULT_COLUMN_COUNT = 2;
68      private static AdminDashboardService _singleton = new AdminDashboardService(  );
69  
70      /**
71       * Private Constructor
72       */
73      private AdminDashboardService(  )
74      {
75          // nothing
76      }
77  
78      /**
79       * Return the unique instance
80       * @return The instance
81       */
82      public static AdminDashboardService getInstance(  )
83      {
84          return _singleton;
85      }
86  
87      /**
88       * Returns the column count, with {@link AdminDashboardService#PROPERTY_COLUMN_COUNT}. Default is {@link AdminDashboardService#CONSTANTE_DEFAULT_COLUMN_COUNT}
89       * @return the column count
90       */
91      public int getColumnCount(  )
92      {
93          return AppPropertiesService.getPropertyInt( PROPERTY_COLUMN_COUNT, CONSTANTE_DEFAULT_COLUMN_COUNT );
94      }
95  
96      /**
97       * All known dashboards as declared in SpringContext
98       * @return dashboards list
99       */
100     public List<IAdminDashboardComponent> getAllAdminDashboardComponents(  )
101     {
102         return AdminDashboardFactory.getAllAdminDashboardComponents(  );
103     }
104 
105     /**
106      *
107      * @param nColumn the column id
108      * @return all dashboards for this column
109      */
110     public List<IAdminDashboardComponent> getAdminDashboardComponents( int nColumn )
111     {
112         AdminDashboardFilter filter = new AdminDashboardFilter(  );
113         filter.setFilterColumn( nColumn );
114 
115         List<IAdminDashboardComponent> dashboardComponents = AdminDashboardHome.findByFilter( filter );
116 
117         return dashboardComponents;
118     }
119 
120     /**
121      * Register a Dashboard Component
122      * @param entry The DashboardComponent entry defined in the plugin's XML file
123      * @param plugin The plugin
124      */
125     public void registerDashboardComponent( DashboardComponentEntry entry, Plugin plugin )
126     {
127         try
128         {
129             IAdminDashboardComponent dc = (IAdminDashboardComponent) Class.forName( entry.getComponentClass(  ) )
130                                                                           .newInstance(  );
131 
132             dc.setName( entry.getName(  ) );
133             dc.setPlugin( plugin );
134 
135             boolean bRegistered = AdminDashboardFactory.registerDashboardComponent( dc );
136 
137             if ( bRegistered )
138             {
139                 AppLogService.info( "New Admin Dashboard Component registered : " + entry.getName(  ) );
140             }
141             else
142             {
143                 AppLogService.error( " Admin Dashboard Component not registered : " + entry.getName(  ) + " : " +
144                     entry.getComponentClass(  ) );
145             }
146         }
147         catch ( InstantiationException e )
148         {
149             AppLogService.error( "Error registering an Admin DashboardComponent : " + e.getMessage(  ), e );
150         }
151         catch ( IllegalAccessException e )
152         {
153             AppLogService.error( "Error registering an Admin DashboardComponent : " + e.getMessage(  ), e );
154         }
155         catch ( ClassNotFoundException e )
156         {
157             AppLogService.error( "Error registering an Admin DashboardComponent : " + e.getMessage(  ), e );
158         }
159     }
160 
161     /**
162      * Moves the dashboard.
163      * @param dashboard to move, with new values
164      * @param nOldColumn previous column id
165      * @param nOldOrder previous order
166      * @param bCreate <code>true</code> if this is a new dashboard, <code>false</code> otherwise.
167      */
168     public void doMoveDashboard( IAdminDashboardComponent dashboard, int nOldColumn, int nOldOrder, boolean bCreate )
169     {
170         int nColumn = dashboard.getZone(  );
171         int nOrder = dashboard.getOrder(  );
172 
173         // find the dashboard already with this order and column
174         AdminDashboardFilter filter = new AdminDashboardFilter(  );
175         filter.setFilterColumn( nColumn );
176 
177         List<IAdminDashboardComponent> listColumnDashboards = AdminDashboardHome.findByFilter( filter );
178 
179         if ( ( listColumnDashboards != null ) && !listColumnDashboards.isEmpty(  ) )
180         {
181             if ( AppLogService.isDebugEnabled(  ) )
182             {
183                 AppLogService.debug( "Reordering admin dashboard column " + dashboard.getZone(  ) );
184             }
185 
186             // sort by order
187             Collections.sort( listColumnDashboards );
188 
189             int nMaxOrder = listColumnDashboards.get( listColumnDashboards.size(  ) - 1 ).getOrder(  );
190 
191             if ( ( nOldColumn == 0 ) || ( nOldColumn != nColumn ) )
192             {
193                 // was not in this column before, put to the end
194                 dashboard.setOrder( nMaxOrder + 1 );
195             }
196             else
197             {
198                 if ( nOrder < nOldOrder )
199                 {
200                     for ( IAdminDashboardComponent dc : listColumnDashboards )
201                     {
202                         int nCurrentOrder = dc.getOrder(  );
203 
204                         if ( !dc.equals( dashboard ) && ( nCurrentOrder >= nOrder ) && ( nCurrentOrder < nOldOrder ) )
205                         {
206                             dc.setOrder( nCurrentOrder + 1 );
207                             AdminDashboardHome.update( dc );
208                         }
209                     }
210                 }
211                 else if ( nOrder > nOldOrder )
212                 {
213                     for ( IAdminDashboardComponent dc : listColumnDashboards )
214                     {
215                         int nCurrentOrder = dc.getOrder(  );
216 
217                         if ( !dc.equals( dashboard ) && ( nCurrentOrder <= nOrder ) && ( nCurrentOrder > nOldOrder ) )
218                         {
219                             dc.setOrder( nCurrentOrder - 1 );
220                             AdminDashboardHome.update( dc );
221                         }
222                     }
223                 }
224 
225                 // dashboard are singletons, values are modified by getting it from database
226                 dashboard.setOrder( nOrder );
227                 dashboard.setZone( nColumn );
228             }
229         }
230         else
231         {
232             dashboard.setOrder( 1 );
233         }
234 
235         if ( bCreate )
236         {
237             // create dashboard
238             AdminDashboardHome.create( dashboard );
239         }
240         else
241         {
242             // update dashboard
243             AdminDashboardHome.update( dashboard );
244         }
245     }
246 
247     /**
248      * Returns all dashboards with no column/order set
249      * @return all dashboards with no column/order set
250      */
251     public List<IAdminDashboardComponent> getNotSetDashboards(  )
252     {
253         List<IAdminDashboardComponent> listDashboards = AdminDashboardHome.findAll(  );
254         List<IAdminDashboardComponent> listSpringDashboards = getAllAdminDashboardComponents(  );
255 
256         List<IAdminDashboardComponent> listUnsetDashboards = new ArrayList<IAdminDashboardComponent>(  );
257 
258         for ( IAdminDashboardComponent dashboard : listSpringDashboards )
259         {
260             if ( !listDashboards.contains( dashboard ) )
261             {
262                 listUnsetDashboards.add( dashboard );
263             }
264         }
265 
266         return listUnsetDashboards;
267     }
268 
269     /**
270      * Finds all dashboard with column and order set.
271      * @return a map where key is the column id, and value is the column's dashboard list.
272      */
273     public Map<String, List<IAdminDashboardComponent>> getAllSetDashboards(  )
274     {
275         Map<String, List<IAdminDashboardComponent>> mapDashboardComponents = new HashMap<String, List<IAdminDashboardComponent>>(  );
276 
277         List<IAdminDashboardComponent> listDashboards = AdminDashboardHome.findAll(  );
278 
279         for ( IAdminDashboardComponent dashboard : listDashboards )
280         {
281             int nColumn = dashboard.getZone(  );
282 
283             String strColumn = Integer.toString( nColumn );
284 
285             // find this column list
286             List<IAdminDashboardComponent> listDashboardsColumn = mapDashboardComponents.get( strColumn );
287 
288             if ( listDashboardsColumn == null )
289             {
290                 // the list does not exist, create it
291                 listDashboardsColumn = new ArrayList<IAdminDashboardComponent>(  );
292                 mapDashboardComponents.put( strColumn, listDashboardsColumn );
293             }
294 
295             // add dashboard to the list
296             listDashboardsColumn.add( dashboard );
297         }
298 
299         return mapDashboardComponents;
300     }
301 
302     /**
303      * Gets Data from all components of the zone
304      * @param user The user
305      * @param nColumn The dasboard column
306      * @param request HttpServletRequest
307      * @return Data of all components of the zone
308      */
309     public String getDashboardData( AdminUser user, int nColumn, HttpServletRequest request )
310     {
311         StringBuilder sbDashboardData = new StringBuilder(  );
312 
313         for ( IAdminDashboardComponent dc : getAdminDashboardComponents( nColumn ) )
314         {
315             boolean bRight = ( dc.getRight(  ) == null ) || user.checkRight( dc.getRight(  ) ) ||
316                 dc.getRight(  ).equalsIgnoreCase( ALL );
317 
318             if ( dc.isEnabled(  ) && bRight )
319             {
320                 sbDashboardData.append( dc.getDashboardData( user, request ) );
321             }
322         }
323 
324         return sbDashboardData.toString(  );
325     }
326 
327     /**
328      * Reorders column's dashboard
329      * @param nColumn the column to reorder
330      */
331     public void doReorderColumn( int nColumn )
332     {
333         int nOrder = CONSTANTE_FIRST_ORDER;
334 
335         for ( IAdminDashboardComponent dc : getAdminDashboardComponents( nColumn ) )
336         {
337             dc.setOrder( nOrder++ );
338             AdminDashboardHome.update( dc );
339         }
340     }
341 
342     /**
343      * Builds the map to with column id as key, and <code>true</code> as value if column is well ordered, <code>false</code> otherwise.
344      * @return the map
345      */
346     public Map<String, Boolean> getOrderedColumnsStatus(  )
347     {
348         Map<String, Boolean> mapOrderedStatus = new HashMap<String, Boolean>(  );
349         List<Integer> listColumns = AdminDashboardHome.findColumns(  );
350 
351         for ( Integer nIdColumn : listColumns )
352         {
353             mapOrderedStatus.put( nIdColumn.toString(  ), isWellOrdered( nIdColumn ) );
354         }
355 
356         return mapOrderedStatus;
357     }
358 
359     /**
360      * Determines if the column is well ordered
361      * @param nColumn the column id
362      * @return true if well ordered, <code>false</code> otherwise.
363      */
364     private boolean isWellOrdered( int nColumn )
365     {
366         int nOrder = CONSTANTE_FIRST_ORDER;
367 
368         for ( IAdminDashboardComponent dc : getAdminDashboardComponents( nColumn ) )
369         {
370             if ( nOrder != dc.getOrder(  ) )
371             {
372                 return false;
373             }
374 
375             nOrder++;
376         }
377 
378         return true;
379     }
380 }