input/output mapping

implicit flow variable polish
This commit is contained in:
Keith Donald
2008-03-05 00:21:20 +00:00
parent b828ada0e7
commit 4bf86f6124
4 changed files with 113 additions and 45 deletions

View File

@@ -192,7 +192,7 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
}
public void buildInputMapper() throws FlowBuilderException {
AttributeMapper inputMapper = parseInputMapper(getDocumentElement(), AttributeMap.class, RequestContext.class);
AttributeMapper inputMapper = parseFlowInputMapper(getDocumentElement());
if (inputMapper != null) {
getFlow().setInputMapper(inputMapper);
}
@@ -215,8 +215,7 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
}
public void buildOutputMapper() throws FlowBuilderException {
AttributeMapper outputMapper = parseOutputMapper(getDocumentElement(), RequestContext.class,
MutableAttributeMap.class);
AttributeMapper outputMapper = parseFlowOutputMapper(getDocumentElement());
if (outputMapper != null) {
getFlow().setOutputMapper(outputMapper);
}
@@ -373,32 +372,45 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
}
}
private AttributeMapper parseInputMapper(Element element, Class sourceType, Class targetType) {
private AttributeMapper parseFlowInputMapper(Element element) {
Collection inputs = DomUtils.getChildElementsByTagName(element, "input");
if (inputs.size() == 0) {
return null;
}
DefaultAttributeMapper inputMapper = new DefaultAttributeMapper();
for (Iterator it = inputs.iterator(); it.hasNext();) {
parseInputMapping((Element) it.next(), inputMapper, sourceType, targetType);
inputMapper.addMapping(parseFlowInputMapping((Element) it.next()));
}
return inputMapper;
}
private AttributeMapper parseOutputMapper(Element element, Class sourceType, Class targetType) {
private Mapping parseFlowInputMapping(Element element) {
ExpressionParser parser = getLocalContext().getExpressionParser();
String name = element.getAttribute("name");
String value = null;
if (element.hasAttribute("value")) {
value = element.getAttribute("value");
} else {
value = element.getAttribute(name);
}
Expression source = parser.parseExpression(name, new ParserContextImpl().eval(MutableAttributeMap.class));
Expression target = parser.parseExpression(value, new ParserContextImpl().eval(RequestContext.class));
return new Mapping(source, target, parseMappingConversionExecutor(element), parseMappingRequired(element));
}
private AttributeMapper parseFlowOutputMapper(Element element) {
Collection inputs = DomUtils.getChildElementsByTagName(element, "output");
if (inputs.size() == 0) {
return null;
}
DefaultAttributeMapper outputMapper = new DefaultAttributeMapper();
for (Iterator it = inputs.iterator(); it.hasNext();) {
parseOutputMapping((Element) it.next(), outputMapper, sourceType, targetType);
outputMapper.addMapping(parseFlowOutputMapping((Element) it.next()));
}
return outputMapper;
}
private Mapping parseInputMapping(Element element, DefaultAttributeMapper mapper, Class sourceClass,
Class targetClass) {
private Mapping parseFlowOutputMapping(Element element) {
ExpressionParser parser = getLocalContext().getExpressionParser();
String name = element.getAttribute("name");
String value = null;
@@ -407,23 +419,8 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
} else {
value = element.getAttribute(name);
}
Expression source = parser.parseExpression(name, new ParserContextImpl().eval(sourceClass));
Expression target = parser.parseExpression(value, new ParserContextImpl().eval(targetClass));
return new Mapping(source, target, parseMappingConversionExecutor(element), parseMappingRequired(element));
}
private Mapping parseOutputMapping(Element element, DefaultAttributeMapper mapper, Class sourceClass,
Class targetClass) {
ExpressionParser parser = getLocalContext().getExpressionParser();
String name = element.getAttribute("name");
String value = null;
if (element.hasAttribute("value")) {
value = element.getAttribute("value");
} else {
value = element.getAttribute(name);
}
Expression source = parser.parseExpression(value, new ParserContextImpl().eval(sourceClass));
Expression target = parser.parseExpression(name, new ParserContextImpl().eval(targetClass));
Expression source = parser.parseExpression(name, new ParserContextImpl().eval(RequestContext.class));
Expression target = parser.parseExpression(value, new ParserContextImpl().eval(MutableAttributeMap.class));
return new Mapping(source, target, parseMappingConversionExecutor(element), parseMappingRequired(element));
}
@@ -557,8 +554,7 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
}
parseAndSetSecuredAttribute(element, attributes);
getFlowArtifactFactory().createEndState(parseId(element), flow, parseEntryActions(element),
new ViewFactoryActionAdapter(parseViewFactory(element, true)),
parseOutputMapper(element, RequestContext.class, MutableAttributeMap.class),
new ViewFactoryActionAdapter(parseViewFactory(element, true)), parseFlowOutputMapper(element),
parseExceptionHandlers(element), attributes);
}
@@ -806,12 +802,64 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
return (SubflowAttributeMapper) getLocalContext().getBeanFactory().getBean(attributeMapperBeanId,
SubflowAttributeMapper.class);
} else {
AttributeMapper inputMapper = parseInputMapper(element, RequestContext.class, MutableAttributeMap.class);
AttributeMapper outputMapper = parseOutputMapper(element, AttributeMap.class, RequestContext.class);
AttributeMapper inputMapper = parseSubflowInputMapper(element);
AttributeMapper outputMapper = parseSubflowOutputMapper(element);
return new GenericSubflowAttributeMapper(inputMapper, outputMapper);
}
}
private AttributeMapper parseSubflowInputMapper(Element element) {
Collection inputs = DomUtils.getChildElementsByTagName(element, "input");
if (inputs.size() == 0) {
return null;
}
DefaultAttributeMapper inputMapper = new DefaultAttributeMapper();
for (Iterator it = inputs.iterator(); it.hasNext();) {
inputMapper.addMapping(parseSubflowInputMapping((Element) it.next()));
}
return inputMapper;
}
private Mapping parseSubflowInputMapping(Element element) {
ExpressionParser parser = getLocalContext().getExpressionParser();
String name = element.getAttribute("name");
String value = null;
if (element.hasAttribute("value")) {
value = element.getAttribute("value");
} else {
value = element.getAttribute(name);
}
Expression source = parser.parseExpression(value, new ParserContextImpl().eval(RequestContext.class));
Expression target = parser.parseExpression(name, new ParserContextImpl().eval(MutableAttributeMap.class));
return new Mapping(source, target, parseMappingConversionExecutor(element), parseMappingRequired(element));
}
private AttributeMapper parseSubflowOutputMapper(Element element) {
Collection inputs = DomUtils.getChildElementsByTagName(element, "output");
if (inputs.size() == 0) {
return null;
}
DefaultAttributeMapper outputMapper = new DefaultAttributeMapper();
for (Iterator it = inputs.iterator(); it.hasNext();) {
outputMapper.addMapping(parseSubflowOutputMapping((Element) it.next()));
}
return outputMapper;
}
private Mapping parseSubflowOutputMapping(Element element) {
ExpressionParser parser = getLocalContext().getExpressionParser();
String name = element.getAttribute("name");
String value = null;
if (element.hasAttribute("value")) {
value = element.getAttribute("value");
} else {
value = element.getAttribute(name);
}
Expression source = parser.parseExpression(name, new ParserContextImpl().eval(MutableAttributeMap.class));
Expression target = parser.parseExpression(value, new ParserContextImpl().eval(RequestContext.class));
return new Mapping(source, target, parseMappingConversionExecutor(element), parseMappingRequired(element));
}
private FlowExecutionExceptionHandler[] parseExceptionHandlers(Element element) {
FlowExecutionExceptionHandler[] transitionExecutingHandlers = parseTransitionExecutingExceptionHandlers(element);
FlowExecutionExceptionHandler[] customHandlers = parseCustomExceptionHandlers(element);

View File

@@ -12,7 +12,7 @@ import javax.el.PropertyNotWritableException;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
public class WebFlowImplicitObjectELResolver extends ELResolver {
public class ImplicitFlowVariableELResolver extends ELResolver {
public Class getCommonPropertyType(ELContext context, Object base) {
return Object.class;
@@ -23,43 +23,63 @@ public class WebFlowImplicitObjectELResolver extends ELResolver {
}
public Class getType(ELContext context, Object base, Object property) {
if (base == null && RequestContextHolder.getRequestContext() == null && ImplicitVariable.matches(property)) {
return ImplicitVariable.value(context, RequestContextHolder.getRequestContext(), property).getClass();
if (base != null) {
return null;
}
RequestContext requestContext = RequestContextHolder.getRequestContext();
if (ImplicitVariables.matches(property)) {
context.setPropertyResolved(true);
return ImplicitVariables.value(context, requestContext, property).getClass();
} else {
return null;
}
return null;
}
public Object getValue(ELContext context, Object base, Object property) {
if (base == null && RequestContextHolder.getRequestContext() == null && ImplicitVariable.matches(property)) {
return ImplicitVariable.value(context, RequestContextHolder.getRequestContext(), property);
if (base != null) {
return null;
}
RequestContext requestContext = RequestContextHolder.getRequestContext();
if (ImplicitVariables.matches(property)) {
context.setPropertyResolved(true);
return ImplicitVariables.value(context, requestContext, property);
} else {
return null;
}
return null;
}
public boolean isReadOnly(ELContext context, Object base, Object property) {
if (base == null && RequestContextHolder.getRequestContext() == null && ImplicitVariable.matches(property)) {
if (base != null) {
return false;
}
if (ImplicitVariables.matches(property)) {
context.setPropertyResolved(true);
return true;
} else {
return false;
}
return false;
}
public void setValue(ELContext context, Object base, Object property, Object value) {
if (base == null && RequestContextHolder.getRequestContext() == null && ImplicitVariable.matches(property)) {
if (base != null) {
return;
}
if (ImplicitVariables.matches(property)) {
context.setPropertyResolved(true);
throw new PropertyNotWritableException("The implicit flow variable " + property + " is not writable.");
}
}
private static final class ImplicitVariable {
private static final class ImplicitVariables {
private static final Set vars = new HashSet();
static {
vars.add("requestParameters");
vars.add("requestScope");
vars.add("flashScope");
vars.add("flowScope");
vars.add("conversationScope");
vars.add("requestParameters");
vars.add("messageContext");
}
private static final BeanELResolver internalResolver = new BeanELResolver();
@@ -70,6 +90,6 @@ public class WebFlowImplicitObjectELResolver extends ELResolver {
public static Object value(ELContext elContext, RequestContext requestContext, Object property) {
return internalResolver.getValue(elContext, requestContext, property);
};
}
}
}

View File

@@ -44,7 +44,7 @@ public class WebFlowELExpressionParser extends ELExpressionParser {
public ELContext getELContext(Object target) {
List customResolvers = new ArrayList();
customResolvers.add(new RequestContextELResolver());
customResolvers.add(new WebFlowImplicitObjectELResolver());
customResolvers.add(new ImplicitFlowVariableELResolver());
customResolvers.add(new SpringBeanWebFlowELResolver());
customResolvers.add(new ActionMethodELResolver());
customResolvers.add(new ScopeSearchingELResolver());

View File

@@ -21,7 +21,7 @@
</view-state>
<subflow-state id="browseDetails" subflow="detail-flow">
<input name="id" value="#{requestParameters.id}" type="long" required="true"/>
<input name="#{id}" value="#{requestParameters.id}" type="long" required="true"/>
<transition on="finish" to="displayResults"/>
</subflow-state>