/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.core.portal;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import com.google.common.base.Preconditions;
import com.enonic.cms.core.Path;
import com.enonic.cms.core.content.ContentEntity;
import com.enonic.cms.core.content.ContentKey;
import com.enonic.cms.core.content.ContentLocation;
import com.enonic.cms.core.content.ContentLocationSpecification;
import com.enonic.cms.core.content.ContentLocations;
import com.enonic.cms.core.structure.SiteEntity;
import com.enonic.cms.core.structure.SitePath;
import com.enonic.cms.core.structure.menuitem.MenuItemEntity;
import com.enonic.cms.core.structure.menuitem.section.SectionContentEntity;
import com.enonic.cms.store.dao.ContentDao;
/**
* Created by IntelliJ IDEA.
* User: rmh
* Date: Apr 13, 2010
* Time: 1:38:52 PM
*/
public class PageRequestContextResolver
{
private ContentDao contentDao;
private static final int CONTENT_ON_ROOT_PATH_ELEMENTS = 2;
public PageRequestContextResolver( ContentDao contentDao )
{
this.contentDao = contentDao;
}
public PageRequestContext resolvePageRequestContext( final SiteEntity site, final SitePath sitePath )
{
PageRequestContext context = new PageRequestContext();
context.setSitePath( sitePath );
final boolean explicitContentPath = sitePath.hasPathToContent();
if ( explicitContentPath )
{
setPageRequestTypeContextDataForExplicitContentPath( sitePath, site, context );
return context;
}
final Path pathToMenuItem = sitePath.resolvePathToMenuItem();
MenuItemEntity menuItem = site.resolveMenuItemByPath( pathToMenuItem );
if ( menuItem != null )
{
context.setRequestedMenuItem( menuItem );
context.setPageRequestType( PageRequestType.MENUITEM );
return context;
}
// No menuitem with requested path found, this could be a content request
menuItem = resolveParentMenuItem( site, pathToMenuItem );
ContentPath resolvedContentPath;
if ( menuItem != null )
{
String possibleContentName = pathToMenuItem.getLastPathElement();
resolvedContentPath = resolveContentPathForContentWithHome( menuItem, possibleContentName );
}
else
{
menuItem = site.resolveMenuItemByPath( Path.ROOT );
resolvedContentPath = resolveContentPermaLink( pathToMenuItem );
}
if ( resolvedContentPath != null )
{
context.setRequestedMenuItem( menuItem );
context.setResolvedContentPath( resolvedContentPath );
context.setPageRequestType( PageRequestType.CONTENT );
}
return context;
}
private ContentPath resolveContentPathForContentWithHome( MenuItemEntity menuItem, String possibleContentName )
{
ContentEntity matchingContent = searchForContentInSection( possibleContentName, menuItem );
if ( matchingContent != null )
{
return new ContentPath( matchingContent.getKey(), matchingContent.getName(), menuItem.getPath() );
}
return null;
}
private void setPageRequestTypeContextDataForExplicitContentPath( SitePath sitePath, SiteEntity site, PageRequestContext context )
{
Preconditions.checkNotNull( sitePath.getContentPath() );
context.setPageRequestType( PageRequestType.CONTENT );
ContentPath contentPath = sitePath.getContentPath();
ContentEntity content = contentDao.findByKey( contentPath.getContentKey() );
if ( content == null )
{
return;
}
// For old style content paths, serve content if exists no matter what path
if ( contentPath.isOldStyleContentPath() )
{
context.setRequestedMenuItem( resolveContentHome( site, content ) );
context.setResolvedContentPath( contentPath );
return;
}
Path requestedMenuItemPath = contentPath.getPathToMenuItem();
MenuItemEntity requestedMenuItem = site.resolveMenuItemByPath( requestedMenuItemPath );
if ( requestedMenuItem == null )
{
return;
}
ContentLocations contentLocations = getContentLocations( site, content );
// prevent explisit content paths outside locations of content
if ( !contentLocations.hasMenuItemAsLocation( requestedMenuItem ) )
{
return;
}
context.setRequestedMenuItem( requestedMenuItem );
context.setResolvedContentPath( contentPath );
}
private ContentLocations getContentLocations( SiteEntity site, ContentEntity content )
{
ContentLocationSpecification contentLocationSpecification = new ContentLocationSpecification();
contentLocationSpecification.setSiteKey( site.getKey() );
contentLocationSpecification.setIncludeInactiveLocationsInSection( false );
return content.getLocations( contentLocationSpecification );
}
private MenuItemEntity resolveContentHome( SiteEntity site, ContentEntity content )
{
ContentLocations contentLocations = getContentLocations( site, content );
ContentLocation homeLocation = contentLocations.getHomeLocation( site.getKey() );
if ( homeLocation != null )
{
return homeLocation.getMenuItem();
}
MenuItemEntity siteFrontPage = site.getFrontPage();
if ( siteFrontPage != null )
{
return siteFrontPage;
}
return null;
}
private ContentPath resolveContentPermaLink( Path pathToMenuItem )
{
if ( !pathMatchesPermaLinkPattern( pathToMenuItem ) )
{
return null;
}
String contentKeyPathElement = pathToMenuItem.getFirstPathElement();
ContentEntity foundContent = contentDao.findByKey( new ContentKey( contentKeyPathElement ) );
if ( foundContent == null )
{
// verifying if content is deleted is done later in process
return null;
}
String contentNameFromRequest = pathToMenuItem.getLastPathElement();
ContentPath contentPath = new ContentPath( foundContent.getKey(), contentNameFromRequest, Path.ROOT );
contentPath.setPermaLink( true );
return contentPath;
}
private boolean pathMatchesPermaLinkPattern( Path pathToMenuItem )
{
// Pattern for content on root: /<key>/<title>
final boolean correctNumberOfElements = pathToMenuItem.numberOfElements() == CONTENT_ON_ROOT_PATH_ELEMENTS;
if ( !correctNumberOfElements )
{
return false;
}
String firstElement = pathToMenuItem.getFirstPathElement();
if ( !StringUtils.isNumeric( firstElement ) )
{
return false;
}
return true;
}
private MenuItemEntity resolveParentMenuItem( final SiteEntity site, final Path pathToMenuItem )
{
if ( pathToMenuItem.getPathElementsCount() <= 1 )
{
return null;
}
Path parentMenuItemPath = pathToMenuItem.substractLastPathElement();
return site.resolveMenuItemByPath( parentMenuItemPath );
}
private ContentEntity searchForContentInSection( final String contentNameFromRequest, final MenuItemEntity menuItem )
{
Set<SectionContentEntity> sectionContents = menuItem.getSectionContents();
if ( sectionContents != null )
{
for ( SectionContentEntity sectionContent : sectionContents )
{
ContentEntity currentContent = sectionContent.getContent();
if ( currentContent.getName().equalsIgnoreCase( contentNameFromRequest ) )
{
return currentContent;
}
}
}
return null;
}
}