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;
35  
36  import fr.paris.lutece.portal.business.dashboard.DashboardFactory;
37  import fr.paris.lutece.portal.business.dashboard.DashboardFilter;
38  import fr.paris.lutece.portal.business.dashboard.DashboardHome;
39  import fr.paris.lutece.portal.business.user.AdminUser;
40  import fr.paris.lutece.portal.service.plugin.Plugin;
41  import fr.paris.lutece.portal.service.spring.SpringContextService;
42  import fr.paris.lutece.portal.service.util.AppLogService;
43  import fr.paris.lutece.portal.service.util.AppPropertiesService;
44  import fr.paris.lutece.util.ReferenceList;
45  import fr.paris.lutece.util.sort.AttributeComparator;
46  
47  import java.util.ArrayList;
48  import java.util.Collections;
49  import java.util.HashMap;
50  import java.util.List;
51  import java.util.Map;
52  
53  import javax.servlet.http.HttpServletRequest;
54  
55  
56  /**
57   * Dashboard Service
58   */
59  public final class DashboardService
60  {
61      // Properties
62      private static final String PROPERTY_COLUMN_COUNT = "dashboard.columnCount";
63  
64      // Constants
65      private static final String ALL = "ALL";
66      private static final String EMPTY_STRING = "";
67      private static final String ORDER = "order";
68      private static final int CONSTANTE_FIRST_ORDER = 1;
69      private static final int CONSTANTE_DEFAULT_COLUMN_COUNT = 3;
70      private static DashboardService _singleton = new DashboardService(  );
71  
72      /**
73       * Private Constructor
74       */
75      private DashboardService(  )
76      {
77      }
78  
79      /**
80       * Return the unique instance
81       * @return The instance
82       */
83      public static DashboardService getInstance(  )
84      {
85          return _singleton;
86      }
87  
88      /**
89           * Returns the column count, with {@link DashboardService#PROPERTY_COLUMN_COUNT}. Default is {@link DashboardService#CONSTANTE_DEFAULT_COLUMN_COUNT}
90           * @return the column count
91           */
92      public int getColumnCount(  )
93      {
94          return AppPropertiesService.getPropertyInt( PROPERTY_COLUMN_COUNT, CONSTANTE_DEFAULT_COLUMN_COUNT );
95      }
96  
97      /**
98       * All known dashboards as declared in SpringContext
99       * @return dashboards list
100      */
101     public List<IDashboardComponent> getAllDashboardComponents(  )
102     {
103         return DashboardFactory.getAllDashboardComponents(  );
104     }
105 
106     /**
107      *
108      * @param nColumn the column id
109      * @return all dashboards for this column
110      */
111     public List<IDashboardComponent> getDashboardComponents( int nColumn )
112     {
113         DashboardFilter filter = new DashboardFilter(  );
114         filter.setFilterColumn( nColumn );
115 
116         List<IDashboardComponent> dashboardComponents = DashboardHome.findByFilter( filter );
117 
118         return dashboardComponents;
119     }
120 
121     /**
122      * Register a Dashboard Component
123      * @param entry The DashboardComponent entry defined in the plugin's XML file
124      * @param plugin The plugin
125      */
126     public void registerDashboardComponent( DashboardComponentEntry entry, Plugin plugin )
127     {
128         try
129         {
130             DashboardComponent dc = (DashboardComponent) Class.forName( entry.getComponentClass(  ) ).newInstance(  );
131 
132             dc.setName( entry.getName(  ) );
133             dc.setRight( entry.getRight(  ) );
134             dc.setPlugin( plugin );
135 
136             boolean bRegistered = DashboardFactory.registerDashboardComponent( dc );
137 
138             if ( bRegistered )
139             {
140                 AppLogService.info( "New Dashboard Component registered : " + entry.getName(  ) );
141             }
142             else
143             {
144                 AppLogService.error( " Dashboard Component not registered : " + entry.getName(  ) + " : " +
145                     entry.getComponentClass(  ) );
146             }
147         }
148         catch ( InstantiationException e )
149         {
150             AppLogService.error( "Error registering a DashboardComponent : " + e.getMessage(  ), e );
151         }
152         catch ( IllegalAccessException e )
153         {
154             AppLogService.error( "Error registering a DashboardComponent : " + e.getMessage(  ), e );
155         }
156         catch ( ClassNotFoundException e )
157         {
158             AppLogService.error( "Error registering a DashboardComponent : " + e.getMessage(  ), e );
159         }
160     }
161 
162     /**
163          * Moves the dashboard.
164          * @param dashboard to move, with new values
165          * @param nOldColumn previous column id
166          * @param nOldOrder previous order
167          * @param bCreate <code>true</code> if this is a new dashboard, <code>false</code> otherwise.
168          */
169     public void doMoveDashboard( IDashboardComponent dashboard, int nOldColumn, int nOldOrder, boolean bCreate )
170     {
171         int nColumn = dashboard.getZone(  );
172         int nOrder = dashboard.getOrder(  );
173 
174         // find the dashboard already with this order and column
175         DashboardFilter filter = new DashboardFilter(  );
176         filter.setFilterColumn( nColumn );
177 
178         List<IDashboardComponent> listColumnDashboards = DashboardHome.findByFilter( filter );
179 
180         if ( ( listColumnDashboards != null ) && !listColumnDashboards.isEmpty(  ) )
181         {
182             if ( AppLogService.isDebugEnabled(  ) )
183             {
184                 AppLogService.debug( "Reordering  dashboard column " + dashboard.getZone(  ) );
185             }
186 
187             // sort by order
188             Collections.sort( listColumnDashboards );
189 
190             int nMaxOrder = listColumnDashboards.get( listColumnDashboards.size(  ) - 1 ).getOrder(  );
191 
192             if ( ( nOldColumn == 0 ) || ( nOldColumn != nColumn ) )
193             {
194                 // was not in this column before, put to the end
195                 dashboard.setOrder( nMaxOrder + 1 );
196             }
197             else
198             {
199                 if ( nOrder < nOldOrder )
200                 {
201                     for ( IDashboardComponent dc : listColumnDashboards )
202                     {
203                         if ( !dc.equals( dashboard ) )
204                         {
205                             int nCurrentOrder = dc.getOrder(  );
206 
207                             if ( ( nCurrentOrder >= nOrder ) && ( nCurrentOrder < nOldOrder ) )
208                             {
209                                 dc.setOrder( nCurrentOrder + 1 );
210                                 DashboardHome.update( dc );
211                             }
212                         }
213                     }
214                 }
215                 else if ( nOrder > nOldOrder )
216                 {
217                     for ( IDashboardComponent dc : listColumnDashboards )
218                     {
219                         if ( !dc.equals( dashboard ) )
220                         {
221                             int nCurrentOrder = dc.getOrder(  );
222 
223                             if ( ( nCurrentOrder <= nOrder ) && ( nCurrentOrder > nOldOrder ) )
224                             {
225                                 dc.setOrder( nCurrentOrder - 1 );
226                                 DashboardHome.update( dc );
227                             }
228                         }
229                     }
230                 }
231 
232                 // dashboard are singletons, values are modified by getting it from database
233                 dashboard.setOrder( nOrder );
234                 dashboard.setZone( nColumn );
235             }
236         }
237         else
238         {
239             dashboard.setOrder( 1 );
240         }
241 
242         if ( bCreate )
243         {
244             // create dashboard
245             DashboardHome.create( dashboard );
246         }
247         else
248         {
249             // update dashboard
250             DashboardHome.update( dashboard );
251         }
252     }
253 
254     /**
255      * Returns all dashboards with no column/order set
256      * @return all dashboards with no column/order set
257      */
258     public List<IDashboardComponent> getNotSetDashboards(  )
259     {
260         List<IDashboardComponent> listDashboards = DashboardHome.findAll(  );
261         List<IDashboardComponent> listSpringDashboards = getAllDashboardComponents(  );
262 
263         List<IDashboardComponent> listUnsetDashboards = new ArrayList<IDashboardComponent>(  );
264 
265         for ( IDashboardComponent dashboard : listSpringDashboards )
266         {
267             if ( !listDashboards.contains( dashboard ) )
268             {
269                 listUnsetDashboards.add( dashboard );
270             }
271         }
272 
273         return listUnsetDashboards;
274     }
275 
276     /**
277      * Finds all dashboard with column and order set.
278      * @param user the current user
279      * @return a map where key is the column id, and value is the column's dashboard list.
280      */
281     public Map<String, List<IDashboardComponent>> getAllSetDashboards( AdminUser user )
282     {
283         Map<String, List<IDashboardComponent>> mapDashboardComponents = new HashMap<String, List<IDashboardComponent>>(  );
284 
285         List<IDashboardComponent> listDashboards = DashboardHome.findAll(  );
286 
287         for ( IDashboardComponent dashboard : listDashboards )
288         {
289             int nColumn = dashboard.getZone(  );
290             boolean bRight = user.checkRight( dashboard.getRight(  ) ) ||
291                 dashboard.getRight(  ).equalsIgnoreCase( ALL );
292 
293             if ( !bRight )
294             {
295                 continue;
296             }
297 
298             String strColumn = Integer.toString( nColumn );
299 
300             // find this column list
301             List<IDashboardComponent> listDashboardsColumn = mapDashboardComponents.get( strColumn );
302 
303             if ( listDashboardsColumn == null )
304             {
305                 // the list does not exist, create it
306                 listDashboardsColumn = new ArrayList<IDashboardComponent>(  );
307                 mapDashboardComponents.put( strColumn, listDashboardsColumn );
308             }
309 
310             // add dashboard to the list
311             listDashboardsColumn.add( dashboard );
312         }
313 
314         return mapDashboardComponents;
315     }
316 
317     /**
318      * Gets Data from all components of the zone
319      * @param user The user
320      * @param nZone The dasboard zone
321      * @param request HttpServletRequest
322      * @return Data of all components of the zone
323      */
324     public String getDashboardData( AdminUser user, int nZone, HttpServletRequest request )
325     {
326         StringBuffer sbDashboardData = new StringBuffer(  );
327 
328         for ( IDashboardComponent dc : getDashboardComponents( nZone ) )
329         {
330             boolean bRight = user.checkRight( dc.getRight(  ) ) || dc.getRight(  ).equalsIgnoreCase( ALL );
331 
332             if ( ( dc.getZone(  ) == nZone ) && dc.isEnabled(  ) && bRight )
333             {
334                 sbDashboardData.append( dc.getDashboardData( user, request ) );
335             }
336         }
337 
338         return sbDashboardData.toString(  );
339     }
340 
341     /**
342      * Get the list of dashboard from plugins
343      * @param user the current user
344      * @param request HttpServletRequest
345      * @return the list of dashboards
346      */
347     public List<IDashboardComponent> getDashboards( AdminUser user, HttpServletRequest request )
348     {
349         List<IDashboardComponent> listDashboards = new ArrayList<IDashboardComponent>(  );
350 
351         // Attributes associated to the plugins
352         for ( DashboardListenerService dashboardListenerService : SpringContextService.getBeansOfType( 
353                 DashboardListenerService.class ) )
354         {
355             dashboardListenerService.getDashboardComponents( listDashboards, user, request );
356         }
357 
358         return listDashboards;
359     }
360 
361     /**
362      * Gets Data from all components of the zone
363      * @param listDashboards the list of dashboards
364      * @param user The user
365      * @param nZone The dasboard zone
366      * @param request HttpServletRequest
367      * @return Data of all components of the zone
368      */
369     public String getDashboardData( List<IDashboardComponent> listDashboards, AdminUser user, int nZone,
370         HttpServletRequest request )
371     {
372         List<IDashboardComponent> listDashboardComponents = new ArrayList<IDashboardComponent>(  );
373 
374         for ( IDashboardComponent dc : listDashboards )
375         {
376             if ( dc.getZone(  ) == nZone )
377             {
378                 listDashboardComponents.add( dc );
379             }
380         }
381 
382         Collections.sort( listDashboardComponents, new AttributeComparator( ORDER, true ) );
383 
384         StringBuffer sbDashboardData = new StringBuffer(  );
385 
386         for ( IDashboardComponent dc : listDashboardComponents )
387         {
388             boolean bRight = user.checkRight( dc.getRight(  ) ) || dc.getRight(  ).equalsIgnoreCase( ALL );
389 
390             if ( ( dc.getZone(  ) == nZone ) && dc.isEnabled(  ) && bRight )
391             {
392                 sbDashboardData.append( dc.getDashboardData( user, request ) );
393             }
394         }
395 
396         return sbDashboardData.toString(  );
397     }
398 
399     /**
400          * Reorders column's dashboard
401          * @param nColumn the column to reorder
402          */
403     public void doReorderColumn( int nColumn )
404     {
405         int nOrder = CONSTANTE_FIRST_ORDER;
406 
407         for ( IDashboardComponent dc : getDashboardComponents( nColumn ) )
408         {
409             dc.setOrder( nOrder++ );
410             DashboardHome.update( dc );
411         }
412     }
413 
414     /**
415      * Builds the map to with column id as key, and <code>true</code> as value if column is well ordered, <code>false</code> otherwise.
416      * @return the map
417      */
418     public Map<String, Boolean> getOrderedColumnsStatus(  )
419     {
420         Map<String, Boolean> mapOrderedStatus = new HashMap<String, Boolean>(  );
421         List<Integer> listColumns = DashboardHome.findColumns(  );
422 
423         for ( Integer nIdColumn : listColumns )
424         {
425             mapOrderedStatus.put( nIdColumn.toString(  ), isWellOrdered( nIdColumn ) );
426         }
427 
428         return mapOrderedStatus;
429     }
430 
431     /**
432      * Determines if the column is well ordered
433      * @param nColumn the column id
434      * @return true if well ordered, <code>false</code> otherwise.
435      */
436     private boolean isWellOrdered( int nColumn )
437     {
438         int nOrder = CONSTANTE_FIRST_ORDER;
439 
440         for ( IDashboardComponent dc : getDashboardComponents( nColumn ) )
441         {
442             if ( nOrder != dc.getOrder(  ) )
443             {
444                 return false;
445             }
446 
447             nOrder++;
448         }
449 
450         return true;
451     }
452 
453     /**
454      * Returns list with available column
455      * @return all available columns
456      */
457     public ReferenceList getListAvailableColumns(  )
458     {
459         ReferenceList refList = new ReferenceList(  );
460 
461         // add empty item
462         refList.addItem( EMPTY_STRING, EMPTY_STRING );
463 
464         for ( int nColumnIndex = 1; nColumnIndex <= getColumnCount(  ); nColumnIndex++ )
465         {
466             refList.addItem( nColumnIndex, Integer.toString( nColumnIndex ) );
467         }
468 
469         return refList;
470     }
471 
472     /**
473      * Builds all refList order for all columns
474      * @return the map with column id as key
475      */
476     public Map<String, ReferenceList> getMapAvailableOrders(  )
477     {
478         Map<String, ReferenceList> mapAvailableOrders = new HashMap<String, ReferenceList>(  );
479 
480         // get columns
481         for ( Integer nColumn : DashboardHome.findColumns(  ) )
482         {
483             // get orders
484             mapAvailableOrders.put( nColumn.toString(  ), getListAvailableOrders( nColumn ) );
485         }
486 
487         return mapAvailableOrders;
488     }
489 
490     /**
491      * Orders reference list for the given column
492      * @param nColumn column
493      * @return the refList
494      */
495     public ReferenceList getListAvailableOrders( int nColumn )
496     {
497         ReferenceList refList = new ReferenceList(  );
498 
499         // add empty item
500         refList.addItem( EMPTY_STRING, EMPTY_STRING );
501 
502         int nMaxOrder = DashboardHome.findMaxOrder( nColumn );
503 
504         for ( int nOrder = 1; nOrder <= nMaxOrder; nOrder++ )
505         {
506             refList.addItem( nOrder, Integer.toString( nOrder ) );
507         }
508 
509         return refList;
510     }
511 }