PortalMenuService.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.portal;
- import fr.paris.lutece.portal.business.XmlContent;
- import fr.paris.lutece.portal.business.page.Page;
- import fr.paris.lutece.portal.business.page.PageHome;
- import fr.paris.lutece.portal.business.portalcomponent.PortalComponentHome;
- import fr.paris.lutece.portal.business.style.ModeHome;
- import fr.paris.lutece.portal.business.stylesheet.StyleSheet;
- import fr.paris.lutece.portal.service.cache.AbstractCacheableService;
- import fr.paris.lutece.portal.service.html.XmlTransformerService;
- import fr.paris.lutece.portal.service.page.PageEvent;
- import fr.paris.lutece.portal.service.page.PageEventListener;
- import fr.paris.lutece.portal.service.page.PageService;
- import fr.paris.lutece.portal.service.security.LuteceUser;
- import fr.paris.lutece.portal.service.security.SecurityService;
- import fr.paris.lutece.util.xml.XmlUtil;
- import org.apache.commons.lang3.StringUtils;
- import java.util.Arrays;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Properties;
- import javax.servlet.http.HttpServletRequest;
- /**
- * This Service build the portal menu
- */
- public final class PortalMenuService extends AbstractCacheableService implements PageEventListener
- {
- public static final int MENU_INIT = 0;
- public static final int MENU_MAIN = 1;
- public static final int MODE_NORMAL = 0;
- public static final int MODE_ADMIN = 1;
- private static final int PORTAL_COMPONENT_MENU_INIT_ID = 3;
- private static final int PORTAL_COMPONENT_MAIN_MENU_ID = 4;
- private static final String SERVICE_NAME = "PortalMenuService";
- // Menus cache
- private static PortalMenuService _singleton;
- /** Creates a new instance of PortalMenuService */
- private PortalMenuService( )
- {
- initCache( getName( ) );
- PageService.addPageEventListener( this );
- }
- /**
- * Get the unique instance of the service
- *
- * @return The unique instance
- */
- public static synchronized PortalMenuService getInstance( )
- {
- if ( _singleton == null )
- {
- _singleton = new PortalMenuService( );
- }
- return _singleton;
- }
- /**
- * Returns the service name
- *
- * @return The service name
- */
- public String getName( )
- {
- return SERVICE_NAME;
- }
- /**
- * Returns the menu bar from the cache or builds it if it not stored in it
- *
- * @param request
- * The HTTP request
- * @param nMode
- * The selected mode
- * @param nPart
- * The part of the menu to build
- * @param nCurrentPageId
- * The current page ID
- * @return The list of the menus layed out with the stylesheet correpsonding to the mode
- */
- public String getMenuContent( int nCurrentPageId, int nMode, int nPart, HttpServletRequest request )
- {
- String strKey = getKey( nMode, nPart, request );
- String strMenu = (String) getFromCache( strKey );
- // Seek for the key in the cache
- if ( strMenu == null )
- {
- // Builds the HTML document
- strMenu = buildMenuContent( nCurrentPageId, nMode, nPart, request );
- // Add it in the cache
- putInCache( strKey, strMenu );
- return strMenu;
- }
- // The document exist in the cache
- return strMenu;
- }
- /**
- * Builds the menu bar
- *
- * @param nCurrentPageId
- * The current page ID
- * @param nMode
- * The selected mode
- * @param nPart
- * The part of the menu to build
- * @param request
- * The HttpServletRequest
- * @return The list of the menus layed out with the stylesheet of the mode
- */
- private String buildMenuContent( int nCurrentPageId, int nMode, int nPart, HttpServletRequest request )
- {
- Collection<Page> listPagesMenu = PageHome.getChildPagesMinimalData( PortalService.getRootPageId( ) );
- StringBuffer strXml = new StringBuffer( );
- strXml.append( XmlUtil.getXmlHeader( ) );
- XmlUtil.beginElement( strXml, XmlContent.TAG_MENU_LIST );
- int nMenuIndex = 1;
- for ( Page menuPage : listPagesMenu )
- {
- if ( ( menuPage.isVisible( request ) ) || ( nMode == MODE_ADMIN ) )
- {
- buildPageXml( menuPage, strXml, nMode, nMenuIndex, nCurrentPageId, request );
- nMenuIndex++;
- }
- }
- XmlUtil.endElement( strXml, XmlContent.TAG_MENU_LIST );
- // Added in v1.3
- StyleSheet xslSource = getMenuXslSource( nMode, nPart );
- Properties outputProperties = ModeHome.getOuputXslProperties( nMode );
- // Added in v1.3
- // Add a path param for choose url to use in admin or normal mode
- Map<String, String> mapParamRequest = new HashMap<>( );
- PortalService.setXslPortalPath( mapParamRequest, nMode );
- XmlTransformerService xmlTransformerService = new XmlTransformerService( );
- return xmlTransformerService.transformBySourceWithXslCache( strXml.toString( ), xslSource, mapParamRequest, outputProperties );
- }
- private void buildPageXml( Page menuPage, StringBuffer strXml, int nMode, int nMenuIndex, int nCurrentPageId, HttpServletRequest request )
- {
- XmlUtil.beginElement( strXml, XmlContent.TAG_MENU );
- XmlUtil.addElement( strXml, XmlContent.TAG_MENU_INDEX, nMenuIndex );
- XmlUtil.addElement( strXml, XmlContent.TAG_PAGE_ID, menuPage.getId( ) );
- XmlUtil.addElementHtml( strXml, XmlContent.TAG_PAGE_NAME, menuPage.getName( ) );
- XmlUtil.addElementHtml( strXml, XmlContent.TAG_CURRENT_PAGE_ID, String.valueOf( nCurrentPageId ) );
- Collection<Page> listSubLevelMenuPages = PageHome.getChildPagesMinimalData( menuPage.getId( ) );
- // add element submenu-list only if list not empty
- if ( !listSubLevelMenuPages.isEmpty( ) )
- {
- // Seek of the sub-menus
- XmlUtil.beginElement( strXml, XmlContent.TAG_SUBLEVEL_MENU_LIST );
- int nSubLevelMenuIndex = 1;
- for ( Page subLevelMenuPage : listSubLevelMenuPages )
- {
- if ( ( subLevelMenuPage.isVisible( request ) ) || ( nMode == MODE_ADMIN ) )
- {
- XmlUtil.beginElement( strXml, XmlContent.TAG_SUBLEVEL_MENU );
- XmlUtil.addElement( strXml, XmlContent.TAG_MENU_INDEX, nMenuIndex );
- XmlUtil.addElement( strXml, XmlContent.TAG_SUBLEVEL_INDEX, nSubLevelMenuIndex );
- XmlUtil.addElement( strXml, XmlContent.TAG_PAGE_ID, subLevelMenuPage.getId( ) );
- XmlUtil.addElementHtml( strXml, XmlContent.TAG_PAGE_NAME, subLevelMenuPage.getName( ) );
- XmlUtil.endElement( strXml, XmlContent.TAG_SUBLEVEL_MENU );
- XmlUtil.addElementHtml( strXml, XmlContent.TAG_CURRENT_PAGE_ID, String.valueOf( nCurrentPageId ) );
- }
- }
- XmlUtil.endElement( strXml, XmlContent.TAG_SUBLEVEL_MENU_LIST );
- }
- XmlUtil.endElement( strXml, XmlContent.TAG_MENU );
- }
- private StyleSheet getMenuXslSource( int nMode, int nPart )
- {
- // Use the same stylesheet for normal or admin mode
- StyleSheet xslSource;
- // Selection of the XSL stylesheet
- switch( nMode )
- {
- case MODE_NORMAL:
- case MODE_ADMIN:
- xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_MAIN_MENU_ID, MODE_NORMAL );
- break;
- default:
- xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_MAIN_MENU_ID, nMode );
- break;
- }
- if ( nPart == MENU_INIT )
- {
- switch( nMode )
- {
- case MODE_NORMAL:
- case MODE_ADMIN:
- xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_MENU_INIT_ID, MODE_NORMAL );
- break;
- default:
- xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_MENU_INIT_ID, nMode );
- break;
- }
- }
- return xslSource;
- }
- /**
- * Returns the key corresponding to the part according to the selected mode
- *
- * @param nMode
- * The mode
- * @param nPart
- * the part
- * @param request
- * The HTTP request
- * @return The key as a String
- */
- private String getKey( int nMode, int nPart, HttpServletRequest request )
- {
- String strRoles = "-";
- if ( SecurityService.isAuthenticationEnable( ) && request != null )
- {
- LuteceUser user = SecurityService.getInstance( ).getRegisteredUser( request );
- if ( ( user != null ) && ( user.getRoles( ) != null ) )
- {
- String [ ] roles = user.getRoles( );
- Arrays.sort( roles );
- strRoles = StringUtils.join( roles, ',' );
- }
- }
- StringBuilder sbKey = new StringBuilder( );
- sbKey.append( "[menu:" ).append( nPart ).append( "][m:" ).append( nMode ).append( "][roles:" ).append( strRoles ).append( ']' );
- return sbKey.toString( );
- }
- @Override
- public void processPageEvent( PageEvent event )
- {
- // page was added, removed or updated; clear cache
- resetCache( );
- }
- }