polishing of resolver implemntations
introduced base class fixed 279
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright 2004-2007 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.springframework.webflow.executor.jsf;
|
||||
|
||||
import javax.faces.el.EvaluationException;
|
||||
import javax.faces.el.PropertyNotFoundException;
|
||||
import javax.faces.el.PropertyResolver;
|
||||
import javax.faces.el.ReferenceSyntaxException;
|
||||
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
|
||||
/**
|
||||
* Base class for property resolvers that set flow execution attributes.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public abstract class AbstractFlowExecutionPropertyResolver extends PropertyResolver {
|
||||
|
||||
/**
|
||||
* The standard property resolver to delegate to if this one doesn't apply.
|
||||
*/
|
||||
private final PropertyResolver resolverDelegate;
|
||||
|
||||
/**
|
||||
* Creates a new flow executon property resolver
|
||||
* @param resolverDelegate the resolver to delegate to when the property is not a flow execution attribute
|
||||
*/
|
||||
public AbstractFlowExecutionPropertyResolver(PropertyResolver resolverDelegate) {
|
||||
this.resolverDelegate = resolverDelegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property resolver this resolver delegates to if necessary.
|
||||
*/
|
||||
protected final PropertyResolver getResolverDelegate() {
|
||||
return resolverDelegate;
|
||||
}
|
||||
|
||||
public Class getType(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
|
||||
if (base instanceof FlowExecution) {
|
||||
FlowExecution execution = (FlowExecution) base;
|
||||
assertPropertyNameValid(property);
|
||||
return doGetAttributeType(execution, (String) property);
|
||||
}
|
||||
else {
|
||||
return resolverDelegate.getType(base, property);
|
||||
}
|
||||
}
|
||||
|
||||
public Class getType(Object base, int index) throws EvaluationException, PropertyNotFoundException {
|
||||
if (base instanceof FlowExecution) {
|
||||
// can't access flow execution by index so we cannot determine type. Return null per JSF spec
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return resolverDelegate.getType(base, index);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getValue(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
|
||||
if (base instanceof FlowExecution) {
|
||||
FlowExecution execution = (FlowExecution) base;
|
||||
assertPropertyNameValid(property);
|
||||
return doGetAttribute(execution, (String) property);
|
||||
}
|
||||
else {
|
||||
return resolverDelegate.getValue(base, property);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getValue(Object base, int index) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.getValue(base, index);
|
||||
}
|
||||
else {
|
||||
throw new ReferenceSyntaxException("Cannot apply an index value to a flow execution");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReadOnly(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
|
||||
if (base instanceof FlowExecution) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return resolverDelegate.isReadOnly(base, property);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReadOnly(Object base, int index) throws EvaluationException, PropertyNotFoundException {
|
||||
if (base instanceof FlowExecution) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return resolverDelegate.isReadOnly(base, index);
|
||||
}
|
||||
}
|
||||
|
||||
public void setValue(Object base, Object property, Object value) throws EvaluationException,
|
||||
PropertyNotFoundException {
|
||||
if ((base instanceof FlowExecution)) {
|
||||
FlowExecution execution = (FlowExecution) base;
|
||||
assertPropertyNameValid(property);
|
||||
doSetAttribute(execution, (String) property, value);
|
||||
}
|
||||
else {
|
||||
resolverDelegate.setValue(base, property, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void setValue(Object base, int index, Object value) throws EvaluationException, PropertyNotFoundException {
|
||||
if (base instanceof FlowExecution) {
|
||||
throw new ReferenceSyntaxException("Cannot apply an index value to flow scope");
|
||||
}
|
||||
else {
|
||||
resolverDelegate.setValue(base, index, value);
|
||||
}
|
||||
}
|
||||
|
||||
// helpers
|
||||
|
||||
private void assertPropertyNameValid(Object property) {
|
||||
if (property == null) {
|
||||
throw new PropertyNotFoundException("The name of the flow execution attribute cannot be null");
|
||||
}
|
||||
if (!(property instanceof String)) {
|
||||
throw new PropertyNotFoundException("Flow execution attribute names must be strings but " + property
|
||||
+ " was not");
|
||||
}
|
||||
if (((String) property).length() == 0) {
|
||||
throw new PropertyNotFoundException("The name of the flow execution attribute cannot be blank");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of value returned by the flow execution attribute.
|
||||
* @param execution the flow execution
|
||||
* @param attributeName the name of the attribute
|
||||
* @return the type of value returned by the attribute
|
||||
*/
|
||||
protected abstract Class doGetAttributeType(FlowExecution execution, String attributeName);
|
||||
|
||||
/**
|
||||
* Gets the value of the flow execution attribute.
|
||||
* @param execution the flow execution
|
||||
* @param attributeName the name of the attribute
|
||||
* @return the attribute value
|
||||
*/
|
||||
protected abstract Object doGetAttribute(FlowExecution execution, String attributeName);
|
||||
|
||||
/**
|
||||
* Sets the value of the flow execution attribute.
|
||||
* @param execution the flow execution
|
||||
* @param attributeName the name of the attribute
|
||||
* @param attributeValue the attribute value
|
||||
*/
|
||||
protected abstract void doSetAttribute(FlowExecution execution, String attributeName, Object attributeValue);
|
||||
|
||||
}
|
||||
@@ -19,15 +19,19 @@ import javax.faces.context.FacesContext;
|
||||
import javax.faces.el.EvaluationException;
|
||||
import javax.faces.el.VariableResolver;
|
||||
|
||||
import org.springframework.web.jsf.DelegatingVariableResolver;
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
|
||||
/**
|
||||
* Custom variable resolver that searches the current flow execution for variables to resolve.
|
||||
* The search algorithm looks in flash scope first, then flow scope, then conversation scope.
|
||||
* If no variable is found, this resolver delegates to the next resolver in the chain.
|
||||
* Custom variable resolver that searches the current flow execution for variables to resolve. The search algorithm
|
||||
* looks in flash scope first, then flow scope, then conversation scope. If no variable is found, this resolver
|
||||
* delegates to the next resolver in the chain.
|
||||
*
|
||||
* Suitable for use along side other variable resolvers to support EL binding expressions like
|
||||
* {#bean.property} where "bean" could be a property in any supported scope.
|
||||
* Suitable for use along side other variable resolvers to support EL binding expressions like {#bean.property} where
|
||||
* "bean" could be a property in any supported scope.
|
||||
*
|
||||
* Consider combining use of this class with a Spring {@link DelegatingVariableResolver} to also support lazy-initialized
|
||||
* binding variables managed by a Spring application context using custom bean scopes.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
|
||||
@@ -17,10 +17,8 @@ package org.springframework.webflow.executor.jsf;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.faces.el.EvaluationException;
|
||||
import javax.faces.el.PropertyNotFoundException;
|
||||
import javax.faces.el.PropertyResolver;
|
||||
import javax.faces.el.ReferenceSyntaxException;
|
||||
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
|
||||
@@ -32,7 +30,7 @@ import org.springframework.webflow.execution.FlowExecution;
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class FlowExecutionPropertyResolver extends PropertyResolver {
|
||||
public class FlowExecutionPropertyResolver extends AbstractFlowExecutionPropertyResolver {
|
||||
|
||||
/**
|
||||
* The name of the special flash scope execution property.
|
||||
@@ -50,53 +48,24 @@ public class FlowExecutionPropertyResolver extends PropertyResolver {
|
||||
private static final String CONVERSATION_SCOPE_PROPERTY = "conversationScope";
|
||||
|
||||
/**
|
||||
* The standard property resolver to delegate to if this one doesn't apply.
|
||||
*/
|
||||
private final PropertyResolver resolverDelegate;
|
||||
|
||||
/**
|
||||
* Create a new FlowExecutionPropertyResolver using the original PropertyResolver.
|
||||
* <p>
|
||||
* A JSF implementation will automatically pass its original resolver into the constructor of a configured resolver,
|
||||
* provided that there is a corresponding constructor argument.
|
||||
*
|
||||
* @param resolverDelegate the original VariableResolver
|
||||
* Creates a new flow executon property resolver that resolves flash, flow, and conversation scope attributes.
|
||||
* @param resolverDelegate the resolver to delegate to when the property is not a flow execution attribute
|
||||
*/
|
||||
public FlowExecutionPropertyResolver(PropertyResolver resolverDelegate) {
|
||||
this.resolverDelegate = resolverDelegate;
|
||||
super(resolverDelegate);
|
||||
}
|
||||
|
||||
public Class getType(Object base, int index) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.getType(base, index);
|
||||
}
|
||||
else {
|
||||
// can't access flow execution property by index - return null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Class getType(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.getType(base, property);
|
||||
}
|
||||
if (property == null) {
|
||||
throw new PropertyNotFoundException("Unable to get value from flow execution - property (key) is null");
|
||||
}
|
||||
if (!(property instanceof String)) {
|
||||
throw new PropertyNotFoundException("Unable to get value from flow execution - key is non-String");
|
||||
}
|
||||
if (FLASH_SCOPE_PROPERTY.equals(property)) {
|
||||
protected Class doGetAttributeType(FlowExecution execution, String attributeName) {
|
||||
if (FLASH_SCOPE_PROPERTY.equals(attributeName)) {
|
||||
return Map.class;
|
||||
} else if (FLOW_SCOPE_PROPERTY.equals(property)) {
|
||||
} else if (FLOW_SCOPE_PROPERTY.equals(attributeName)) {
|
||||
return Map.class;
|
||||
} else if (CONVERSATION_SCOPE_PROPERTY.equals(property)) {
|
||||
} else if (CONVERSATION_SCOPE_PROPERTY.equals(attributeName)) {
|
||||
return Map.class;
|
||||
} else {
|
||||
// perform an attribute search
|
||||
FlowExecution execution = (FlowExecution)base;
|
||||
String attributeName = (String)property;
|
||||
// try flash scope
|
||||
|
||||
// try flash scope first
|
||||
Object value = execution.getActiveSession().getFlashMap().get(attributeName);
|
||||
if (value != null) {
|
||||
return value.getClass();
|
||||
@@ -111,36 +80,21 @@ public class FlowExecutionPropertyResolver extends PropertyResolver {
|
||||
if (value != null) {
|
||||
return value.getClass();
|
||||
}
|
||||
// cannot determine
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Object getValue(Object base, int index) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.getValue(base, index);
|
||||
}
|
||||
else {
|
||||
throw new ReferenceSyntaxException("Cannot apply an index value to flow execution");
|
||||
}
|
||||
}
|
||||
|
||||
public Object getValue(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.getValue(base, property);
|
||||
}
|
||||
if (!(property instanceof String)) {
|
||||
throw new PropertyNotFoundException("Unable to get value from flow execution - key is non-String");
|
||||
}
|
||||
FlowExecution execution = (FlowExecution) base;
|
||||
if (FLASH_SCOPE_PROPERTY.equals(property)) {
|
||||
protected Object doGetAttribute(FlowExecution execution, String attributeName) {
|
||||
if (FLASH_SCOPE_PROPERTY.equals(attributeName)) {
|
||||
return execution.getActiveSession().getFlashMap().asMap();
|
||||
} else if (FLOW_SCOPE_PROPERTY.equals(property)) {
|
||||
} else if (FLOW_SCOPE_PROPERTY.equals(attributeName)) {
|
||||
return execution.getActiveSession().getScope().asMap();
|
||||
} else if (CONVERSATION_SCOPE_PROPERTY.equals(property)) {
|
||||
} else if (CONVERSATION_SCOPE_PROPERTY.equals(attributeName)) {
|
||||
return execution.getConversationScope().asMap();
|
||||
} else {
|
||||
// perform an attribute search
|
||||
String attributeName = (String)property;
|
||||
|
||||
// try flash scope
|
||||
Object value = execution.getActiveSession().getFlashMap().get(attributeName);
|
||||
if (value != null) {
|
||||
@@ -156,54 +110,23 @@ public class FlowExecutionPropertyResolver extends PropertyResolver {
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
throw new PropertyNotFoundException("Cannot resolve flow execution property '" + property + "'");
|
||||
}
|
||||
// cannot resolve as expected
|
||||
throw new PropertyNotFoundException("Readable flow execution attribute '" + attributeName + "' not found in any scope (flash, flow, or conversation)");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReadOnly(Object base, int index) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.isReadOnly(base, index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isReadOnly(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.isReadOnly(base, property);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setValue(Object base, int index, Object value) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
resolverDelegate.setValue(base, index, value);
|
||||
}
|
||||
throw new ReferenceSyntaxException("Cannot apply an index value to a flow execution");
|
||||
}
|
||||
|
||||
public void setValue(Object base, Object property, Object value) throws EvaluationException,
|
||||
PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
resolverDelegate.setValue(base, property, value);
|
||||
return;
|
||||
}
|
||||
if (property == null || !(property instanceof String)
|
||||
|| ((String)property).length() == 0) {
|
||||
throw new PropertyNotFoundException(
|
||||
"Attempt to set flow execution attribute with null name, empty name, or non-String name");
|
||||
}
|
||||
FlowExecution execution = (FlowExecution)base;
|
||||
String attributeName = (String)property;
|
||||
// perform a search: flash, flow, conversation
|
||||
protected void doSetAttribute(FlowExecution execution, String attributeName, Object attributeValue) {
|
||||
// perform a search
|
||||
if (execution.getActiveSession().getFlashMap().contains(attributeName)) {
|
||||
execution.getActiveSession().getFlashMap().put(attributeName, value);
|
||||
execution.getActiveSession().getFlashMap().put(attributeName, attributeValue);
|
||||
}
|
||||
else if (execution.getActiveSession().getScope().contains(attributeName)) {
|
||||
execution.getActiveSession().getScope().put(attributeName, value);
|
||||
execution.getActiveSession().getScope().put(attributeName, attributeValue);
|
||||
} else if (execution.getConversationScope().contains(attributeName)) {
|
||||
execution.getConversationScope().put(attributeName, value);
|
||||
execution.getConversationScope().put(attributeName, attributeValue);
|
||||
} else {
|
||||
throw new PropertyNotFoundException("Settable flow execution property '" + property + "' not found");
|
||||
}
|
||||
// cannot resolve as expected
|
||||
throw new PropertyNotFoundException("Settable flow execution attribute '" + attributeName + "' not found in any scope (flash, flow, or conversation)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,33 +46,26 @@ public class FlowExecutionVariableResolver extends VariableResolver {
|
||||
private VariableResolver resolverDelegate;
|
||||
|
||||
/**
|
||||
* Create a new FlowExecutionVariableResolver, using the given original VariableResolver.
|
||||
* <p>
|
||||
* A JSF implementation will automatically pass its original resolver into the constructor of a configured resolver,
|
||||
* provided that there is a corresponding constructor argument.
|
||||
*
|
||||
* @param resolverDelegate the original VariableResolver
|
||||
* Creates a new flow executon variable resolver that resolves the current FlowExecution object.
|
||||
* @param resolverDelegate the resolver to delegate to when the variable is not named "flowExecution".
|
||||
*/
|
||||
public FlowExecutionVariableResolver(VariableResolver resolverDelegate) {
|
||||
this.resolverDelegate = resolverDelegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the original VariableResolver that this resolver delegates to.
|
||||
* Returns the variable resolver this resolver delegates to if necessary.
|
||||
*/
|
||||
protected final VariableResolver getResolverDelegate() {
|
||||
return resolverDelegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the special "flow" variable first, then delegate to the original VariableResolver.
|
||||
*/
|
||||
public Object resolveVariable(FacesContext context, String name) throws EvaluationException {
|
||||
if (!FLOW_EXECUTION_VARIABLE_NAME.equals(name)) {
|
||||
return resolverDelegate.resolveVariable(context, name);
|
||||
if (FLOW_EXECUTION_VARIABLE_NAME.equals(name)) {
|
||||
return FlowExecutionHolderUtils.getRequiredCurrentFlowExecution(context);
|
||||
}
|
||||
else {
|
||||
return FlowExecutionHolderUtils.getRequiredCurrentFlowExecution(context);
|
||||
return resolverDelegate.resolveVariable(context, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,65 +16,42 @@
|
||||
package org.springframework.webflow.executor.jsf;
|
||||
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.el.EvaluationException;
|
||||
import javax.faces.el.PropertyNotFoundException;
|
||||
import javax.faces.el.PropertyResolver;
|
||||
import javax.faces.el.ReferenceSyntaxException;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.jsf.DelegatingVariableResolver;
|
||||
import org.springframework.web.jsf.FacesContextUtils;
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
|
||||
/**
|
||||
* Custom property resolve that resolves active flow session scope properties
|
||||
* from a thread bound flow execution.
|
||||
* Custom property resolve that resolves flow session scope attributes from the current flow execution. This resolver
|
||||
* will also create and set the attribute value to a bean from the root Spring Web Application Context if the value does
|
||||
* not already exist, allowing for lazy-initialized binding variables.
|
||||
*
|
||||
* Designed mainly to be used with the {@link FlowVariableResolver}. This is the original property resolver implemented
|
||||
* with Spring Web Flow 1.0. In general, prefer {@link DelegatingFlowVariableResolver} or
|
||||
* {@link FlowExecutionVariableResolver} over use of this class. Also, consider use of the
|
||||
* {@link DelegatingVariableResolver} as an alternative to accessing lazy-initialized binding variables managed by a
|
||||
* Spring application context that uses custom bean scopes.
|
||||
*
|
||||
* @author Colin Sampaleanu
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class FlowPropertyResolver extends PropertyResolver {
|
||||
public class FlowPropertyResolver extends AbstractFlowExecutionPropertyResolver {
|
||||
|
||||
/**
|
||||
* The standard property resolver to delegate to if this one doesn't apply.
|
||||
*/
|
||||
private final PropertyResolver resolverDelegate;
|
||||
|
||||
/**
|
||||
* Create a new PropertyResolver, using the given original PropertyResolver.
|
||||
* <p>
|
||||
* A JSF implementation will automatically pass its original resolver into
|
||||
* the constructor of a configured resolver, provided that there is a
|
||||
* corresponding constructor argument.
|
||||
*
|
||||
* @param resolverDelegate the original VariableResolver
|
||||
* Creates a new flow execution property resolver that resolves flow scope attributes.
|
||||
* @param resolverDelegate the resolver to delegate to when the property is not a flow execution attribute
|
||||
*/
|
||||
public FlowPropertyResolver(PropertyResolver resolverDelegate) {
|
||||
this.resolverDelegate = resolverDelegate;
|
||||
super(resolverDelegate);
|
||||
}
|
||||
|
||||
public Class getType(Object base, int index) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.getType(base, index);
|
||||
}
|
||||
else {
|
||||
// can't access flow scope by index, so can't determine type. Return null per JSF spec
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Class getType(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.getType(base, property);
|
||||
}
|
||||
if (property == null) {
|
||||
throw new PropertyNotFoundException("Unable to get value from Flow, as property (key) is null");
|
||||
}
|
||||
if (!(property instanceof String)) {
|
||||
throw new PropertyNotFoundException("Unable to get value from Flow map, as key is non-String");
|
||||
}
|
||||
FlowExecution execution = (FlowExecution)base;
|
||||
protected Class doGetAttributeType(FlowExecution execution, String attributeName) {
|
||||
// we want to access flow scope of the active session (conversation)
|
||||
Object value = execution.getActiveSession().getScope().get((String)property);
|
||||
Object value = execution.getActiveSession().getScope().get(attributeName);
|
||||
// note that MyFaces returns Object.class for a null value here, but
|
||||
// as I read the JSF spec, null should be returned when the object
|
||||
// type can not be determined this certainly seems to be the case
|
||||
@@ -82,80 +59,29 @@ public class FlowPropertyResolver extends PropertyResolver {
|
||||
return (value == null) ? null : value.getClass();
|
||||
}
|
||||
|
||||
public Object getValue(Object base, int index) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.getValue(base, index);
|
||||
}
|
||||
else {
|
||||
throw new ReferenceSyntaxException("Cannot apply an index value to flow scope map");
|
||||
}
|
||||
}
|
||||
|
||||
public Object getValue(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.getValue(base, property);
|
||||
}
|
||||
if (!(property instanceof String)) {
|
||||
throw new PropertyNotFoundException("Unable to get value from flow scope map - key is non-String");
|
||||
}
|
||||
FlowExecution execution = (FlowExecution)base;
|
||||
String attributeName = (String)property;
|
||||
protected Object doGetAttribute(FlowExecution execution, String attributeName) {
|
||||
Object value = execution.getActiveSession().getScope().get(attributeName);
|
||||
if (value == null) {
|
||||
FacesContext context = FacesContext.getCurrentInstance();
|
||||
Assert.notNull(context, "FacesContext must exist during property resolution stage");
|
||||
WebApplicationContext wac = getWebApplicationContext(context);
|
||||
if (wac.containsBean(attributeName)) {
|
||||
// note: this resolver doesn't care, but this should normally be
|
||||
// either a stateless singleton bean, or a stateful/stateless prototype
|
||||
value = wac.getBean(attributeName);
|
||||
FacesContext facesContext = FacesContext.getCurrentInstance();
|
||||
Assert.notNull(facesContext, "The current FacesContext must be present during property resolution stage");
|
||||
BeanFactory beanFactory = getWebApplicationContext(facesContext);
|
||||
if (beanFactory.containsBean(attributeName)) {
|
||||
// note: this resolver doesn't care, but this should be
|
||||
// a stateless bean with singleton scope or a stateful bean with prototype scope
|
||||
value = beanFactory.getBean(attributeName);
|
||||
execution.getActiveSession().getScope().put(attributeName, value);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isReadOnly(Object base, int index) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.isReadOnly(base, index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isReadOnly(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
return resolverDelegate.isReadOnly(base, property);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setValue(Object base, int index, Object value) throws EvaluationException, PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
resolverDelegate.setValue(base, index, value);
|
||||
}
|
||||
throw new ReferenceSyntaxException("Cannot apply an index value to flow scope");
|
||||
}
|
||||
|
||||
public void setValue(Object base, Object property, Object value) throws EvaluationException,
|
||||
PropertyNotFoundException {
|
||||
if (!(base instanceof FlowExecution)) {
|
||||
resolverDelegate.setValue(base, property, value);
|
||||
return;
|
||||
}
|
||||
if (property == null || !(property instanceof String)
|
||||
|| ((String)property).length() == 0) {
|
||||
throw new PropertyNotFoundException(
|
||||
"Attempt to set flow attribute with null name, empty name, or non-String name");
|
||||
}
|
||||
FlowExecution execution = (FlowExecution)base;
|
||||
execution.getActiveSession().getScope().put((String)property, value);
|
||||
protected void doSetAttribute(FlowExecution execution, String attributeName, Object attributeValue) {
|
||||
execution.getActiveSession().getScope().put(attributeName, attributeValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the web application context to delegate bean name resolution to.
|
||||
* <p>
|
||||
* Default implementation delegates to FacesContextUtils.
|
||||
*
|
||||
* Retrieve the web application context to delegate bean name resolution to. Default implementation delegates to
|
||||
* FacesContextUtils.
|
||||
* @param facesContext the current JSF context
|
||||
* @return the Spring web application context (never <code>null</code>)
|
||||
* @see FacesContextUtils#getRequiredWebApplicationContext
|
||||
|
||||
@@ -20,9 +20,16 @@ import javax.faces.el.EvaluationException;
|
||||
import javax.faces.el.VariableResolver;
|
||||
|
||||
/**
|
||||
* Custom variable resolver that resolves to a thread-bound FlowExecution object
|
||||
* for binding expressions prefixed with {@link #FLOW_SCOPE_VARIABLE}. For instance
|
||||
* "flowScope.myBean.myProperty".
|
||||
* Custom variable resolver that resolves the current FlowExecution object for binding expressions prefixed with
|
||||
* {@link #FLOW_SCOPE_VARIABLE}. For instance "flowScope.myBean.myProperty". Designed to be used in conjunction with
|
||||
* {@link FlowPropertyResolver} only.
|
||||
*
|
||||
* This class is the original flow execution variable resolver implementation introduced in Spring Web Flow's JSF
|
||||
* support available since 1.0. In general, prefer use of {@link DelegatingFlowVariableResolver} or
|
||||
* {@link FlowExecutionVariableResolver} to this implementation as they are both considerably more flexible.
|
||||
*
|
||||
* This resolver should only be used with the {@link FlowPropertyResolver} which can only resolve flow-scoped variables.
|
||||
* May be deprecated in a future release of Spring Web Flow.
|
||||
*
|
||||
* @author Colin Sampaleanu
|
||||
*/
|
||||
@@ -39,12 +46,10 @@ public class FlowVariableResolver extends VariableResolver {
|
||||
private VariableResolver resolverDelegate;
|
||||
|
||||
/**
|
||||
* Create a new FlowVariableResolver, using the given original
|
||||
* VariableResolver.
|
||||
* Create a new FlowVariableResolver, using the given original VariableResolver.
|
||||
* <p>
|
||||
* A JSF implementation will automatically pass its original resolver into
|
||||
* the constructor of a configured resolver, provided that there is a
|
||||
* corresponding constructor argument.
|
||||
* A JSF implementation will automatically pass its original resolver into the constructor of a configured resolver,
|
||||
* provided that there is a corresponding constructor argument.
|
||||
*
|
||||
* @param resolverDelegate the original VariableResolver
|
||||
*/
|
||||
@@ -59,16 +64,12 @@ public class FlowVariableResolver extends VariableResolver {
|
||||
return resolverDelegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the special "flow" variable first, then delegate to the
|
||||
* original VariableResolver.
|
||||
*/
|
||||
public Object resolveVariable(FacesContext context, String name) throws EvaluationException {
|
||||
if (!FLOW_SCOPE_VARIABLE.equals(name)) {
|
||||
return resolverDelegate.resolveVariable(context, name);
|
||||
if (FLOW_SCOPE_VARIABLE.equals(name)) {
|
||||
return FlowExecutionHolderUtils.getRequiredCurrentFlowExecution(context);
|
||||
}
|
||||
else {
|
||||
return FlowExecutionHolderUtils.getRequiredCurrentFlowExecution(context);
|
||||
return resolverDelegate.resolveVariable(context, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user