/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.vertical.adminweb.handlers.preview;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import com.enonic.esl.containers.ExtendedMap;
import com.enonic.esl.servlet.http.HttpServletRequestWrapper;
import com.enonic.vertical.adminweb.VerticalAdminException;
import com.enonic.vertical.engine.handlers.MenuHandler;
import com.enonic.cms.core.Attribute;
import com.enonic.cms.core.content.ContentEntity;
import com.enonic.cms.core.content.ContentKey;
import com.enonic.cms.core.language.LanguageEntity;
import com.enonic.cms.core.language.LanguageKey;
import com.enonic.cms.core.language.LanguageResolver;
import com.enonic.cms.core.portal.PageRequestType;
import com.enonic.cms.core.portal.PrettyPathNameCreator;
import com.enonic.cms.core.portal.rendering.PageRenderer;
import com.enonic.cms.core.portal.rendering.PageRendererContext;
import com.enonic.cms.core.portal.rendering.PageRendererFactory;
import com.enonic.cms.core.portal.rendering.RegionsResolver;
import com.enonic.cms.core.portal.rendering.RenderedPageResult;
import com.enonic.cms.core.preview.MenuItemPreviewContext;
import com.enonic.cms.core.preview.PreviewContext;
import com.enonic.cms.core.preview.PreviewService;
import com.enonic.cms.core.resolver.ResolverContext;
import com.enonic.cms.core.resolver.deviceclass.DeviceClassResolverService;
import com.enonic.cms.core.resolver.locale.LocaleResolverService;
import com.enonic.cms.core.security.user.UserEntity;
import com.enonic.cms.core.servlet.ServletRequestAccessor;
import com.enonic.cms.core.structure.RunAsType;
import com.enonic.cms.core.structure.SiteEntity;
import com.enonic.cms.core.structure.SiteKey;
import com.enonic.cms.core.structure.SitePath;
import com.enonic.cms.core.structure.menuitem.MenuItemEntity;
import com.enonic.cms.core.structure.menuitem.MenuItemKey;
import com.enonic.cms.core.structure.menuitem.MenuItemRequestParameter;
import com.enonic.cms.core.structure.menuitem.MenuItemType;
import com.enonic.cms.core.structure.page.PageEntity;
import com.enonic.cms.core.structure.page.PageWindowEntity;
import com.enonic.cms.core.structure.page.PageWindowKey;
import com.enonic.cms.core.structure.page.Regions;
import com.enonic.cms.core.structure.page.template.PageTemplateEntity;
import com.enonic.cms.core.structure.page.template.PageTemplateRegionEntity;
import com.enonic.cms.core.structure.portlet.PortletEntity;
import com.enonic.cms.core.time.TimeService;
import com.enonic.cms.store.dao.ContentDao;
import com.enonic.cms.store.dao.LanguageDao;
import com.enonic.cms.store.dao.MenuItemDao;
import com.enonic.cms.store.dao.PageTemplateDao;
import com.enonic.cms.store.dao.PortletDao;
import com.enonic.cms.store.dao.SiteDao;
public class PreviewPageHandler
{
private static final String FORM_ITEM_DISPLAY_NAME = "displayname";
private static final String FORM_ITEM_MENU_NAME = "menu-name";
private HttpServletRequest httpRequest;
private SiteDao siteDao;
private PortletDao portletDao;
private PageTemplateDao pageTemplateDao;
private MenuItemDao menuItemDao;
private ContentDao contentDao;
private LanguageDao languageDao;
private TimeService timeService;
private LocaleResolverService localeResolverService;
private DeviceClassResolverService deviceClassResolverService;
private PreviewService previewService;
private PageRendererFactory pageRendererFactory;
private ExtendedMap formItems;
private String ticketId;
private UserEntity previewer;
private boolean transliterate;
public RenderedPageResult renderPreview( final SiteKey siteKey, final MenuItemKey parentKey, final MenuItemKey menuItemKey, MenuHandler menuHandler )
{
final MenuItemEntity menuItem = resolveModifiedMenuItem( siteKey, parentKey, menuItemKey );
final PageTemplateEntity pageTemplate = menuItem.getPage().getTemplate();
final Regions regionsInPage = RegionsResolver.resolveRegionsForPageRequest( menuItem, pageTemplate, PageRequestType.MENUITEM );
final SitePath sitePath = new SitePath( menuItem.getSite().getKey(), menuItem.getPath() );
sitePath.addParam( "id", menuItemKey.toString() );
httpRequest.setAttribute( Attribute.ORIGINAL_SITEPATH, sitePath );
httpRequest.setAttribute( Attribute.PREVIEW_ENABLED, "true" );
final HttpServletRequestWrapper wrappedRequest = new HttpServletRequestWrapper( httpRequest );
wrappedRequest.setServletPath( "/site" );
wrappedRequest.setParameter( "id", menuItemKey.toString() );
for ( MenuItemRequestParameter menuItemRequestParameter : menuItem.getRequestParameters().values() )
{
wrappedRequest.setParameter( menuItemRequestParameter.getName(), menuItemRequestParameter.getValue() );
}
ServletRequestAccessor.setRequest( wrappedRequest );
final PreviewContext previewContext = new PreviewContext( new MenuItemPreviewContext( menuItem ) );
previewService.setPreviewContext( previewContext );
final UserEntity runAsUser = resolveRunAsUser( menuItem, menuHandler );
final LanguageEntity language = LanguageResolver.resolve( menuItem.getSite(), menuItem );
final ResolverContext resolverContext = new ResolverContext( wrappedRequest, menuItem.getSite(), menuItem, language );
resolverContext.setUser( previewer );
final Locale locale = localeResolverService.getLocale( resolverContext );
final String deviceClass = deviceClassResolverService.getDeviceClass( resolverContext );
// render page
PageRendererContext pageRendererContext = new PageRendererContext();
pageRendererContext.setDeviceClass( deviceClass );
pageRendererContext.setForceNoCacheUsage( true );
pageRendererContext.setHttpRequest( wrappedRequest );
pageRendererContext.setLanguage( language );
pageRendererContext.setLocale( locale );
pageRendererContext.setMenuItem( menuItem );
pageRendererContext.setOriginalSitePath( sitePath );
pageRendererContext.setPageRequestType( PageRequestType.MENUITEM );
pageRendererContext.setPreviewContext( previewContext );
pageRendererContext.setRegionsInPage( regionsInPage );
pageRendererContext.setRenderer( previewer );
pageRendererContext.setRequestTime( new DateTime() );
pageRendererContext.setRunAsUser( runAsUser );
pageRendererContext.setTicketId( ticketId );
pageRendererContext.setSite( menuItem.getSite() );
pageRendererContext.setSitePath( sitePath );
final PageRenderer renderer = pageRendererFactory.createPageRenderer( pageRendererContext );
return renderer.renderPage( pageTemplate );
}
private MenuItemEntity resolveModifiedMenuItem( final SiteKey siteKey, final MenuItemKey parentKey, final MenuItemKey menuItemKey )
{
final MenuItemEntity persistedMenuItem = menuItemDao.findByKey( menuItemKey );
MenuItemEntity modifiedMenuItem;
if ( persistedMenuItem == null )
{
modifiedMenuItem = new MenuItemEntity();
PageEntity newPage = new PageEntity();
int pageTemplateKey = formItems.getInt( "pagetemplatekey" );
PageTemplateEntity pageTemplate = pageTemplateDao.findByKey( pageTemplateKey );
newPage.setTemplate( pageTemplate );
modifiedMenuItem.setPage( newPage );
SiteEntity site = siteDao.findByKey( siteKey );
modifiedMenuItem.setSite( site );
modifiedMenuItem.setKey( new MenuItemKey( -1 ) );
modifiedMenuItem.setParent( menuItemDao.findByKey( parentKey ) );
}
else
{
modifiedMenuItem = new MenuItemEntity( persistedMenuItem );
}
// create new menu-item with same values and modify with values from request
modifiedMenuItem = modifyMenuItemForPreview( formItems, modifiedMenuItem );
return modifiedMenuItem;
}
private MenuItemEntity modifyMenuItemForPreview( ExtendedMap formItems, MenuItemEntity menuItem )
throws VerticalAdminException
{
menuItem.removeRequestParameters();
if ( isArrayFormItem( formItems, "paramname" ) )
{
// there are multiple parameters
String[] paramNames = (String[]) formItems.get( "paramname" );
String[] paramVals = (String[]) formItems.get( "paramval" );
String[] paramOverrides = (String[]) formItems.get( "paramoverride" );
for ( int i = 0; i < paramNames.length; i++ )
{
String paramName = paramNames[i];
String paramValue = paramVals[i];
if ( paramName.length() == 0 || paramValue.length() == 0 )
{
continue;
}
String paramOverride = paramOverrides[i];
menuItem.addRequestParameter( paramName, paramValue, paramOverride );
}
}
else
{
// there is only one (or zero) parameter
String paramName = formItems.getString( "paramname", null );
String paramVal = formItems.getString( "paramval", null );
String paramOverride = formItems.getString( "paramoverride", null );
if ( paramName != null || paramVal != null )
{
menuItem.addRequestParameter( paramName, paramVal, paramOverride );
}
}
menuItem.setXmlData( menuItem.getMenuDataJDOMDocument() );
// name
String menuItemName = formItems.getString( "name", null ) != null ? formItems.getString( "name" ) : menuItem.getName();
// display-name
String displayName = formItems.getString( FORM_ITEM_DISPLAY_NAME, null );
String menuName = formItems.getString( FORM_ITEM_MENU_NAME, null );
menuItemName = ensureOrGenerateMenuItemName( menuItemName, displayName, menuName );
menuItem.setName( menuItemName );
menuItem.setDisplayName( displayName != null ? formItems.getString( FORM_ITEM_DISPLAY_NAME ) : menuItem.getDisplayName() );
menuItem.setMenuName( menuName != null ? formItems.getString( FORM_ITEM_MENU_NAME ) : menuItem.getMenuName() );
// type
String type = formItems.getString( "type", "" );
MenuItemType menuItemType = null;
if ( type.equals( "form" ) )
{
menuItemType = MenuItemType.CONTENT;
}
else if ( type.equals( "section" ) )
{
menuItemType = MenuItemType.SECTION;
}
else if ( type.equals( "page" ) )
{
menuItemType = MenuItemType.PAGE;
}
else if ( type.equals( "sectionpage" ) )
{
menuItemType = MenuItemType.PAGE;
}
else if ( type.equals( "content" ) )
{
menuItemType = MenuItemType.CONTENT;
}
else if ( type.equals( "newsletter" ) )
{
menuItemType = MenuItemType.PAGE;
}
else if ( type.equals( "label" ) )
{
menuItemType = MenuItemType.LABEL;
}
else if ( type.equals( "shortcut" ) )
{
menuItemType = MenuItemType.SHORTCUT;
}
else if ( "localurl".equals( type ) || "externalurl".equals( type ) )
{
menuItemType = MenuItemType.URL;
}
if ( menuItemType != null )
{
menuItem.setType( menuItemType );
}
// set runAs
String runAs = formItems.getString( "runAs", "" );
RunAsType runAsType = RunAsType.INHERIT;
// automatically treat a form as a page
if ( runAs.equals( "DEFAULT_USER" ) )
{
runAsType = RunAsType.DEFAULT_USER;
}
else if ( runAs.equals( "INHERIT" ) )
{
runAsType = RunAsType.INHERIT;
}
else if ( runAs.equals( "PERSONALIZED" ) )
{
runAsType = RunAsType.PERSONALIZED;
}
menuItem.setRunAs( runAsType );
// set description
menuItem.setDescription(
formItems.getString( "description", null ) != null ? formItems.getString( "description" ) : menuItem.getDescription() );
// set keywords
menuItem.setKeywords(
formItems.getString( "keywords", null ) != null ? formItems.getString( "keywords" ) : menuItem.getKeywords() );
// set language
if ( formItems.getString( "languagekey", null ) != null )
{
String languageKeyStr = formItems.getString( "languagekey" );
LanguageKey languageKey = new LanguageKey( languageKeyStr );
LanguageEntity language = languageDao.findByKey( languageKey );
menuItem.setLanguage( language );
}
// set visibility:
if ( "on".equals( formItems.getString( "visibility", null ) ) )
{
menuItem.setHidden( false );
}
else
{
menuItem.setHidden( true );
}
// timestamp
menuItem.setTimestamp( timeService.getNowAsDateTime().toDate() );
// content
if ( formItems.containsKey( "_selected_content" ) && menuItem.getRequestParameterValue( "key" ) == null )
{
int contentKey = formItems.getInt( "_selected_content" );
ContentEntity contentEntity = contentDao.findByKey( new ContentKey( contentKey ) );
menuItem.setContent( contentEntity );
}
else if ( menuItem.getRequestParameterValue( "key" ) != null )
{
int contentKey = Integer.valueOf( menuItem.getRequestParameterValue( "key" ) );
ContentEntity contentEntity = contentDao.findByKey( new ContentKey( contentKey ) );
menuItem.setContent( contentEntity );
}
//page windows
if ( menuItem.getPage() != null )
{
PageEntity modifiedPage = new PageEntity( menuItem.getPage() );
menuItem.setPage( modifiedPage );
modifiedPage.removeAllPortletPlacements();
PageTemplateEntity pageTemplate = modifiedPage.getTemplate();
Set<PageTemplateRegionEntity> pageTemplateRegions = pageTemplate.getPageTemplateRegions();
for ( PageTemplateRegionEntity pageTemplateRegion : pageTemplateRegions )
{
String[] portletKeys = formItems.getStringArray( pageTemplateRegion.getName() + "_portlet" );
if ( portletKeys.length > 0 )
{
for ( String portletKeyStr : portletKeys )
{
if ( StringUtils.isBlank( portletKeyStr ) )
{
continue;
}
PortletEntity portlet = portletDao.findByKey( Integer.valueOf( portletKeyStr ) );
PageWindowEntity pageWindow = new PageWindowEntity();
pageWindow.setKey( new PageWindowKey( modifiedPage.getKey(), portlet.getKey() ) );
pageWindow.setPage( modifiedPage );
pageWindow.setPageTemplateRegion( pageTemplateRegion );
pageWindow.setTimestamp( timeService.getNowAsDateTime().toDate() );
pageWindow.setPortlet( portlet );
modifiedPage.addPortletPlacement( pageWindow );
}
}
}
}
return menuItem;
}
private String ensureOrGenerateMenuItemName( String menuItemName, String displayName, String menuName )
{
// Generate name for preview if none given
if ( StringUtils.isEmpty( menuItemName ) )
{
String suggestedName = menuName;
if ( StringUtils.isEmpty( suggestedName ) )
{
suggestedName = displayName;
}
menuItemName = new PrettyPathNameCreator( transliterate ).generatePrettyPathName( suggestedName );
}
return menuItemName;
}
private UserEntity resolveRunAsUser( final MenuItemEntity modifiedMenuItem, MenuHandler menuHandler )
{
UserEntity runAsUser = modifiedMenuItem.resolveRunAsUser( previewer, true, menuHandler );
if ( runAsUser == null )
{
runAsUser = previewer;
}
return runAsUser;
}
private static boolean isArrayFormItem( Map formItems, String string )
{
if ( !formItems.containsKey( string ) )
{
return false;
}
if ( formItems.get( string ) == null )
{
return false;
}
return formItems.get( string ).getClass() == String[].class;
}
public void setPreviewService( final PreviewService previewService )
{
this.previewService = previewService;
}
public void setTicketId( final String ticketId )
{
this.ticketId = ticketId;
}
public void setHttpRequest( final HttpServletRequest httpRequest )
{
this.httpRequest = httpRequest;
}
public void setContentDao( final ContentDao contentDao )
{
this.contentDao = contentDao;
}
public void setTimeService( final TimeService timeService )
{
this.timeService = timeService;
}
public void setLocaleResolverService( final LocaleResolverService localeResolverService )
{
this.localeResolverService = localeResolverService;
}
public void setDeviceClassResolverService( final DeviceClassResolverService deviceClassResolverService )
{
this.deviceClassResolverService = deviceClassResolverService;
}
public void setPageRendererFactory( final PageRendererFactory pageRendererFactory )
{
this.pageRendererFactory = pageRendererFactory;
}
public void setFormItems( final ExtendedMap formItems )
{
this.formItems = formItems;
}
public void setMenuItemDao( final MenuItemDao menuItemDao )
{
this.menuItemDao = menuItemDao;
}
public void setPortletDao( final PortletDao portletDao )
{
this.portletDao = portletDao;
}
public void setSiteDao( final SiteDao siteDao )
{
this.siteDao = siteDao;
}
public void setPageTemplateDao( final PageTemplateDao pageTemplateDao )
{
this.pageTemplateDao = pageTemplateDao;
}
public void setLanguageDao( final LanguageDao languageDao )
{
this.languageDao = languageDao;
}
public void setPreviewer( final UserEntity previewer )
{
this.previewer = previewer;
}
public void setTransliterate( final boolean transliterate )
{
this.transliterate = transliterate;
}
}