/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the License at the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apereo.portal.layout;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils;
import org.apereo.portal.IUserPreferencesManager;
import org.apereo.portal.IUserProfile;
import org.apereo.portal.layout.dao.IStylesheetDescriptorDao;
import org.apereo.portal.layout.dao.IStylesheetUserPreferencesDao;
import org.apereo.portal.layout.om.ILayoutAttributeDescriptor;
import org.apereo.portal.layout.om.IOutputPropertyDescriptor;
import org.apereo.portal.layout.om.IStylesheetData;
import org.apereo.portal.layout.om.IStylesheetData.Scope;
import org.apereo.portal.layout.om.IStylesheetDescriptor;
import org.apereo.portal.layout.om.IStylesheetParameterDescriptor;
import org.apereo.portal.layout.om.IStylesheetUserPreferences;
import org.apereo.portal.security.IPerson;
import org.apereo.portal.user.IUserInstance;
import org.apereo.portal.user.IUserInstanceManager;
import org.apereo.portal.utils.IFragmentDefinitionUtils;
import org.apereo.portal.utils.Populator;
import org.apereo.portal.utils.web.PortalWebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.util.WebUtils;
/**
* Handles retrieving and storing the various scopes of stylesheet user preference data.
*
*/
@Service
public class StylesheetUserPreferencesServiceImpl implements IStylesheetUserPreferencesService {
private static final String OUTPUT_PROPERTIES_KEY =
StylesheetUserPreferencesServiceImpl.class.getName() + ".OUTPUT_PROPERTIES";
private static final String STYLESHEET_PARAMETERS_KEY =
StylesheetUserPreferencesServiceImpl.class.getName() + ".STYLESHEET_PARAMETERS";
private static final String LAYOUT_ATTRIBUTES_KEY =
StylesheetUserPreferencesServiceImpl.class.getName() + ".LAYOUT_ATTRIBUTES";
public static final String STYLESHEET_STRUCTURE_OVERRIDE_REQUEST_ATTRIBUTE =
StylesheetUserPreferencesServiceImpl.class.getCanonicalName()
+ ".STYLESHEET_STRUCTURE_NAME";
public static final String STYLESHEET_THEME_OVERRIDE_REQUEST_ATTRIBUTE_NAME =
StylesheetUserPreferencesServiceImpl.class.getCanonicalName()
+ ".STYLESHEET_THEME_NAME";
protected final Logger logger = LoggerFactory.getLogger(getClass());
private IFragmentDefinitionUtils fragmentUtils;
private IUserInstanceManager userInstanceManager;
private IStylesheetDescriptorDao stylesheetDescriptorDao;
private IStylesheetUserPreferencesDao stylesheetUserPreferencesDao;
@Autowired
public void setUserInstanceManager(IUserInstanceManager userInstanceManager) {
this.userInstanceManager = userInstanceManager;
}
@Autowired
public void setStylesheetDescriptorDao(IStylesheetDescriptorDao stylesheetDescriptorDao) {
this.stylesheetDescriptorDao = stylesheetDescriptorDao;
}
@Autowired
public void setStylesheetUserPreferencesDao(
IStylesheetUserPreferencesDao stylesheetUserPreferencesDao) {
this.stylesheetUserPreferencesDao = stylesheetUserPreferencesDao;
}
@Autowired
public void setFragmentDefinitionUtils(final IFragmentDefinitionUtils utils) {
this.fragmentUtils = utils;
}
protected static final class StylesheetPreferencesKey {
private final IPerson person;
private final IUserProfile userProfile;
private final IStylesheetDescriptor stylesheetDescriptor;
private final String str;
private StylesheetPreferencesKey(
IPerson person,
IUserProfile userProfile,
IStylesheetDescriptor stylesheetDescriptor) {
this.person = person;
this.userProfile = userProfile;
this.stylesheetDescriptor = stylesheetDescriptor;
this.str =
"["
+ stylesheetDescriptor.getId()
+ ","
+ person.getUserName()
+ ","
+ userProfile.getProfileId()
+ "]";
}
public String toString() {
return this.str;
}
}
protected final StylesheetPreferencesKey getStylesheetPreferencesKey(
HttpServletRequest request, PreferencesScope prefScope) {
final IUserInstance userInstance = this.userInstanceManager.getUserInstance(request);
final IPerson person = userInstance.getPerson();
final IUserPreferencesManager preferencesManager = userInstance.getPreferencesManager();
final IUserProfile userProfile = preferencesManager.getUserProfile();
final IStylesheetDescriptor stylesheetDescriptor =
getStylesheetDescriptor(request, prefScope);
return new StylesheetPreferencesKey(person, userProfile, stylesheetDescriptor);
}
protected final IStylesheetUserPreferences getDistributedStylesheetUserPreferences(
HttpServletRequest request, PreferencesScope prefScope) {
final IUserInstance userInstance = this.userInstanceManager.getUserInstance(request);
final IUserPreferencesManager preferencesManager = userInstance.getPreferencesManager();
final IUserLayoutManager userLayoutManager = preferencesManager.getUserLayoutManager();
final IUserLayout userLayout = userLayoutManager.getUserLayout();
return prefScope.getDistributedIStylesheetUserPreferences(userLayout);
}
protected final Scope getWriteScope(
HttpServletRequest request,
PreferencesScope prefScope,
StylesheetPreferencesKey stylesheetPreferencesKey,
IStylesheetData descriptor) {
final Scope scope = descriptor.getScope();
final boolean persistentScopeReadOnly = stylesheetPreferencesKey.person.isGuest();
if (persistentScopeReadOnly && Scope.PERSISTENT == scope) {
return Scope.SESSION;
}
return scope;
}
protected final boolean compareValues(String value, String defaultValue) {
return value == defaultValue || (value != null && value.equals(defaultValue));
}
protected final <T> T getDataValue(
HttpServletRequest request,
StylesheetPreferencesKey stylesheetPreferencesKey,
Scope scope,
String mapKey,
String name) {
switch (scope) {
case SESSION:
{
final HttpSession session = request.getSession(false);
if (session == null) {
return null;
}
final Map<String, T> outputProperties =
PortalWebUtils.getMapSessionAttribute(
session, mapKey + stylesheetPreferencesKey.toString(), false);
if (outputProperties == null) {
return null;
}
return outputProperties.get(name);
}
case REQUEST:
{
final Map<String, T> outputProperties =
PortalWebUtils.getMapRequestAttribute(
request, mapKey + stylesheetPreferencesKey.toString(), false);
if (outputProperties == null) {
return null;
}
return outputProperties.get(name);
}
default:
{
return null;
}
}
}
protected final <T> T putDataValue(
HttpServletRequest request,
StylesheetPreferencesKey stylesheetPreferencesKey,
Scope scope,
String mapKey,
String name,
T value) {
switch (scope) {
case SESSION:
{
final HttpSession session = request.getSession();
final Map<String, T> outputProperties =
PortalWebUtils.getMapSessionAttribute(
session, mapKey + stylesheetPreferencesKey.toString());
return outputProperties.put(name, value);
}
case REQUEST:
{
final Map<String, T> outputProperties =
PortalWebUtils.getMapRequestAttribute(
request, mapKey + stylesheetPreferencesKey.toString());
return outputProperties.put(name, value);
}
default:
{
return null;
}
}
}
protected final <T> T removeDataValue(
HttpServletRequest request,
StylesheetPreferencesKey stylesheetPreferencesKey,
Scope scope,
String mapKey,
String name) {
switch (scope) {
case SESSION:
{
final HttpSession session = request.getSession(false);
if (session == null) {
return null;
}
final Map<String, T> outputProperties =
PortalWebUtils.getMapSessionAttribute(
session, mapKey + stylesheetPreferencesKey.toString(), false);
if (outputProperties == null) {
return null;
}
return outputProperties.remove(name);
}
case REQUEST:
{
final Map<String, T> outputProperties =
PortalWebUtils.getMapRequestAttribute(
request, mapKey + stylesheetPreferencesKey.toString(), false);
if (outputProperties == null) {
return null;
}
return outputProperties.remove(name);
}
default:
{
return null;
}
}
}
@Override
public IStylesheetDescriptor getStylesheetDescriptor(
HttpServletRequest request, PreferencesScope prefScope) {
String stylesheetName = this.getStyleSheetName(request, prefScope);
if (!StringUtils.isBlank(stylesheetName)) {
return this.stylesheetDescriptorDao.getStylesheetDescriptorByName(stylesheetName);
} else {
final IUserInstance userInstance = this.userInstanceManager.getUserInstance(request);
final IUserPreferencesManager preferencesManager = userInstance.getPreferencesManager();
final IUserProfile userProfile = preferencesManager.getUserProfile();
final int stylesheetId = prefScope.getStylesheetId(userProfile);
return this.stylesheetDescriptorDao.getStylesheetDescriptor(stylesheetId);
}
}
@Transactional
@Override
public String removeOutputProperty(
HttpServletRequest request, PreferencesScope prefScope, String name) {
final StylesheetPreferencesKey stylesheetPreferencesKey =
this.getStylesheetPreferencesKey(request, prefScope);
final IStylesheetDescriptor stylesheetDescriptor =
stylesheetPreferencesKey.stylesheetDescriptor;
final IOutputPropertyDescriptor outputPropertyDescriptor =
stylesheetDescriptor.getOutputPropertyDescriptor(name);
if (outputPropertyDescriptor == null) {
logger.warn(
"Attempted to remove output property '{}' but no such output property is defined in stylesheet descriptor '{}'. It will be ignored",
new Object[] {name, stylesheetDescriptor.getName()});
return null;
}
final Scope scope =
this.getWriteScope(
request, prefScope, stylesheetPreferencesKey, outputPropertyDescriptor);
switch (scope) {
case PERSISTENT:
{
final IStylesheetUserPreferences stylesheetUserPreferences =
this.getStylesheetUserPreferences(request, stylesheetPreferencesKey);
if (stylesheetUserPreferences == null) {
return null;
}
final String oldValue = stylesheetUserPreferences.removeOutputProperty(name);
this.stylesheetUserPreferencesDao.storeStylesheetUserPreferences(
stylesheetUserPreferences);
this.clearStylesheetUserPreferencesCache(request, stylesheetPreferencesKey);
return oldValue;
}
default:
{
return removeDataValue(
request, stylesheetPreferencesKey, scope, OUTPUT_PROPERTIES_KEY, name);
}
}
}
@Override
public <P extends Populator<String, String>> P populateOutputProperties(
HttpServletRequest request, PreferencesScope prefScope, P properties) {
final StylesheetPreferencesKey stylesheetPreferencesKey =
this.getStylesheetPreferencesKey(request, prefScope);
final IStylesheetDescriptor stylesheetDescriptor =
stylesheetPreferencesKey.stylesheetDescriptor;
//Get the scoped sources once
final IStylesheetUserPreferences stylesheetUserPreferences =
this.getStylesheetUserPreferences(request, stylesheetPreferencesKey);
final Map<String, String> sessionOutputProperties;
final HttpSession session = request.getSession(false);
if (session == null) {
sessionOutputProperties = null;
} else {
sessionOutputProperties =
PortalWebUtils.getMapSessionAttribute(
session,
OUTPUT_PROPERTIES_KEY + stylesheetPreferencesKey.toString(),
false);
}
final Map<String, String> requestOutputProperties =
PortalWebUtils.getMapRequestAttribute(
request,
OUTPUT_PROPERTIES_KEY + stylesheetPreferencesKey.toString(),
false);
//Try getting each output property to populate the Properties
for (final IOutputPropertyDescriptor outputPropertyDescriptor :
stylesheetDescriptor.getOutputPropertyDescriptors()) {
final String name = outputPropertyDescriptor.getName();
final String value;
final Scope scope = outputPropertyDescriptor.getScope();
switch (scope) {
case PERSISTENT:
{
if (stylesheetUserPreferences == null) {
value = null;
break;
}
value = stylesheetUserPreferences.getOutputProperty(name);
break;
}
case SESSION:
{
if (sessionOutputProperties == null) {
value = null;
break;
}
value = sessionOutputProperties.get(name);
break;
}
case REQUEST:
{
if (requestOutputProperties == null) {
value = null;
break;
}
value = requestOutputProperties.get(name);
break;
}
default:
{
value = null;
break;
}
}
//Don't add unset properties
if (value == null) {
continue;
}
//If the value is equal to the default value remove the property and return null
if (this.compareValues(value, outputPropertyDescriptor.getDefaultValue())) {
this.removeOutputProperty(request, prefScope, name);
continue;
}
properties.put(name, value);
}
return properties;
}
@Override
public String getStylesheetParameter(
HttpServletRequest request, PreferencesScope prefScope, String name) {
final StylesheetPreferencesKey stylesheetPreferencesKey =
this.getStylesheetPreferencesKey(request, prefScope);
final IStylesheetDescriptor stylesheetDescriptor =
stylesheetPreferencesKey.stylesheetDescriptor;
final IStylesheetParameterDescriptor stylesheetParameterDescriptor =
stylesheetDescriptor.getStylesheetParameterDescriptor(name);
if (stylesheetParameterDescriptor == null) {
logger.warn(
"Attempted to get stylesheet parameter '{}' but no such stylesheet parameter is defined in stylesheet descriptor '{}'. null will be returned",
new Object[] {name, stylesheetDescriptor.getName()});
return null;
}
final String value;
final Scope scope = stylesheetParameterDescriptor.getScope();
switch (scope) {
case PERSISTENT:
{
final IStylesheetUserPreferences stylesheetUserPreferences =
this.getStylesheetUserPreferences(request, stylesheetPreferencesKey);
if (stylesheetUserPreferences == null) {
return null;
}
value = stylesheetUserPreferences.getStylesheetParameter(name);
break;
}
default:
{
value =
this.getDataValue(
request,
stylesheetPreferencesKey,
scope,
STYLESHEET_PARAMETERS_KEY,
name);
break;
}
}
if (value == null) {
return null;
}
//If the value is equal to the default value remove the property and return null
if (this.compareValues(value, stylesheetParameterDescriptor.getDefaultValue())) {
this.removeStylesheetParameter(request, prefScope, name);
return null;
}
return value;
}
@Transactional
@Override
public String setStylesheetParameter(
HttpServletRequest request, PreferencesScope prefScope, String name, String value) {
logger.trace(
"Setting stylesheet parameter {} with scope {} to {}.", name, prefScope, value);
final StylesheetPreferencesKey stylesheetPreferencesKey =
this.getStylesheetPreferencesKey(request, prefScope);
final IStylesheetDescriptor stylesheetDescriptor =
stylesheetPreferencesKey.stylesheetDescriptor;
final IStylesheetParameterDescriptor stylesheetParameterDescriptor =
stylesheetDescriptor.getStylesheetParameterDescriptor(name);
if (stylesheetParameterDescriptor == null) {
logger.warn(
"Attempted to set stylesheet parameter {}={} but no such stylesheet parameter is defined in stylesheet descriptor {}. It will be ignored",
new Object[] {name, value, stylesheetDescriptor.getName()});
return null;
}
if (this.compareValues(value, stylesheetParameterDescriptor.getDefaultValue())) {
return this.removeStylesheetParameter(request, prefScope, name);
}
final Scope scope =
this.getWriteScope(
request,
prefScope,
stylesheetPreferencesKey,
stylesheetParameterDescriptor);
switch (scope) {
case PERSISTENT:
{
IStylesheetUserPreferences stylesheetUserPreferences =
this.getStylesheetUserPreferences(request, stylesheetPreferencesKey);
if (stylesheetUserPreferences == null) {
stylesheetUserPreferences =
this.stylesheetUserPreferencesDao.createStylesheetUserPreferences(
stylesheetDescriptor,
stylesheetPreferencesKey.person,
stylesheetPreferencesKey.userProfile);
this.clearStylesheetUserPreferencesCache(request, stylesheetPreferencesKey);
}
final String oldValue =
stylesheetUserPreferences.setStylesheetParameter(name, value);
this.stylesheetUserPreferencesDao.storeStylesheetUserPreferences(
stylesheetUserPreferences);
return oldValue;
}
default:
{
return this.putDataValue(
request,
stylesheetPreferencesKey,
scope,
STYLESHEET_PARAMETERS_KEY,
name,
value);
}
}
}
@Transactional
@Override
public String removeStylesheetParameter(
HttpServletRequest request, PreferencesScope prefScope, String name) {
final StylesheetPreferencesKey stylesheetPreferencesKey =
this.getStylesheetPreferencesKey(request, prefScope);
final IStylesheetDescriptor stylesheetDescriptor =
stylesheetPreferencesKey.stylesheetDescriptor;
final IStylesheetParameterDescriptor stylesheetParameterDescriptor =
stylesheetDescriptor.getStylesheetParameterDescriptor(name);
if (stylesheetParameterDescriptor == null) {
logger.warn(
"Attempted to remove stylesheet parameter {} but no such stylesheet parameter is defined in stylesheet descriptor {}. It will be ignored",
new Object[] {name, stylesheetDescriptor.getName()});
return null;
}
final Scope scope =
this.getWriteScope(
request,
prefScope,
stylesheetPreferencesKey,
stylesheetParameterDescriptor);
switch (scope) {
case PERSISTENT:
{
final IStylesheetUserPreferences stylesheetUserPreferences =
this.getStylesheetUserPreferences(request, stylesheetPreferencesKey);
if (stylesheetUserPreferences == null) {
return null;
}
final String oldValue =
stylesheetUserPreferences.removeStylesheetParameter(name);
this.stylesheetUserPreferencesDao.storeStylesheetUserPreferences(
stylesheetUserPreferences);
return oldValue;
}
default:
{
return removeDataValue(
request,
stylesheetPreferencesKey,
scope,
STYLESHEET_PARAMETERS_KEY,
name);
}
}
}
@Override
public <P extends Populator<String, String>> P populateStylesheetParameters(
HttpServletRequest request, PreferencesScope prefScope, P stylesheetParameters) {
final StylesheetPreferencesKey stylesheetPreferencesKey =
this.getStylesheetPreferencesKey(request, prefScope);
final IStylesheetDescriptor stylesheetDescriptor =
stylesheetPreferencesKey.stylesheetDescriptor;
//Get the scoped sources once
final IStylesheetUserPreferences stylesheetUserPreferences =
this.getStylesheetUserPreferences(request, stylesheetPreferencesKey);
final Map<String, String> sessionStylesheetParameters;
final HttpSession session = request.getSession(false);
if (session == null) {
sessionStylesheetParameters = null;
} else {
sessionStylesheetParameters =
PortalWebUtils.getMapSessionAttribute(
session,
STYLESHEET_PARAMETERS_KEY + stylesheetPreferencesKey.toString(),
false);
}
final Map<String, String> requestStylesheetParameters =
PortalWebUtils.getMapRequestAttribute(
request,
STYLESHEET_PARAMETERS_KEY + stylesheetPreferencesKey.toString(),
false);
//Try getting each stylesheet parameter to populate the Map
for (final IStylesheetParameterDescriptor stylesheetParameterDescriptor :
stylesheetDescriptor.getStylesheetParameterDescriptors()) {
final String name = stylesheetParameterDescriptor.getName();
final String value;
final Scope scope = stylesheetParameterDescriptor.getScope();
switch (scope) {
case PERSISTENT:
{
if (stylesheetUserPreferences == null) {
value = null;
break;
}
value = stylesheetUserPreferences.getStylesheetParameter(name);
break;
}
case SESSION:
{
if (sessionStylesheetParameters == null) {
value = null;
break;
}
value = sessionStylesheetParameters.get(name);
break;
}
case REQUEST:
{
if (requestStylesheetParameters == null) {
value = null;
break;
}
value = requestStylesheetParameters.get(name);
break;
}
default:
{
value = null;
break;
}
}
//Don't add unset properties
if (value == null) {
continue;
}
//If the value is equal to the default value remove the property and return null
if (this.compareValues(value, stylesheetParameterDescriptor.getDefaultValue())) {
this.removeStylesheetParameter(request, prefScope, name);
continue;
}
stylesheetParameters.put(name, value);
}
return stylesheetParameters;
}
@Override
public String getLayoutAttribute(
HttpServletRequest request, PreferencesScope prefScope, String nodeId, String name) {
final StylesheetPreferencesKey stylesheetPreferencesKey =
this.getStylesheetPreferencesKey(request, prefScope);
final IStylesheetDescriptor stylesheetDescriptor =
stylesheetPreferencesKey.stylesheetDescriptor;
final ILayoutAttributeDescriptor layoutAttributeDescriptor =
stylesheetDescriptor.getLayoutAttributeDescriptor(name);
if (layoutAttributeDescriptor == null) {
logger.warn(
"Attempted to get layout attribute {} for ID=\"{}\" but no such stylesheet parameter is defined in stylesheet descriptor {}. Null will be returned",
new Object[] {name, nodeId, stylesheetDescriptor.getName()});
return null;
}
//Load the default value
String defaultValue = null;
final IStylesheetUserPreferences distributedStylesheetUserPreferences =
this.getDistributedStylesheetUserPreferences(request, prefScope);
if (distributedStylesheetUserPreferences != null) {
defaultValue = distributedStylesheetUserPreferences.getLayoutAttribute(nodeId, name);
// special handling for fragment owner
if (this.isFragmentOwnerStylesheetPreferencesKey(stylesheetPreferencesKey)) {
return defaultValue;
}
if (this.compareValues(defaultValue, layoutAttributeDescriptor.getDefaultValue())) {
//DLM attribute value matches the stylesheet descriptor default, remove the DLM value
distributedStylesheetUserPreferences.removeLayoutAttribute(nodeId, name);
defaultValue = null;
}
}
final String value;
final Scope scope = layoutAttributeDescriptor.getScope();
switch (scope) {
case PERSISTENT:
{
final IStylesheetUserPreferences stylesheetUserPreferences =
this.getStylesheetUserPreferences(request, stylesheetPreferencesKey);
if (stylesheetUserPreferences == null) {
value = null;
break;
}
value = stylesheetUserPreferences.getLayoutAttribute(nodeId, name);
break;
}
default:
{
final Map<String, String> nodeAttributes =
this.getDataValue(
request,
stylesheetPreferencesKey,
scope,
LAYOUT_ATTRIBUTES_KEY,
nodeId);
if (nodeAttributes == null) {
value = null;
break;
}
value = nodeAttributes.get(name);
break;
}
}
if (value == null) {
return defaultValue;
}
if (!this.isFragmentOwnerStylesheetPreferencesKey(stylesheetPreferencesKey)) {
if (this.compareValues(value, layoutAttributeDescriptor.getDefaultValue())
|| //Value is equal to stylesheet descriptor default
(defaultValue != null
&& this.compareValues(
value,
defaultValue))) { //Value is equal to DLM stylesheet preferences default
//Remove the user's customized value
this.removeLayoutAttribute(request, prefScope, nodeId, name);
return null;
}
}
return value;
}
private static final String NO_PERSISTENT_IStylesheetUserPreferences =
StylesheetUserPreferencesServiceImpl.class.getName()
+ ".NO_PERSISTENT_IStylesheetUserPreferences";
private String getCacheKey(StylesheetPreferencesKey stylesheetPreferencesKey) {
return NO_PERSISTENT_IStylesheetUserPreferences + "." + stylesheetPreferencesKey.toString();
}
private IStylesheetUserPreferences getStylesheetUserPreferences(
HttpServletRequest request, StylesheetPreferencesKey stylesheetPreferencesKey) {
final String key = getCacheKey(stylesheetPreferencesKey);
if (request.getAttribute(key) != null) {
return null;
}
final HttpSession session = request.getSession();
if (session.getAttribute(key) != null) {
request.setAttribute(key, Boolean.TRUE);
return null;
}
final IStylesheetUserPreferences stylesheetUserPreferences =
this.stylesheetUserPreferencesDao.getStylesheetUserPreferences(
stylesheetPreferencesKey.stylesheetDescriptor,
stylesheetPreferencesKey.person,
stylesheetPreferencesKey.userProfile);
if (stylesheetUserPreferences == null) {
session.setAttribute(key, Boolean.TRUE);
request.setAttribute(key, Boolean.TRUE);
}
return stylesheetUserPreferences;
}
private void clearStylesheetUserPreferencesCache(
HttpServletRequest request, StylesheetPreferencesKey stylesheetPreferencesKey) {
final String key = getCacheKey(stylesheetPreferencesKey);
request.removeAttribute(key);
final HttpSession session = request.getSession();
session.removeAttribute(key);
}
/** @return Map<nodeId, Map<name, value>> */
protected ConcurrentMap<String, Map<String, String>> getRequestLayoutAttributes(
HttpServletRequest request, StylesheetPreferencesKey stylesheetPreferencesKey) {
return PortalWebUtils.getMapRequestAttribute(
request, LAYOUT_ATTRIBUTES_KEY + stylesheetPreferencesKey.toString(), false);
}
/** @return Map<nodeId, Map<name, value>> */
protected ConcurrentMap<String, Map<String, String>> getSessionLayoutAttributes(
HttpSession session, StylesheetPreferencesKey stylesheetPreferencesKey) {
return PortalWebUtils.getMapSessionAttribute(
session, LAYOUT_ATTRIBUTES_KEY + stylesheetPreferencesKey.toString(), false);
}
@Transactional
@Override
public String setLayoutAttribute(
HttpServletRequest request,
PreferencesScope prefScope,
String nodeId,
String name,
String value) {
final StylesheetPreferencesKey stylesheetPreferencesKey =
this.getStylesheetPreferencesKey(request, prefScope);
final IStylesheetDescriptor stylesheetDescriptor =
stylesheetPreferencesKey.stylesheetDescriptor;
final ILayoutAttributeDescriptor layoutAttributeDescriptor =
stylesheetDescriptor.getLayoutAttributeDescriptor(name);
if (layoutAttributeDescriptor == null) {
logger.warn(
"Attempted to set layout attribute {}={} on node with ID=\"{}\" but no such stylesheet parameter is defined in stylesheet descriptor {}. It will be ignored.",
new Object[] {name, value, nodeId, stylesheetDescriptor.getName()});
return null;
}
if (this.compareValues(value, layoutAttributeDescriptor.getDefaultValue())) {
//Value matches the default value, remove the attribute
return this.removeLayoutAttribute(request, prefScope, nodeId, name);
}
final IStylesheetUserPreferences distributedStylesheetUserPreferences =
this.getDistributedStylesheetUserPreferences(request, prefScope);
if (distributedStylesheetUserPreferences != null) {
final String defaultValue =
distributedStylesheetUserPreferences.getLayoutAttribute(nodeId, name);
if (this.compareValues(value, defaultValue)) {
//Value matches the DLM preferences value, remove the value
return this.removeLayoutAttribute(request, prefScope, nodeId, name);
}
}
final Scope scope =
this.getWriteScope(
request, prefScope, stylesheetPreferencesKey, layoutAttributeDescriptor);
switch (scope) {
case PERSISTENT:
{
IStylesheetUserPreferences stylesheetUserPreferences =
this.getStylesheetUserPreferences(request, stylesheetPreferencesKey);
if (stylesheetUserPreferences == null) {
stylesheetUserPreferences =
this.stylesheetUserPreferencesDao.createStylesheetUserPreferences(
stylesheetDescriptor,
stylesheetPreferencesKey.person,
stylesheetPreferencesKey.userProfile);
this.clearStylesheetUserPreferencesCache(request, stylesheetPreferencesKey);
}
final String oldValue =
stylesheetUserPreferences.setLayoutAttribute(nodeId, name, value);
this.stylesheetUserPreferencesDao.storeStylesheetUserPreferences(
stylesheetUserPreferences);
return oldValue;
}
default:
{
//Determine the mutex to use for accessing the nodeAttributes map
final Object mutex;
switch (scope) {
case REQUEST:
{
mutex = PortalWebUtils.getRequestAttributeMutex(request);
break;
}
case SESSION:
{
final HttpSession session = request.getSession();
mutex = WebUtils.getSessionMutex(session);
break;
}
default:
{
mutex = new Object();
break;
}
}
//Get/Create the nodeAttributes map
Map<String, String> nodeAttributes;
synchronized (mutex) {
nodeAttributes =
this.getDataValue(
request,
stylesheetPreferencesKey,
scope,
LAYOUT_ATTRIBUTES_KEY,
nodeId);
if (nodeAttributes == null) {
nodeAttributes = new ConcurrentHashMap<String, String>();
this.putDataValue(
request,
stylesheetPreferencesKey,
scope,
LAYOUT_ATTRIBUTES_KEY,
nodeId,
nodeAttributes);
}
}
return nodeAttributes.put(name, value);
}
}
}
@Transactional
@Override
public String removeLayoutAttribute(
HttpServletRequest request, PreferencesScope prefScope, String nodeId, String name) {
final StylesheetPreferencesKey stylesheetPreferencesKey =
this.getStylesheetPreferencesKey(request, prefScope);
final IStylesheetDescriptor stylesheetDescriptor =
stylesheetPreferencesKey.stylesheetDescriptor;
final ILayoutAttributeDescriptor layoutAttributeDescriptor =
stylesheetDescriptor.getLayoutAttributeDescriptor(name);
if (layoutAttributeDescriptor == null) {
logger.warn(
"Attempted to remove layout attribute {} for ID=\"{}\" but no such stylesheet parameter is defined in stylesheet descriptor {}. It will be ignored.",
new Object[] {name, nodeId, stylesheetDescriptor.getName()});
return null;
}
final Scope scope =
this.getWriteScope(
request, prefScope, stylesheetPreferencesKey, layoutAttributeDescriptor);
switch (scope) {
case PERSISTENT:
{
final IStylesheetUserPreferences stylesheetUserPreferences =
this.getStylesheetUserPreferences(request, stylesheetPreferencesKey);
if (stylesheetUserPreferences == null) {
break;
}
final String oldValue =
stylesheetUserPreferences.removeLayoutAttribute(nodeId, name);
if (oldValue != null) {
this.stylesheetUserPreferencesDao.storeStylesheetUserPreferences(
stylesheetUserPreferences);
return oldValue;
}
}
default:
{
final Map<String, String> nodeAttributes =
this.getDataValue(
request,
stylesheetPreferencesKey,
scope,
LAYOUT_ATTRIBUTES_KEY,
nodeId);
if (nodeAttributes == null) {
break;
}
final String oldValue = nodeAttributes.remove(name);
if (oldValue != null) {
return oldValue;
}
}
}
final IStylesheetUserPreferences distributedStylesheetUserPreferences =
this.getDistributedStylesheetUserPreferences(request, prefScope);
if (distributedStylesheetUserPreferences != null) {
return distributedStylesheetUserPreferences.removeLayoutAttribute(nodeId, name);
}
return null;
}
@Override
public Iterable<String> getAllLayoutAttributeNodeIds(
HttpServletRequest request, PreferencesScope prefScope) {
final StylesheetPreferencesKey stylesheetPreferencesKey =
this.getStylesheetPreferencesKey(request, prefScope);
final LinkedHashSet<String> allNodeIds = new LinkedHashSet<String>();
final IStylesheetUserPreferences stylesheetUserPreferences =
this.getStylesheetUserPreferences(request, stylesheetPreferencesKey);
if (stylesheetUserPreferences != null) {
allNodeIds.addAll(stylesheetUserPreferences.getAllLayoutAttributeNodeIds());
}
final HttpSession session = request.getSession(false);
if (session != null) {
final Map<String, Map<String, String>> sessionLayoutAttributes =
getSessionLayoutAttributes(session, stylesheetPreferencesKey);
if (sessionLayoutAttributes != null) {
allNodeIds.addAll(sessionLayoutAttributes.keySet());
}
}
final Map<String, Map<String, String>> requestLayoutAttributes =
getRequestLayoutAttributes(request, stylesheetPreferencesKey);
if (requestLayoutAttributes != null) {
allNodeIds.addAll(requestLayoutAttributes.keySet());
}
final IStylesheetUserPreferences distributedStylesheetUserPreferences =
this.getDistributedStylesheetUserPreferences(request, prefScope);
if (distributedStylesheetUserPreferences != null) {
allNodeIds.addAll(distributedStylesheetUserPreferences.getAllLayoutAttributeNodeIds());
}
return allNodeIds;
}
@Override
public Map<String, String> getAllNodesAndValuesForAttribute(
HttpServletRequest request, PreferencesScope prefScope, String name) {
final StylesheetPreferencesKey stylesheetPreferencesKey =
this.getStylesheetPreferencesKey(request, prefScope);
final Builder<String, String> result = ImmutableMap.builder();
final boolean isFragmentOwner =
this.isFragmentOwnerStylesheetPreferencesKey(stylesheetPreferencesKey);
if (!isFragmentOwner) {
final IStylesheetUserPreferences distributedStylesheetUserPreferences =
this.getDistributedStylesheetUserPreferences(request, prefScope);
if (distributedStylesheetUserPreferences != null) {
final Map<String, String> allNodesAndValuesForAttribute =
distributedStylesheetUserPreferences.getAllNodesAndValuesForAttribute(name);
result.putAll(allNodesAndValuesForAttribute);
}
}
final IStylesheetUserPreferences stylesheetUserPreferences =
this.getStylesheetUserPreferences(request, stylesheetPreferencesKey);
if (stylesheetUserPreferences != null) {
final Map<String, String> allNodesAndValuesForAttribute =
stylesheetUserPreferences.getAllNodesAndValuesForAttribute(name);
result.putAll(allNodesAndValuesForAttribute);
}
final HttpSession session = request.getSession(false);
if (session != null) {
//nodeId, name, value
final Map<String, Map<String, String>> sessionLayoutAttributes =
getSessionLayoutAttributes(session, stylesheetPreferencesKey);
getAllNodesAndValuesForAttribute(sessionLayoutAttributes, name, result);
}
final Map<String, Map<String, String>> requestLayoutAttributes =
getRequestLayoutAttributes(request, stylesheetPreferencesKey);
if (requestLayoutAttributes != null) {
getAllNodesAndValuesForAttribute(requestLayoutAttributes, name, result);
}
return result.build();
}
protected void getAllNodesAndValuesForAttribute(
Map<String, Map<String, String>> layoutAttributes,
String name,
Builder<String, String> result) {
if (layoutAttributes == null) {
return;
}
for (Map.Entry<String, Map<String, String>> layoutNodeAttributesEntry :
layoutAttributes.entrySet()) {
//name, value
final Map<String, String> layoutNodeAttribute = layoutNodeAttributesEntry.getValue();
final String value = layoutNodeAttribute.get(name);
if (value != null) {
final String nodeId = layoutNodeAttributesEntry.getKey();
result.put(nodeId, value);
}
}
}
@Override
public <P extends Populator<String, String>> P populateLayoutAttributes(
HttpServletRequest request,
PreferencesScope prefScope,
String nodeId,
P layoutAttributes) {
final StylesheetPreferencesKey stylesheetPreferencesKey =
this.getStylesheetPreferencesKey(request, prefScope);
final IStylesheetDescriptor stylesheetDescriptor =
stylesheetPreferencesKey.stylesheetDescriptor;
//Get the scoped sources once
final IStylesheetUserPreferences stylesheetUserPreferences =
this.getStylesheetUserPreferences(request, stylesheetPreferencesKey);
final Map<String, Map<String, String>> sessionLayoutAttributes;
final HttpSession session = request.getSession(false);
if (session == null) {
sessionLayoutAttributes = null;
} else {
sessionLayoutAttributes = getSessionLayoutAttributes(session, stylesheetPreferencesKey);
}
final Map<String, Map<String, String>> requestLayoutAttributes =
getRequestLayoutAttributes(request, stylesheetPreferencesKey);
final IStylesheetUserPreferences distributedStylesheetUserPreferences =
this.getDistributedStylesheetUserPreferences(request, prefScope);
if (distributedStylesheetUserPreferences != null) {
distributedStylesheetUserPreferences.populateLayoutAttributes(nodeId, layoutAttributes);
}
//Try getting each layout attribute to populate the Map
for (final ILayoutAttributeDescriptor layoutAttributeDescriptor :
stylesheetDescriptor.getLayoutAttributeDescriptors()) {
final String name = layoutAttributeDescriptor.getName();
String value;
final Scope scope = layoutAttributeDescriptor.getScope();
switch (scope) {
case PERSISTENT:
{
if (stylesheetUserPreferences == null) {
value = null;
break;
}
value = stylesheetUserPreferences.getLayoutAttribute(nodeId, name);
break;
}
case SESSION:
{
if (sessionLayoutAttributes == null) {
value = null;
break;
}
final Map<String, String> nodeAttributes =
sessionLayoutAttributes.get(nodeId);
if (nodeAttributes == null) {
value = null;
break;
}
value = nodeAttributes.get(name);
break;
}
case REQUEST:
{
if (requestLayoutAttributes == null) {
value = null;
break;
}
final Map<String, String> nodeAttributes =
requestLayoutAttributes.get(nodeId);
if (nodeAttributes == null) {
value = null;
break;
}
value = nodeAttributes.get(name);
break;
}
default:
{
value = null;
break;
}
}
//Don't add unset properties
if (value == null) {
continue;
}
//If the value is equal to the default value remove the property and return null
if (this.compareValues(value, layoutAttributeDescriptor.getDefaultValue())) {
this.removeLayoutAttribute(request, prefScope, nodeId, name);
continue;
}
layoutAttributes.put(name, value);
}
return layoutAttributes;
}
@Override
public void setStructureStylesheetOverride(HttpServletRequest request, String override) {
request.setAttribute(
StylesheetUserPreferencesServiceImpl
.STYLESHEET_STRUCTURE_OVERRIDE_REQUEST_ATTRIBUTE,
override);
}
@Override
public void setThemeStyleSheetOverride(HttpServletRequest request, String override) {
request.setAttribute(
StylesheetUserPreferencesServiceImpl
.STYLESHEET_THEME_OVERRIDE_REQUEST_ATTRIBUTE_NAME,
override);
}
/**
* Returns the stylesheet name if overridden in the request object.
*
* @param request HttpRequest
* @param scope Scope (Structure or Theme)
* @return Stylesheet name if set as an override in the request, else null if it was not.
*/
protected String getStyleSheetName(final HttpServletRequest request, PreferencesScope scope) {
final String stylesheetNameFromRequest;
if (scope.equals(PreferencesScope.STRUCTURE)) {
stylesheetNameFromRequest =
(String) request.getAttribute(STYLESHEET_STRUCTURE_OVERRIDE_REQUEST_ATTRIBUTE);
} else {
stylesheetNameFromRequest =
(String) request.getAttribute(STYLESHEET_THEME_OVERRIDE_REQUEST_ATTRIBUTE_NAME);
}
return stylesheetNameFromRequest;
}
protected boolean isFragmentOwnerStylesheetPreferencesKey(final StylesheetPreferencesKey key) {
return this.isFragmentOwner(key.person);
}
protected boolean isFragmentOwner(final IPerson person) {
return this.fragmentUtils.getFragmentDefinitionByOwner(person) != null;
}
}