/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.core.resolver.deviceclass;
import java.util.Calendar;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import com.enonic.cms.core.resolver.CacheResolverValueService;
import com.enonic.cms.core.resolver.ForceResolverValueService;
import com.enonic.cms.core.resolver.ForcedResolverValueLifetimeSettings;
import com.enonic.cms.core.resolver.ResolverContext;
import com.enonic.cms.core.resolver.ScriptResolverResult;
import com.enonic.cms.core.resolver.ScriptResolverService;
import com.enonic.cms.core.resource.ResourceFile;
import com.enonic.cms.core.resource.ResourceKey;
import com.enonic.cms.core.resource.ResourceService;
import com.enonic.cms.core.structure.SiteEntity;
import com.enonic.cms.core.structure.SitePropertiesService;
@Component
public class DeviceClassResolverServiceImpl
implements DeviceClassResolverService
{
private ResourceService resourceService;
private SitePropertiesService sitePropertiesService;
public final static String DEVICE_CLASS_FORCED_BASE_NAME = "ForceDeviceClass";
public static final String DEVICE_CLASS_CACHE_BASE_NAME = "DeviceClass";
public static final String DEFAULT_DEVICE_CLASS = "Unknown";
public final static int DEVICE_CLASS_RESOLVER_SCRIPT_NOT_SET_TIMESTAMP = 0;
private ScriptResolverService deviceClassScriptResolver;
private ForceResolverValueService forceResolverValueService;
private CacheResolverValueService cacheResolverValueService;
public String getDeviceClass( ResolverContext context )
{
if ( !deviceClassificationEnabled( context ) )
{
return null;
}
String forcedDeviceClass = resolveForcedDeviceClass( context );
if ( StringUtils.isNotEmpty( forcedDeviceClass ) )
{
return forcedDeviceClass;
}
ResourceFile deviceClassResolverScript = getDeviceClassResolverResourceFile( context.getSite() );
final String isDeviceCachingOn =
sitePropertiesService.getSiteProperties( context.getSite().getKey() ).getProperty( "cms.site.deviceClassification.cache" );
if ( Boolean.parseBoolean( isDeviceCachingOn ) )
{
String cachedDeviceClass = resolveCachedDeviceClass( context, deviceClassResolverScript );
if ( StringUtils.isNotEmpty( cachedDeviceClass ) )
{
return cachedDeviceClass;
}
}
String resolvedDeviceClass = resolveDeviceClassFromScript( context, deviceClassResolverScript );
if ( StringUtils.isEmpty( resolvedDeviceClass ) )
{
return DEFAULT_DEVICE_CLASS;
}
cacheResolverValueService.setCachedResolverValue( context, resolvedDeviceClass,
createDeviceClassCacheKey( context, deviceClassResolverScript ) );
return resolvedDeviceClass;
}
private boolean deviceClassificationEnabled( ResolverContext context )
{
return context.getSite().isDeviceClassificationEnabled();
}
private ResourceFile getDeviceClassResolverResourceFile( SiteEntity site )
{
ResourceKey deviceClassResolverResourceKey = site.getDeviceClassResolver();
if ( deviceClassResolverResourceKey == null )
{
return null;
}
return getResolverScript( deviceClassResolverResourceKey );
}
private String resolveForcedDeviceClass( ResolverContext context )
{
String forcedDeviceClassKey = createForcedDeviceClassKey( context.getSite() );
return forceResolverValueService.getForcedResolverValue( context, forcedDeviceClassKey );
}
private String resolveCachedDeviceClass( ResolverContext context, ResourceFile deviceClassResourceFile )
{
String deviceClassCacheKey = createDeviceClassCacheKey( context, deviceClassResourceFile );
return cacheResolverValueService.getCachedResolverValue( context, deviceClassCacheKey );
}
private String resolveDeviceClassFromScript( ResolverContext context, ResourceFile deviceClassResolverScript )
{
if ( deviceClassResolverScript == null )
{
return null;
}
ScriptResolverResult scriptResolverResult = deviceClassScriptResolver.resolveValue( context, deviceClassResolverScript );
return (String) scriptResolverResult.getResolverReturnValues().get( DeviceClassXsltScriptResolver.DEVICE_CLASS_RETURN_VALUE_KEY );
}
public void setForcedDeviceClass( ResolverContext context, HttpServletResponse response, ForcedResolverValueLifetimeSettings setting,
String deviceClass )
{
resetDeviceClass( context, response );
forceResolverValueService.setForcedValue( context, response, createForcedValueKey( context.getSite() ), setting, deviceClass );
}
private String createForcedDeviceClassKey( SiteEntity site )
{
return DEVICE_CLASS_FORCED_BASE_NAME + site.getKey();
}
private String createDeviceClassCacheKey( ResolverContext context, ResourceFile resourceFile )
{
return createSiteSessionBaseName( context.getSite() ) + getResourceFileTimeStamp( resourceFile );
}
private long getResourceFileTimeStamp( ResourceFile deviceClassResolverScript )
{
Calendar lastModified = null;
if ( deviceClassResolverScript != null )
{
lastModified = deviceClassResolverScript.getLastModified();
}
return lastModified == null ? DEVICE_CLASS_RESOLVER_SCRIPT_NOT_SET_TIMESTAMP : lastModified.getTimeInMillis();
}
protected ResourceFile getResolverScript( ResourceKey resourceKey )
{
return resourceService.getResourceFile( resourceKey );
}
public void resetDeviceClass( ResolverContext context, HttpServletResponse response )
{
forceResolverValueService.clearForcedValue( context, response, createForcedValueKey( context.getSite() ) );
cacheResolverValueService.clearCachedResolverValue( context, createSiteSessionBaseName( context.getSite() ) );
}
private String createSiteSessionBaseName( SiteEntity site )
{
return DEVICE_CLASS_CACHE_BASE_NAME + site.getKey().toInt();
}
protected String createForcedValueKey( SiteEntity site )
{
return DEVICE_CLASS_FORCED_BASE_NAME + site.getKey();
}
@Autowired
@Qualifier("deviceClassXsltScriptResolver")
public void setDeviceClassScriptResolver( ScriptResolverService deviceClassScriptResolver )
{
this.deviceClassScriptResolver = deviceClassScriptResolver;
}
@Autowired
public void setForceResolverValueService( ForceResolverValueService forceResolverValueService )
{
this.forceResolverValueService = forceResolverValueService;
}
@Autowired
public void setCacheResolverValueService( CacheResolverValueService cacheResolverValueService )
{
this.cacheResolverValueService = cacheResolverValueService;
}
@Autowired
public void setResourceService( ResourceService resourceService )
{
this.resourceService = resourceService;
}
@Autowired
public void setSitePropertiesService( SitePropertiesService sitePropertiesService )
{
this.sitePropertiesService = sitePropertiesService;
}
}