View Javadoc
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.web.portlet;
35  
36  import java.util.HashMap;
37  import java.util.Locale;
38  import java.util.Map;
39  
40  import javax.servlet.http.HttpServletRequest;
41  
42  import fr.paris.lutece.portal.business.page.PageHome;
43  import fr.paris.lutece.portal.business.portlet.Portlet;
44  import fr.paris.lutece.portal.business.portlet.PortletHome;
45  import fr.paris.lutece.portal.business.portlet.PortletType;
46  import fr.paris.lutece.portal.business.portlet.PortletTypeHome;
47  import fr.paris.lutece.portal.business.role.RoleHome;
48  import fr.paris.lutece.portal.service.message.AdminMessage;
49  import fr.paris.lutece.portal.service.message.AdminMessageService;
50  import fr.paris.lutece.portal.service.template.AppTemplateService;
51  import fr.paris.lutece.portal.service.util.AppLogService;
52  import fr.paris.lutece.portal.service.util.AppPropertiesService;
53  import fr.paris.lutece.portal.web.admin.AdminFeaturesPageJspBean;
54  import fr.paris.lutece.portal.web.constants.Messages;
55  import fr.paris.lutece.portal.web.constants.Parameters;
56  import fr.paris.lutece.util.ReferenceList;
57  import fr.paris.lutece.util.html.HtmlTemplate;
58  import fr.paris.lutece.util.string.StringUtil;
59  
60  /**
61   * This class represents user interface Portlet. It is the base class of all user interface portlets. It is abstract and the implementation of the interface
62   * PortletJspBeanInterface is compulsary.
63   */
64  public abstract class PortletJspBean extends AdminFeaturesPageJspBean
65  {
66      // //////////////////////////////////////////////////////////////////////////
67      // Constants
68      public static final String RIGHT_MANAGE_ADMIN_SITE = "CORE_ADMIN_SITE";
69  
70      // Parameters
71      protected static final String PARAMETER_PAGE_ID = "page_id";
72      protected static final String PARAMETER_PORTLET_ID = "portlet_id";
73      protected static final String PARAMETER_PORTLET_TYPE_ID = "portlet_type_id";
74      private static final long serialVersionUID = -3546292252642160812L;
75  
76      // Markers
77      private static final String MARK_PORTLET = "portlet";
78      private static final String MARK_PORTLET_TYPE = "portletType";
79      private static final String MARK_PORTLET_PAGE_ID = "portlet_page_id";
80      private static final String MARK_PORTLET_ORDER_COMBO = "portlet_order_combo";
81      private static final String MARK_PORTLET_COLUMNS_COMBO = "portlet_columns_combo";
82      private static final String MARK_PORTLET_STYLES_COMBO = "portlet_style_combo";
83      private static final String MARK_PORTLET_ROLES_COMBO = "portlet_role_combo";
84      private static final String MARK_SMALL_CHECKED = "small_checked";
85      private static final String MARK_NORMAL_CHECKED = "normal_checked";
86      private static final String MARK_LARGE_CHECKED = "large_checked";
87      private static final String MARK_XLARGE_CHECKED = "xlarge_checked";
88      private static final String VALUE_CHECKED = "checked=\"checked\"";
89      private static final String VALUE_UNCHECKED = "";
90  
91      // Templates
92      private static final String TEMPLATE_CREATE_PORTLET = "admin/portlet/create_portlet.html";
93      private static final String TEMPLATE_MODIFY_PORTLET = "admin/portlet/modify_portlet.html";
94  
95      // Properties
96      private static final String PROPERTY_LIST_ORDER_MAX = "list.order.max";
97      private static final String PROPERTY_COLUMN_NUM_MAX = "nb.columns";
98  
99      // Messages
100     private static final String MESSAGE_INVALID_PAGE_ID = "portal.site.message.pageIdInvalid";
101 
102     // Jsp
103     private static final String JSP_ADMIN_SITE = "../../site/AdminSite.jsp";
104 
105     /**
106      * Displays the portlet's creation form
107      *
108      * @param request
109      *            The http request
110      * @return The html code for displaying the creation form
111      */
112     public abstract String getCreate( HttpServletRequest request );
113 
114     /**
115      * Processes portlet's creation
116      *
117      * @param request
118      *            The http request
119      * @return The Management jsp url
120      */
121     public abstract String doCreate( HttpServletRequest request );
122 
123     /**
124      * Displays the portlet's modification form
125      *
126      * @param request
127      *            The http request
128      * @return The html code for displaying the modification form
129      */
130     public abstract String getModify( HttpServletRequest request );
131 
132     /**
133      * Processes portlet's modification
134      *
135      * @param request
136      *            The http request
137      * @return The Management jsp url
138      */
139     public abstract String doModify( HttpServletRequest request );
140 
141     // //////////////////////////////////////////////////////////////////////////
142     // Management of the combos common to all portlets
143     // Order combo
144 
145     /**
146      * Returns a list of orders
147      *
148      * @return the list of orders in form of ReferenceList
149      */
150     private ReferenceList getOrdersList( )
151     {
152         ReferenceListnceList.html#ReferenceList">ReferenceList list = new ReferenceList( );
153         int nOrderMax = AppPropertiesService.getPropertyInt( PROPERTY_LIST_ORDER_MAX, 15 );
154 
155         for ( int i = 1; i <= nOrderMax; i++ )
156         {
157             list.addItem( i, String.valueOf( i ) );
158         }
159 
160         return list;
161     }
162 
163     /**
164      * Returns the list of the columns of the page where the portlet can be positioned
165      *
166      * @return the list of the page columns in form of ReferenceList
167      */
168     private ReferenceList getColumnsList( )
169     {
170         ReferenceListnceList.html#ReferenceList">ReferenceList list = new ReferenceList( );
171         int nColumnNumMax = AppPropertiesService.getPropertyInt( PROPERTY_COLUMN_NUM_MAX, 1 );
172 
173         for ( int i = 1; i <= nColumnNumMax; i++ )
174         {
175             list.addItem( i, String.valueOf( i ) );
176         }
177 
178         return list;
179     }
180 
181     /**
182      * Recovers the common attributes of the portlet
183      *
184      * @param request
185      *            the http request
186      * @param portlet
187      *            The instance of the portlet
188      * @return An error Key if error, otherwise null.
189      */
190     protected String setPortletCommonData( HttpServletRequest request, Portlet portlet )
191     {
192         String strErrorKey = null;
193 
194         // get portlet attributes
195         String strName = request.getParameter( Parameters.PORTLET_NAME );
196         String strStyleId = request.getParameter( Parameters.STYLE );
197         String strColumn = request.getParameter( Parameters.COLUMN );
198         String strOrder = request.getParameter( Parameters.ORDER );
199         String strAcceptAlias = request.getParameter( Parameters.ACCEPT_ALIAS );
200         String strAcceptPortletTitle = request.getParameter( Parameters.DISPLAY_PORTLET_TITLE );
201         String strPortletTypeId = request.getParameter( Parameters.PORTLET_TYPE_ID );
202         String strRole = request.getParameter( Parameters.ROLE );
203         String strDisplaySmall = request.getParameter( Parameters.DISPLAY_ON_SMALL_DEVICE );
204         String strDisplayNormal = request.getParameter( Parameters.DISPLAY_ON_NORMAL_DEVICE );
205         String strDisplayLarge = request.getParameter( Parameters.DISPLAY_ON_LARGE_DEVICE );
206         String strDisplayXLarge = request.getParameter( Parameters.DISPLAY_ON_XLARGE_DEVICE );
207 
208         strName = strName.replaceAll( "\"", "" );
209 
210         // Check Mandatory fields
211         if ( StringUtil.isAnyEmpty( strName, strOrder, strColumn, strAcceptAlias, strAcceptPortletTitle ) )
212         {
213             return AdminMessageService.getMessageUrl( request, Messages.MANDATORY_FIELDS, AdminMessage.TYPE_STOP );
214         }
215 
216         // style id is not mandatory if the content is not generated from XML and XSL
217         if ( portlet.isContentGeneratedByXmlAndXsl( ) && ( strStyleId == null || strStyleId.trim( ).equals( "" ) ) )
218         {
219             return AdminMessageService.getMessageUrl( request, Messages.MANDATORY_FIELDS, AdminMessage.TYPE_STOP );
220         }
221 
222         String strPageId = request.getParameter( PARAMETER_PAGE_ID );
223         int nPageId;
224 
225         // Test format of the id and the existence of the page
226         try
227         {
228             nPageId = Integer.parseInt( strPageId );
229 
230             if ( !PageHome.checkPageExist( nPageId ) )
231             {
232                 return AdminMessageService.getMessageUrl( request, MESSAGE_INVALID_PAGE_ID, AdminMessage.TYPE_STOP );
233             }
234         }
235         catch( NumberFormatException e )
236         {
237             AppLogService.error( e.getMessage( ), e );
238 
239             return AdminMessageService.getMessageUrl( request, MESSAGE_INVALID_PAGE_ID, AdminMessage.TYPE_STOP );
240         }
241 
242         int nOrder = Integer.parseInt( strOrder );
243         int nColumn = Integer.parseInt( strColumn );
244         int nAcceptAlias = Integer.parseInt( strAcceptAlias );
245         int nAcceptPortletTitle = Integer.parseInt( strAcceptPortletTitle );
246 
247         int nStyleId = portlet.isContentGeneratedByXmlAndXsl( ) ? Integer.parseInt( strStyleId ) : 0;
248 
249         int nDeviceDisplayFlags = 0;
250 
251         if ( strDisplaySmall != null )
252         {
253             nDeviceDisplayFlags |= Portlet.FLAG_DISPLAY_ON_SMALL_DEVICE;
254         }
255 
256         if ( strDisplayNormal != null )
257         {
258             nDeviceDisplayFlags |= Portlet.FLAG_DISPLAY_ON_NORMAL_DEVICE;
259         }
260 
261         if ( strDisplayLarge != null )
262         {
263             nDeviceDisplayFlags |= Portlet.FLAG_DISPLAY_ON_LARGE_DEVICE;
264         }
265 
266         if ( strDisplayXLarge != null )
267         {
268             nDeviceDisplayFlags |= Portlet.FLAG_DISPLAY_ON_XLARGE_DEVICE;
269         }
270 
271         portlet.setName( strName );
272         portlet.setOrder( nOrder );
273         portlet.setColumn( nColumn );
274         portlet.setStyleId( nStyleId );
275         portlet.setPageId( nPageId );
276         portlet.setAcceptAlias( nAcceptAlias );
277         portlet.setDisplayPortletTitle( nAcceptPortletTitle );
278         portlet.setPortletTypeId( strPortletTypeId );
279         portlet.setRole( strRole );
280         portlet.setDeviceDisplayFlags( nDeviceDisplayFlags );
281 
282         return strErrorKey;
283     }
284 
285     /**
286      * Fills templates with common values shared by portlet creation form
287      *
288      * @param strPageId
289      *            the page identifier
290      * @param strPortletTypeId
291      *            the Portlet type identifier
292      * @return the template filled
293      */
294     protected HtmlTemplate getCreateTemplate( String strPageId, String strPortletTypeId )
295     {
296         return getCreateTemplate( strPageId, strPortletTypeId, new HashMap<>( ) );
297     }
298 
299     /**
300      * Fills templates with common values shared by portlet creation form
301      *
302      * @param strPageId
303      *            the page identifier
304      * @param strPortletTypeId
305      *            the Portlet type identifier
306      * @param model
307      *            Specific data stored in a hashtable
308      * @return the template filled
309      */
310     protected HtmlTemplate getCreateTemplate( String strPageId, String strPortletTypeId, Map<String, Object> model )
311     {
312         PortletType portletType = PortletTypeHome.findByPrimaryKey( strPortletTypeId );
313         Locale locale = getLocale( );
314         portletType.setLocale( locale );
315 
316         model.put( MARK_PORTLET_TYPE, portletType );
317         model.put( MARK_PORTLET_PAGE_ID, strPageId );
318         model.put( MARK_PORTLET_ORDER_COMBO, getOrdersList( ) );
319         model.put( MARK_PORTLET_COLUMNS_COMBO, getColumnsList( ) );
320         model.put( MARK_PORTLET_STYLES_COMBO, PortletHome.getStylesList( strPortletTypeId ) );
321         model.put( MARK_PORTLET_ROLES_COMBO, RoleHome.getRolesList( getUser( ) ) );
322 
323         return AppTemplateService.getTemplate( TEMPLATE_CREATE_PORTLET, locale, model );
324     }
325 
326     /**
327      * Fills update template with portlet values
328      *
329      * @param portlet
330      *            the object to update
331      * @return the update template filled
332      */
333     protected HtmlTemplate getModifyTemplate( Portlet portlet )
334     {
335         return getModifyTemplate( portlet, new HashMap<>( ) );
336     }
337 
338     /**
339      * Fills update template with portlet values
340      *
341      * @param portlet
342      *            the object to update
343      * @param model
344      *            The Data model
345      * @return the update template filled
346      */
347     protected HtmlTemplate getModifyTemplate( Portlet portlet, Map<String, Object> model )
348     {
349         PortletType portletType = PortletTypeHome.findByPrimaryKey( portlet.getPortletTypeId( ) );
350         portletType.setLocale( getLocale( ) );
351         model.put( MARK_PORTLET_TYPE, portletType );
352         model.put( MARK_PORTLET, portlet );
353         model.put( MARK_PORTLET_ORDER_COMBO, getOrdersList( ) );
354         model.put( MARK_PORTLET_COLUMNS_COMBO, getColumnsList( ) );
355         model.put( MARK_PORTLET_STYLES_COMBO, PortletHome.getStylesList( portlet.getPortletTypeId( ) ) );
356         model.put( MARK_PORTLET_ROLES_COMBO, RoleHome.getRolesList( getUser( ) ) );
357         putCheckBox( model, MARK_SMALL_CHECKED, portlet.hasDeviceDisplayFlag( Portlet.FLAG_DISPLAY_ON_SMALL_DEVICE ) );
358         putCheckBox( model, MARK_NORMAL_CHECKED, portlet.hasDeviceDisplayFlag( Portlet.FLAG_DISPLAY_ON_NORMAL_DEVICE ) );
359         putCheckBox( model, MARK_LARGE_CHECKED, portlet.hasDeviceDisplayFlag( Portlet.FLAG_DISPLAY_ON_LARGE_DEVICE ) );
360         putCheckBox( model, MARK_XLARGE_CHECKED, portlet.hasDeviceDisplayFlag( Portlet.FLAG_DISPLAY_ON_XLARGE_DEVICE ) );
361 
362         return AppTemplateService.getTemplate( TEMPLATE_MODIFY_PORTLET, getLocale( ), model );
363     }
364 
365     /**
366      * Put check box.
367      *
368      * @param model
369      *            the model
370      * @param strMarkerChecked
371      *            the str marker checked
372      * @param bChecked
373      *            the b checked
374      */
375     protected void putCheckBox( Map<String, Object> model, String strMarkerChecked, boolean bChecked )
376     {
377         String strChecked = ( bChecked ) ? VALUE_CHECKED : VALUE_UNCHECKED;
378         model.put( strMarkerChecked, strChecked );
379     }
380 
381     /**
382      * Gets the page URL
383      * 
384      * @param nIdPage
385      *            Page ID
386      * @return The page URL
387      */
388     protected String getPageUrl( int nIdPage )
389     {
390         return JSP_ADMIN_SITE + "?" + PARAMETER_PAGE_ID + "=" + nIdPage;
391     }
392 }