enhanced mapper subsystem
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package org.springframework.binding.expression;
|
||||
|
||||
/**
|
||||
* An evaluation exception indicating a expression that references a property failed to evaluate because the property
|
||||
* could not be found.
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class PropertyNotFoundException extends EvaluationException {
|
||||
|
||||
/**
|
||||
* Creates a new property not found exception
|
||||
* @param evaluationAttempt the evaluaion attempt details
|
||||
* @param cause root cause of the failure
|
||||
*/
|
||||
public PropertyNotFoundException(EvaluationAttempt evaluationAttempt, Throwable cause) {
|
||||
super(evaluationAttempt, cause);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import javax.el.ValueExpression;
|
||||
import org.springframework.binding.expression.EvaluationAttempt;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.PropertyNotFoundException;
|
||||
import org.springframework.binding.expression.SetValueAttempt;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -46,8 +47,10 @@ public class ELExpression implements Expression {
|
||||
throw new EvaluationException(new EvaluationAttempt(this, context), null);
|
||||
}
|
||||
return result;
|
||||
} catch (ELException ex) {
|
||||
throw new EvaluationException(new EvaluationAttempt(this, context), ex);
|
||||
} catch (javax.el.PropertyNotFoundException e) {
|
||||
throw new PropertyNotFoundException(new EvaluationAttempt(this, context), e);
|
||||
} catch (ELException e) {
|
||||
throw new EvaluationException(new EvaluationAttempt(this, context), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +61,8 @@ public class ELExpression implements Expression {
|
||||
if (!ctx.isPropertyResolved()) {
|
||||
throw new EvaluationException(new SetValueAttempt(this, context, value), null);
|
||||
}
|
||||
} catch (javax.el.PropertyNotFoundException e) {
|
||||
throw new PropertyNotFoundException(new EvaluationAttempt(this, context), e);
|
||||
} catch (ELException ex) {
|
||||
throw new EvaluationException(new EvaluationAttempt(this, context), ex);
|
||||
}
|
||||
@@ -67,6 +72,8 @@ public class ELExpression implements Expression {
|
||||
ELContext ctx = elContextFactory.getELContext(context);
|
||||
try {
|
||||
return valueExpression.getType(ctx);
|
||||
} catch (javax.el.PropertyNotFoundException e) {
|
||||
throw new PropertyNotFoundException(new EvaluationAttempt(this, context), e);
|
||||
} catch (ELException ex) {
|
||||
throw new EvaluationException(new EvaluationAttempt(this, context), ex);
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* 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.binding.mapping;
|
||||
|
||||
/**
|
||||
* A lightweight service interface for mapping between two attribute sources.
|
||||
* <p>
|
||||
* Implementations of this interface are expected to encapsulate the mapping configuration information as well as the
|
||||
* logic to act on it to perform mapping between a given source and target attribute source.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface AttributeMapper {
|
||||
|
||||
/**
|
||||
* Map data from a source object to a target object.
|
||||
* @param source the source
|
||||
* @param target the target
|
||||
* @param context the mapping context
|
||||
* @throws AttributeMappingException if errors occurred during the mapping process
|
||||
*/
|
||||
public void map(Object source, Object target, MappingContext context) throws AttributeMappingException;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package org.springframework.binding.mapping;
|
||||
|
||||
public class AttributeMappingException extends RuntimeException {
|
||||
|
||||
}
|
||||
@@ -1,32 +1,32 @@
|
||||
/*
|
||||
* 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.binding.mapping;
|
||||
|
||||
/**
|
||||
* Thrown when a required mapping could not be performed.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class RequiredMappingException extends IllegalStateException {
|
||||
|
||||
/**
|
||||
* Create a new required mapping exception.
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
public RequiredMappingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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.binding.mapping;
|
||||
|
||||
/**
|
||||
* Maps state between two objects.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface Mapper {
|
||||
|
||||
/**
|
||||
* Map state from a source object to a target object.
|
||||
* @param source the source
|
||||
* @param target the target
|
||||
* @return results of the mapping transaction
|
||||
*/
|
||||
public MappingResults map(Object source, Object target);
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* 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.binding.mapping;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.support.DefaultConversionService;
|
||||
import org.springframework.binding.convert.support.RuntimeBindingConversionExecutor;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.support.CollectionAddingExpression;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A stateful builder that builds {@link Mapping} objects. Designed for convenience to build mappings in a clear,
|
||||
* readable manner.
|
||||
* <p>
|
||||
* Example usage:
|
||||
*
|
||||
* <pre>
|
||||
* MappingBuilder mapping = new MappingBuilder();
|
||||
* Mapping result = mapping.source("foo").target("bar").from(String.class).to(Long.class).value();
|
||||
* </pre>
|
||||
*
|
||||
* Calling the {@link #value()} result method clears out this builder's state so it can be reused to build another
|
||||
* mapping.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class MappingBuilder {
|
||||
|
||||
/**
|
||||
* The expression string parser.
|
||||
*/
|
||||
private ExpressionParser expressionParser;
|
||||
|
||||
/**
|
||||
* The conversion service for applying type conversions.
|
||||
*/
|
||||
private ConversionService conversionService = new DefaultConversionService();
|
||||
|
||||
/**
|
||||
* The source mapping expression.
|
||||
*/
|
||||
private Expression sourceExpression;
|
||||
|
||||
/**
|
||||
* The target mapping settable expression.
|
||||
*/
|
||||
private Expression targetExpression;
|
||||
|
||||
/**
|
||||
* The type of the object returned by evaluating the source expression.
|
||||
*/
|
||||
private Class sourceType;
|
||||
|
||||
/**
|
||||
* The type of the property settable by the target expression.
|
||||
*/
|
||||
private Class targetType;
|
||||
|
||||
/**
|
||||
* Whether or not the built mapping is a required mapping.
|
||||
*/
|
||||
private boolean required;
|
||||
|
||||
/**
|
||||
* Creates a mapping builder that uses the expression parser to parse attribute mapping expressions.
|
||||
* @param expressionParser the expression parser
|
||||
*/
|
||||
public MappingBuilder(ExpressionParser expressionParser) {
|
||||
Assert.notNull(expressionParser, "The expression parser is required");
|
||||
this.expressionParser = expressionParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the conversion service that will convert the object returned by evaluating the source expression to the
|
||||
* {@link #to(Class)} type if necessary.
|
||||
* @param conversionService the conversion service
|
||||
*/
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source expression of the mapping built by this builder.
|
||||
* @param expressionString the expression string
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public MappingBuilder source(String expressionString) {
|
||||
sourceExpression = expressionParser.parseExpression(expressionString, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the target property expression of the mapping built by this builder.
|
||||
* @param expressionString the expression string
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public MappingBuilder target(String expressionString) {
|
||||
targetExpression = expressionParser.parseExpression(expressionString, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the target collection of the mapping built by this builder.
|
||||
* @param expressionString the expression string, resolving a collection
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public MappingBuilder targetCollection(String expressionString) {
|
||||
targetExpression = new CollectionAddingExpression(expressionParser.parseExpression(expressionString, null));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the expected type of the object returned by evaluating the source expression. Used in conjunction with
|
||||
* {@link #to(Class)} to perform a type conversion during the mapping process.
|
||||
* @param sourceType the source type
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public MappingBuilder from(Class sourceType) {
|
||||
this.sourceType = sourceType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the target type of the property writeable by the target expression.
|
||||
* @param targetType the target type
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public MappingBuilder to(Class targetType) {
|
||||
this.targetType = targetType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the mapping to be built a "required" mapping.
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public MappingBuilder required() {
|
||||
this.required = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The logical GoF builder getResult method, returning a fully constructed Mapping from the configured pieces. Once
|
||||
* called, the state of this builder is nulled out to support building a new mapping object again.
|
||||
* @return the mapping result
|
||||
*/
|
||||
public Mapping value() {
|
||||
Assert.notNull(sourceExpression, "The source expression must be set at a minimum");
|
||||
if (targetExpression == null) {
|
||||
targetExpression = sourceExpression;
|
||||
}
|
||||
ConversionExecutor typeConverter = null;
|
||||
if (targetType != null) {
|
||||
if (sourceType != null) {
|
||||
typeConverter = conversionService.getConversionExecutor(sourceType, targetType);
|
||||
} else {
|
||||
typeConverter = new RuntimeBindingConversionExecutor(targetType, conversionService);
|
||||
}
|
||||
}
|
||||
Mapping result = new Mapping(sourceExpression, targetExpression, typeConverter, required);
|
||||
reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset this mapping builder.
|
||||
*/
|
||||
public void reset() {
|
||||
sourceExpression = null;
|
||||
targetExpression = null;
|
||||
sourceType = null;
|
||||
targetType = null;
|
||||
required = false;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* 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.binding.mapping;
|
||||
|
||||
import org.springframework.binding.message.MessageContext;
|
||||
|
||||
/**
|
||||
* A context object with two main responsibities:
|
||||
* <ol>
|
||||
* <li>Exposing information to a mapper to influence a mapping attempt.
|
||||
* <li>Providing operations for recording progress or errors during the mapping process.
|
||||
* </ol>
|
||||
* Empty for now; subclasses may define their own custom context behavior accessible by a mapper with a downcast.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface MappingContext {
|
||||
|
||||
/**
|
||||
* Returns the message context to use to record errors during the mapping process.
|
||||
* @return the message context
|
||||
*/
|
||||
public MessageContext getMessageContext();
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package org.springframework.binding.mapping;
|
||||
|
||||
import org.springframework.binding.message.MessageContext;
|
||||
|
||||
public class MappingContextImpl implements MappingContext {
|
||||
|
||||
private MessageContext messageContext;
|
||||
|
||||
public MappingContextImpl(MessageContext messageContext) {
|
||||
this.messageContext = messageContext;
|
||||
}
|
||||
|
||||
public MessageContext getMessageContext() {
|
||||
return messageContext;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.springframework.binding.mapping;
|
||||
|
||||
public class MappingResult {
|
||||
|
||||
private Mapping mapping;
|
||||
|
||||
private Result result;
|
||||
|
||||
public MappingResult(Mapping mapping, Result result) {
|
||||
this.mapping = mapping;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public Mapping getMapping() {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
public Result getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.springframework.binding.mapping;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MappingResults {
|
||||
|
||||
public Object getSource();
|
||||
|
||||
public Object getTarget();
|
||||
|
||||
public List getAllResults();
|
||||
|
||||
public boolean hasErrorResults();
|
||||
|
||||
public List getErrorResults();
|
||||
|
||||
public List getResults(MappingResultsCriteria criteria);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.springframework.binding.mapping;
|
||||
|
||||
public interface MappingResultsCriteria {
|
||||
public boolean test(MappingResult result);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.springframework.binding.mapping;
|
||||
|
||||
public abstract class Result {
|
||||
public abstract Object getOriginalValue();
|
||||
|
||||
public abstract Object getMappedValue();
|
||||
|
||||
public abstract boolean isError();
|
||||
|
||||
public abstract String getErrorCode();
|
||||
}
|
||||
@@ -13,13 +13,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.binding.mapping;
|
||||
package org.springframework.binding.mapping.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.binding.mapping.Mapping;
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
|
||||
/**
|
||||
@@ -29,34 +32,33 @@ import org.springframework.core.style.ToStringCreator;
|
||||
* @author Keith Donald
|
||||
* @author Colin Sampaleanu
|
||||
*/
|
||||
public class DefaultAttributeMapper implements AttributeMapper {
|
||||
public class DefaultMapper implements Mapper {
|
||||
|
||||
/**
|
||||
* The ordered list of mappings to apply.
|
||||
*/
|
||||
private List mappings = new LinkedList();
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
public ConversionService getConversionService() {
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mapping to this mapper.
|
||||
* @param mapping the mapping to add
|
||||
* @return this, to support convenient call chaining
|
||||
*/
|
||||
public DefaultAttributeMapper addMapping(Mapping mapping) {
|
||||
public DefaultMapper addMapping(DefaultMapping mapping) {
|
||||
mappings.add(mapping);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a set of mappings.
|
||||
* @param mappings the mappings
|
||||
*/
|
||||
public void addMappings(Mapping[] mappings) {
|
||||
if (mappings == null) {
|
||||
return;
|
||||
}
|
||||
this.mappings.addAll(Arrays.asList(mappings));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this mapper's list of mappings.
|
||||
* @return the list of mappings
|
||||
@@ -65,21 +67,14 @@ public class DefaultAttributeMapper implements AttributeMapper {
|
||||
return (Mapping[]) mappings.toArray(new Mapping[mappings.size()]);
|
||||
}
|
||||
|
||||
public void map(Object source, Object target, MappingContext context) throws AttributeMappingException {
|
||||
boolean mappingFailure = false;
|
||||
if (mappings != null) {
|
||||
Iterator it = mappings.iterator();
|
||||
while (it.hasNext()) {
|
||||
Mapping mapping = (Mapping) it.next();
|
||||
boolean result = mapping.map(source, target, context);
|
||||
if (!result && !mappingFailure) {
|
||||
mappingFailure = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mappingFailure) {
|
||||
throw new AttributeMappingException();
|
||||
public MappingResults map(Object source, Object target) {
|
||||
DefaultMappingContext context = new DefaultMappingContext(source, target, conversionService);
|
||||
Iterator it = mappings.iterator();
|
||||
while (it.hasNext()) {
|
||||
DefaultMapping mapping = (DefaultMapping) it.next();
|
||||
mapping.map(context);
|
||||
}
|
||||
return context.toResult();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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.binding.mapping.impl;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.mapping.Mapping;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A single mapping definition, encapsulating the information necessary to map the result of evaluating an expression on
|
||||
* a source object to a property on a target object, optionally applying a type conversion during the mapping process.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class DefaultMapping implements Mapping {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(DefaultMapping.class);
|
||||
|
||||
/**
|
||||
* The source expression to evaluate against a source object to map from.
|
||||
*/
|
||||
private final Expression sourceExpression;
|
||||
|
||||
/**
|
||||
* The target expression to set on a target object to map to.
|
||||
*/
|
||||
private final Expression targetExpression;
|
||||
|
||||
/**
|
||||
* Whether or not this is a required mapping; if true, the source expression must return a non-null value.
|
||||
*/
|
||||
private boolean required;
|
||||
|
||||
/**
|
||||
* A specific type conversion routine to apply during the mapping process.
|
||||
*/
|
||||
private ConversionExecutor typeConverter;
|
||||
|
||||
/**
|
||||
* Creates a new mapping.
|
||||
* @param sourceExpression the source expression
|
||||
* @param targetExpression the target expression
|
||||
*/
|
||||
public DefaultMapping(Expression sourceExpression, Expression targetExpression) {
|
||||
Assert.notNull(sourceExpression, "The source expression is required");
|
||||
Assert.notNull(targetExpression, "The target expression is required");
|
||||
this.sourceExpression = sourceExpression;
|
||||
this.targetExpression = targetExpression;
|
||||
}
|
||||
|
||||
// implementing mapping
|
||||
|
||||
public Expression getSourceExpression() {
|
||||
return sourceExpression;
|
||||
}
|
||||
|
||||
public Expression getTargetExpression() {
|
||||
return targetExpression;
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
// optional impl getters/setters
|
||||
|
||||
public ConversionExecutor getTypeConverter() {
|
||||
return typeConverter;
|
||||
}
|
||||
|
||||
public void setTypeConverter(ConversionExecutor typeConverter) {
|
||||
this.typeConverter = typeConverter;
|
||||
}
|
||||
|
||||
public void setRequired(boolean required) {
|
||||
this.required = required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute this mapping.
|
||||
* @param context the mapping context
|
||||
*/
|
||||
public void map(MappingContext context) {
|
||||
context.setCurrentMapping(this);
|
||||
Object sourceValue;
|
||||
try {
|
||||
sourceValue = sourceExpression.getValue(context.getSource());
|
||||
} catch (EvaluationException e) {
|
||||
context.setSourceAccessError(e);
|
||||
return;
|
||||
}
|
||||
if (required && (sourceValue == null || isEmptyString(sourceValue))) {
|
||||
context.setRequiredErrorResult(sourceValue);
|
||||
return;
|
||||
}
|
||||
Object targetValue = sourceValue;
|
||||
if (sourceValue != null) {
|
||||
if (typeConverter != null) {
|
||||
try {
|
||||
targetValue = typeConverter.execute(targetValue);
|
||||
} catch (ConversionException e) {
|
||||
context.setTypeConversionErrorResult(sourceValue, e.getTargetClass());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
ConversionService conversionService = context.getConversionService();
|
||||
if (conversionService != null) {
|
||||
Class targetType;
|
||||
try {
|
||||
targetType = targetExpression.getValueType(context.getTarget());
|
||||
} catch (EvaluationException e) {
|
||||
context.setTargetAccessError(sourceValue, e);
|
||||
return;
|
||||
}
|
||||
if (targetType != null && !targetType.isInstance(targetValue)) {
|
||||
try {
|
||||
ConversionExecutor typeConverter = conversionService.getConversionExecutor(sourceValue
|
||||
.getClass(), targetType);
|
||||
targetValue = typeConverter.execute(sourceValue);
|
||||
} catch (ConversionException e) {
|
||||
context.setTypeConversionErrorResult(sourceValue, e.getTargetClass());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Mapping '" + sourceExpression + "' value [" + sourceValue + "] to target '"
|
||||
+ targetExpression + "'; setting target value to [" + targetValue + "]");
|
||||
}
|
||||
try {
|
||||
targetExpression.setValue(context.getTarget(), targetValue);
|
||||
context.setSuccessResult(sourceValue, targetValue);
|
||||
} catch (EvaluationException e) {
|
||||
context.setTargetAccessError(sourceValue, e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEmptyString(Object sourceValue) {
|
||||
if (sourceValue instanceof CharSequence) {
|
||||
return ((CharSequence) sourceValue).length() == 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof DefaultMapping)) {
|
||||
return false;
|
||||
}
|
||||
DefaultMapping other = (DefaultMapping) o;
|
||||
return sourceExpression.equals(other.sourceExpression) && targetExpression.equals(other.targetExpression);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return sourceExpression.hashCode() + targetExpression.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append(sourceExpression + " -> " + targetExpression).toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.springframework.binding.mapping.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.mapping.Mapping;
|
||||
import org.springframework.binding.mapping.MappingResult;
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.binding.mapping.results.RequiredError;
|
||||
import org.springframework.binding.mapping.results.SourceAccessError;
|
||||
import org.springframework.binding.mapping.results.Success;
|
||||
import org.springframework.binding.mapping.results.TargetAccessError;
|
||||
import org.springframework.binding.mapping.results.TypeConversionError;
|
||||
|
||||
class DefaultMappingContext implements MappingContext {
|
||||
|
||||
private Object source;
|
||||
|
||||
private Object target;
|
||||
|
||||
private Mapping currentMapping;
|
||||
|
||||
private List mappingResults;
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
public DefaultMappingContext(Object source, Object target, ConversionService conversionService) {
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
this.conversionService = conversionService;
|
||||
this.mappingResults = new ArrayList();
|
||||
}
|
||||
|
||||
public Object getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public Object getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public ConversionService getConversionService() {
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
public void setCurrentMapping(Mapping mapping) {
|
||||
if (this.currentMapping != null) {
|
||||
throw new IllegalStateException("The current mapping has not finished yet");
|
||||
}
|
||||
this.currentMapping = mapping;
|
||||
}
|
||||
|
||||
public void setSuccessResult(Object originalValue, Object mappedValue) {
|
||||
mappingResults.add(new MappingResult(currentMapping, new Success(originalValue, mappedValue)));
|
||||
currentMapping = null;
|
||||
}
|
||||
|
||||
public void setRequiredErrorResult(Object originalValue) {
|
||||
mappingResults.add(new MappingResult(currentMapping, new RequiredError(originalValue)));
|
||||
this.currentMapping = null;
|
||||
}
|
||||
|
||||
public void setTypeConversionErrorResult(Object originalValue, Class targetType) {
|
||||
mappingResults.add(new MappingResult(currentMapping, new TypeConversionError(originalValue, targetType)));
|
||||
this.currentMapping = null;
|
||||
}
|
||||
|
||||
public void setSourceAccessError(EvaluationException error) {
|
||||
mappingResults.add(new MappingResult(currentMapping, new SourceAccessError(error)));
|
||||
this.currentMapping = null;
|
||||
}
|
||||
|
||||
public void setTargetAccessError(Object originalValue, EvaluationException error) {
|
||||
mappingResults.add(new MappingResult(currentMapping, new TargetAccessError(originalValue, error)));
|
||||
this.currentMapping = null;
|
||||
}
|
||||
|
||||
public MappingResults toResult() {
|
||||
return new DefaultMappingResults(source, target, mappingResults);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package org.springframework.binding.mapping.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.binding.mapping.MappingResult;
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.binding.mapping.MappingResultsCriteria;
|
||||
|
||||
public class DefaultMappingResults implements MappingResults {
|
||||
|
||||
private Object source;
|
||||
|
||||
private Object target;
|
||||
|
||||
private List mappingResults;
|
||||
|
||||
public DefaultMappingResults(Object source, Object target, List mappingResults) {
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
this.mappingResults = mappingResults;
|
||||
}
|
||||
|
||||
public Object getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public Object getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public List getAllResults() {
|
||||
return Collections.unmodifiableList(mappingResults);
|
||||
}
|
||||
|
||||
public boolean hasErrorResults() {
|
||||
Iterator it = mappingResults.iterator();
|
||||
while (it.hasNext()) {
|
||||
MappingResult result = (MappingResult) it.next();
|
||||
if (result.getResult().isError()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List getErrorResults() {
|
||||
List errorResults = new ArrayList();
|
||||
Iterator it = mappingResults.iterator();
|
||||
while (it.hasNext()) {
|
||||
MappingResult result = (MappingResult) it.next();
|
||||
if (result.getResult().isError()) {
|
||||
errorResults.add(result);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableList(errorResults);
|
||||
}
|
||||
|
||||
public List getResults(MappingResultsCriteria criteria) {
|
||||
List results = new ArrayList();
|
||||
Iterator it = mappingResults.iterator();
|
||||
while (it.hasNext()) {
|
||||
MappingResult result = (MappingResult) it.next();
|
||||
if (criteria.test(result)) {
|
||||
results.add(result);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableList(results);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.binding.mapping.impl;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.mapping.Mapping;
|
||||
|
||||
/**
|
||||
* A context for a mapping transaction.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface MappingContext {
|
||||
|
||||
/**
|
||||
* The object being mapped from.
|
||||
*/
|
||||
public Object getSource();
|
||||
|
||||
/**
|
||||
* The object being mapped to.
|
||||
*/
|
||||
public Object getTarget();
|
||||
|
||||
/**
|
||||
* Returns the conversion service that can be used to perform type conversions during the mapping process. May be
|
||||
* null if no externally managed conversion service is provided.
|
||||
*/
|
||||
public ConversionService getConversionService();
|
||||
|
||||
/**
|
||||
* Sets the current mapping. Called when a single mapping operation is about to begin. This updates progress of the
|
||||
* overall mapping transaction.
|
||||
* @param mapping the mapping to make the current mapping
|
||||
*/
|
||||
public void setCurrentMapping(Mapping mapping);
|
||||
|
||||
/**
|
||||
* Indicates the current mapping completed successfully.
|
||||
* @param originalValue the original value from the source of the mapping
|
||||
* @param mappedValue the successfully mapped value, which may be different from the original if a type conversion
|
||||
* was performed
|
||||
*/
|
||||
public void setSuccessResult(Object originalValue, Object mappedValue);
|
||||
|
||||
/**
|
||||
* Indicates the current mapping ended with a 'required' error. This means the value obtained from the source was
|
||||
* empty, and the mapping could not be completed as a result.
|
||||
* @param originalValue the original source value that is empty (null or an empty string, typically)
|
||||
*/
|
||||
public void setRequiredErrorResult(Object originalValue);
|
||||
|
||||
/**
|
||||
* Indicates the current mapping ended with a 'type conversion' error. This means the value obtained from the source
|
||||
* could not be converted to a type that could be assigned to the target expression.
|
||||
* @param originalValue the original source value that could not be converted during the mapping attempt
|
||||
* @param targetType the desired target type to which conversion could not be performed
|
||||
*/
|
||||
public void setTypeConversionErrorResult(Object originalValue, Class targetType);
|
||||
|
||||
/**
|
||||
* Indicates a error occurred accessing the source mapping expression.
|
||||
* @param error the error that occurred
|
||||
*/
|
||||
public void setSourceAccessError(EvaluationException error);
|
||||
|
||||
/**
|
||||
* Indicates a error occurred accessing the target mapping expression.
|
||||
* @param error the error that occurred
|
||||
*/
|
||||
public void setTargetAccessError(Object originalValue, EvaluationException error);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.springframework.binding.mapping.results;
|
||||
|
||||
import org.springframework.binding.mapping.Result;
|
||||
|
||||
public class RequiredError extends Result {
|
||||
|
||||
private Object originalValue;
|
||||
|
||||
public RequiredError(Object originalValue) {
|
||||
this.originalValue = originalValue;
|
||||
}
|
||||
|
||||
public Object getOriginalValue() {
|
||||
return originalValue;
|
||||
}
|
||||
|
||||
public Object getMappedValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getErrorCode() {
|
||||
return "required";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.springframework.binding.mapping.results;
|
||||
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.mapping.Result;
|
||||
|
||||
public class SourceAccessError extends Result {
|
||||
|
||||
private EvaluationException error;
|
||||
|
||||
public SourceAccessError(EvaluationException error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public EvaluationException getException() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public Object getOriginalValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getMappedValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getErrorCode() {
|
||||
return "sourceAccess";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.springframework.binding.mapping.results;
|
||||
|
||||
import org.springframework.binding.mapping.Result;
|
||||
|
||||
public class Success extends Result {
|
||||
|
||||
private Object originalValue;
|
||||
private Object mappedValue;
|
||||
|
||||
public Success(Object mappedValue, Object originalValue) {
|
||||
this.mappedValue = mappedValue;
|
||||
this.originalValue = originalValue;
|
||||
}
|
||||
|
||||
public Object getOriginalValue() {
|
||||
return originalValue;
|
||||
}
|
||||
|
||||
public Object getMappedValue() {
|
||||
return mappedValue;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getErrorCode() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.springframework.binding.mapping.results;
|
||||
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.PropertyNotFoundException;
|
||||
import org.springframework.binding.mapping.Result;
|
||||
|
||||
public class TargetAccessError extends Result {
|
||||
|
||||
private Object originalValue;
|
||||
|
||||
private EvaluationException error;
|
||||
|
||||
public TargetAccessError(Object originalValue, EvaluationException error) {
|
||||
this.originalValue = originalValue;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public EvaluationException getException() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public Object getOriginalValue() {
|
||||
return originalValue;
|
||||
}
|
||||
|
||||
public Object getMappedValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getErrorCode() {
|
||||
if (error instanceof PropertyNotFoundException) {
|
||||
return "propertyNotFound";
|
||||
} else {
|
||||
return "targetAccess";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.springframework.binding.mapping.results;
|
||||
|
||||
import org.springframework.binding.mapping.Result;
|
||||
|
||||
public class TypeConversionError extends Result {
|
||||
|
||||
private Object originalValue;
|
||||
|
||||
private Class targetType;
|
||||
|
||||
public TypeConversionError(Object originalValue, Class targetType) {
|
||||
this.originalValue = originalValue;
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
public Object getOriginalValue() {
|
||||
return originalValue;
|
||||
}
|
||||
|
||||
public Class getTargetType() {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
public Object getMappedValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getErrorCode() {
|
||||
return "typeMismatch";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* 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.action;
|
||||
|
||||
import org.springframework.binding.mapping.AttributeMapper;
|
||||
import org.springframework.binding.mapping.MappingContext;
|
||||
import org.springframework.binding.mapping.MappingContextImpl;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Action that executes an attribute mapper to map information in the request context. Both the source and the target of
|
||||
* the mapping will be the request context. This allows for maximum flexibility when defining attribute mapping
|
||||
* expressions (e.g. "${flowScope.someAttribute}").
|
||||
* <p>
|
||||
* This action always returns the {@link org.springframework.webflow.action.AbstractAction#success() success} event. If
|
||||
* something goes wrong while executing the mapping, an exception is thrown.
|
||||
*
|
||||
* @see org.springframework.binding.mapping.AttributeMapper
|
||||
* @see org.springframework.webflow.execution.RequestContext
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class AttributeMapperAction extends AbstractAction {
|
||||
|
||||
/**
|
||||
* The attribute mapper strategy to delegate to perform the mapping.
|
||||
*/
|
||||
private AttributeMapper attributeMapper;
|
||||
|
||||
/**
|
||||
* Creates a new attribute mapper action that delegates to the configured attribute mapper to complete the mapping
|
||||
* process.
|
||||
* @param attributeMapper the mapper
|
||||
*/
|
||||
public AttributeMapperAction(AttributeMapper attributeMapper) {
|
||||
Assert.notNull(attributeMapper, "The attribute mapper is required");
|
||||
this.attributeMapper = attributeMapper;
|
||||
}
|
||||
|
||||
protected Event doExecute(RequestContext context) throws Exception {
|
||||
// map attributes from and to the request context
|
||||
attributeMapper.map(context, context, getMappingContext(context));
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a context containing extra data available during attribute mapping. The default implementation just
|
||||
* returns null. Subclasses can override this if necessary.
|
||||
*/
|
||||
protected MappingContext getMappingContext(RequestContext context) {
|
||||
return new MappingContextImpl(context.getMessageContext());
|
||||
}
|
||||
}
|
||||
@@ -5,22 +5,24 @@ import java.util.Iterator;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.support.RuntimeBindingConversionExecutor;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.support.ParserContextImpl;
|
||||
import org.springframework.binding.mapping.AttributeMappingException;
|
||||
import org.springframework.binding.mapping.DefaultAttributeMapper;
|
||||
import org.springframework.binding.mapping.Mapping;
|
||||
import org.springframework.binding.mapping.MappingContextImpl;
|
||||
import org.springframework.binding.mapping.MappingResult;
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.binding.mapping.MappingResultsCriteria;
|
||||
import org.springframework.binding.mapping.impl.DefaultMapper;
|
||||
import org.springframework.binding.mapping.impl.DefaultMapping;
|
||||
import org.springframework.binding.mapping.results.TargetAccessError;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
public class BindAction extends AbstractAction {
|
||||
|
||||
private static Log logger = LogFactory.getLog(BindAction.class);
|
||||
private static final Log logger = LogFactory.getLog(BindAction.class);
|
||||
|
||||
private static final MappingResultsCriteria PROPERTY_NOT_FOUND_ERRORS = new PropertyNotFoundErrors();
|
||||
|
||||
private Expression target;
|
||||
|
||||
@@ -40,7 +42,8 @@ public class BindAction extends AbstractAction {
|
||||
throw new IllegalStateException(
|
||||
"The bind target cannot be null - check your expression. Bind target expression = " + target);
|
||||
}
|
||||
DefaultAttributeMapper mapper = new DefaultAttributeMapper();
|
||||
DefaultMapper mapper = new DefaultMapper();
|
||||
mapper.setConversionService(conversionService);
|
||||
AttributeMap eventAttributes = context.getLastEvent().getAttributes();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Binding event '" + context.getLastEvent().getId() + "' attributes " + eventAttributes
|
||||
@@ -52,23 +55,25 @@ public class BindAction extends AbstractAction {
|
||||
.eval(AttributeMap.class));
|
||||
Expression targetAttribute = expressionParser.parseExpression(name, new ParserContextImpl().eval(target
|
||||
.getClass()));
|
||||
Class targetType;
|
||||
try {
|
||||
targetType = targetAttribute.getValueType(target);
|
||||
} catch (EvaluationException e) {
|
||||
targetType = null;
|
||||
}
|
||||
if (targetType != null) {
|
||||
mapper.addMapping(new Mapping(sourceAttribute, targetAttribute, new RuntimeBindingConversionExecutor(
|
||||
targetType, conversionService), false));
|
||||
mapper.addMapping(new DefaultMapping(sourceAttribute, targetAttribute));
|
||||
}
|
||||
MappingResults results = mapper.map(context.getLastEvent().getAttributes(), target);
|
||||
if (!results.hasErrorResults()) {
|
||||
return success();
|
||||
} else {
|
||||
if (results.getResults(PROPERTY_NOT_FOUND_ERRORS).size() == results.getErrorResults().size()) {
|
||||
// all errors are 'property not found' -- acceptable
|
||||
return success();
|
||||
} else {
|
||||
return error();
|
||||
}
|
||||
}
|
||||
try {
|
||||
mapper.map(context.getLastEvent().getAttributes(), target, new MappingContextImpl(context
|
||||
.getMessageContext()));
|
||||
return success();
|
||||
} catch (AttributeMappingException e) {
|
||||
return error();
|
||||
}
|
||||
|
||||
private static class PropertyNotFoundErrors implements MappingResultsCriteria {
|
||||
public boolean test(MappingResult result) {
|
||||
return result.getResult() instanceof TargetAccessError
|
||||
&& result.getResult().getErrorCode().equals("propertyNotFound");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package org.springframework.webflow.engine;
|
||||
|
||||
import org.springframework.binding.mapping.AttributeMapper;
|
||||
import org.springframework.binding.mapping.MappingContextImpl;
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
@@ -53,7 +53,7 @@ public class EndState extends State {
|
||||
/**
|
||||
* The attribute mapper for mapping output attributes exposed by this end state when it is entered.
|
||||
*/
|
||||
private AttributeMapper outputMapper;
|
||||
private Mapper outputMapper;
|
||||
|
||||
/**
|
||||
* Create a new end state with no associated view.
|
||||
@@ -62,7 +62,7 @@ public class EndState extends State {
|
||||
* @throws IllegalArgumentException when this state cannot be added to given flow, e.g. because the id is not unique
|
||||
* @see State#State(Flow, String)
|
||||
* @see #setFinalResponseAction(Action)
|
||||
* @see #setOutputMapper(AttributeMapper)
|
||||
* @see #setOutputMapper(Mapper)
|
||||
*/
|
||||
public EndState(Flow flow, String id) throws IllegalArgumentException {
|
||||
super(flow, id);
|
||||
@@ -78,7 +78,7 @@ public class EndState extends State {
|
||||
/**
|
||||
* Sets the attribute mapper to use for mapping output attributes exposed by this end state when it is entered.
|
||||
*/
|
||||
public void setOutputMapper(AttributeMapper outputMapper) {
|
||||
public void setOutputMapper(Mapper outputMapper) {
|
||||
this.outputMapper = outputMapper;
|
||||
}
|
||||
|
||||
@@ -113,11 +113,14 @@ public class EndState extends State {
|
||||
* execution request context into a newly created empty map.
|
||||
*/
|
||||
protected LocalAttributeMap createSessionOutput(RequestContext context) {
|
||||
LocalAttributeMap outputMap = new LocalAttributeMap();
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
if (outputMapper != null) {
|
||||
outputMapper.map(context, outputMap, new MappingContextImpl(context.getMessageContext()));
|
||||
MappingResults results = outputMapper.map(context, output);
|
||||
if (results != null && results.hasErrorResults()) {
|
||||
throw new FlowOutputMappingException(getOwner().getId(), getId(), results);
|
||||
}
|
||||
}
|
||||
return outputMap;
|
||||
return output;
|
||||
}
|
||||
|
||||
protected void appendToString(ToStringCreator creator) {
|
||||
|
||||
@@ -25,8 +25,8 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.binding.mapping.AttributeMapper;
|
||||
import org.springframework.binding.mapping.MappingContextImpl;
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
@@ -137,7 +137,7 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
/**
|
||||
* The mapper to map flow input attributes.
|
||||
*/
|
||||
private AttributeMapper inputMapper;
|
||||
private Mapper inputMapper;
|
||||
|
||||
/**
|
||||
* The list of actions to execute when this flow starts.
|
||||
@@ -160,7 +160,7 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
/**
|
||||
* The mapper to map flow output attributes.
|
||||
*/
|
||||
private AttributeMapper outputMapper;
|
||||
private Mapper outputMapper;
|
||||
|
||||
/**
|
||||
* The set of exception handlers for this flow.
|
||||
@@ -388,7 +388,7 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
* Returns the configured flow input mapper, or null if none.
|
||||
* @return the input mapper
|
||||
*/
|
||||
public AttributeMapper getInputMapper() {
|
||||
public Mapper getInputMapper() {
|
||||
return inputMapper;
|
||||
}
|
||||
|
||||
@@ -396,7 +396,7 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
* Sets the mapper to map flow input attributes.
|
||||
* @param inputMapper the input mapper
|
||||
*/
|
||||
public void setInputMapper(AttributeMapper inputMapper) {
|
||||
public void setInputMapper(Mapper inputMapper) {
|
||||
this.inputMapper = inputMapper;
|
||||
}
|
||||
|
||||
@@ -422,7 +422,7 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
* Returns the configured flow output mapper, or null if none.
|
||||
* @return the output mapper
|
||||
*/
|
||||
public AttributeMapper getOutputMapper() {
|
||||
public Mapper getOutputMapper() {
|
||||
return outputMapper;
|
||||
}
|
||||
|
||||
@@ -430,7 +430,7 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
* Sets the mapper to map flow output attributes.
|
||||
* @param outputMapper the output mapper
|
||||
*/
|
||||
public void setOutputMapper(AttributeMapper outputMapper) {
|
||||
public void setOutputMapper(Mapper outputMapper) {
|
||||
this.outputMapper = outputMapper;
|
||||
}
|
||||
|
||||
@@ -500,7 +500,7 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
* <ol>
|
||||
* <li>Create (setup) all registered flow variables ({@link #addVariable(FlowVariable)}) in flow scope.</li>
|
||||
* <li>Map provided input data into the flow. Typically data will be mapped into flow scope using the registered
|
||||
* input mapper ({@link #setInputMapper(AttributeMapper)}).</li>
|
||||
* input mapper ({@link #setInputMapper(Mapper)}).</li>
|
||||
* <li>Execute all registered start actions ({@link #getStartActionList()}).</li>
|
||||
* <li>Enter the configured start state ({@link #setStartState(State)})</li>
|
||||
* </ol>
|
||||
@@ -512,7 +512,10 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
assertStartStateSet();
|
||||
createVariables(context);
|
||||
if (inputMapper != null) {
|
||||
inputMapper.map(input, context, new MappingContextImpl(context.getMessageContext()));
|
||||
MappingResults results = inputMapper.map(input, context);
|
||||
if (results != null && results.hasErrorResults()) {
|
||||
throw new FlowInputMappingException(getId(), results);
|
||||
}
|
||||
}
|
||||
startActionList.execute(context);
|
||||
startState.enter(context);
|
||||
@@ -555,7 +558,7 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
* <ol>
|
||||
* <li>Execute all registered end actions ({@link #getEndActionList()}).</li>
|
||||
* <li>Map data available in the flow execution control context into provided output map using a registered output
|
||||
* mapper ({@link #setOutputMapper(AttributeMapper)}).</li>
|
||||
* mapper ({@link #setOutputMapper(Mapper)}).</li>
|
||||
* </ol>
|
||||
* @param context the flow execution control context
|
||||
* @param output initial output produced by the session that is eligible for modification by this method
|
||||
@@ -564,7 +567,10 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
public void end(RequestControlContext context, MutableAttributeMap output) throws FlowExecutionException {
|
||||
endActionList.execute(context);
|
||||
if (outputMapper != null) {
|
||||
outputMapper.map(context, output, new MappingContextImpl(context.getMessageContext()));
|
||||
MappingResults results = outputMapper.map(context, output);
|
||||
if (results != null && results.hasErrorResults()) {
|
||||
throw new FlowOutputMappingException(getId(), results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.springframework.webflow.engine;
|
||||
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
|
||||
public class FlowAttributeMappingException extends FlowExecutionException {
|
||||
|
||||
private MappingResults results;
|
||||
|
||||
public FlowAttributeMappingException(String flowId, String stateId, MappingResults results, String message) {
|
||||
super(flowId, stateId, message);
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
public MappingResults getMappingResults() {
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.springframework.webflow.engine;
|
||||
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
|
||||
public class FlowInputMappingException extends FlowAttributeMappingException {
|
||||
public FlowInputMappingException(String flowId, MappingResults results) {
|
||||
super(flowId, null, results, "Errors occured during flow input mapping; errors = "
|
||||
+ StylerUtils.style(results.getErrorResults()));
|
||||
}
|
||||
|
||||
public FlowInputMappingException(String flowId, String stateId, MappingResults results) {
|
||||
super(flowId, stateId, results, "Errors occured during flow input mapping; errors = "
|
||||
+ StylerUtils.style(results.getErrorResults()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.springframework.webflow.engine;
|
||||
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
|
||||
public class FlowOutputMappingException extends FlowAttributeMappingException {
|
||||
public FlowOutputMappingException(String flowId, MappingResults results) {
|
||||
this(flowId, null, results);
|
||||
}
|
||||
|
||||
public FlowOutputMappingException(String flowId, String stateId, MappingResults results) {
|
||||
super(flowId, stateId, results, "Errors occured during flow output mapping; errors = "
|
||||
+ StylerUtils.style(results.getErrorResults()));
|
||||
}
|
||||
}
|
||||
@@ -15,12 +15,12 @@ public interface SubflowAttributeMapper {
|
||||
* @param context the current request execution context
|
||||
* @return a map of attributes to pass as input
|
||||
*/
|
||||
public MutableAttributeMap createFlowInput(RequestContext context);
|
||||
public MutableAttributeMap createSubflowInput(RequestContext context);
|
||||
|
||||
/**
|
||||
* Map output attributes of an ended subflow flow to the resuming parent flow.
|
||||
* @param flowOutput the output attributes returned by the ended subflow
|
||||
* @param output the output attributes returned by the ended subflow
|
||||
* @param context the current request execution context, which gives access to the parent flow scope
|
||||
*/
|
||||
public void mapFlowOutput(AttributeMap flowOutput, RequestContext context);
|
||||
public void mapSubflowOutput(AttributeMap output, RequestContext context);
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public class SubflowState extends TransitionableState {
|
||||
protected void doEnter(RequestControlContext context) throws FlowExecutionException {
|
||||
MutableAttributeMap flowInput;
|
||||
if (subflowAttributeMapper != null) {
|
||||
flowInput = subflowAttributeMapper.createFlowInput(context);
|
||||
flowInput = subflowAttributeMapper.createSubflowInput(context);
|
||||
} else {
|
||||
flowInput = new LocalAttributeMap();
|
||||
}
|
||||
@@ -111,7 +111,7 @@ public class SubflowState extends TransitionableState {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Mapping subflow output " + subflowOutput);
|
||||
}
|
||||
subflowAttributeMapper.mapFlowOutput(subflowOutput, context);
|
||||
subflowAttributeMapper.mapSubflowOutput(subflowOutput, context);
|
||||
}
|
||||
return super.handleEvent(context);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package org.springframework.webflow.engine.builder;
|
||||
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.mapping.AttributeMapper;
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.engine.ActionState;
|
||||
import org.springframework.webflow.engine.DecisionState;
|
||||
@@ -179,7 +179,7 @@ public class FlowArtifactFactory {
|
||||
* @return the fully initialized subflow state instance
|
||||
*/
|
||||
public State createEndState(String id, Flow flow, Action[] entryActions, Action finalResponseAction,
|
||||
AttributeMapper outputMapper, FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap attributes) {
|
||||
Mapper outputMapper, FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap attributes) {
|
||||
EndState endState = new EndState(flow, id);
|
||||
if (finalResponseAction != null) {
|
||||
endState.setFinalResponseAction(finalResponseAction);
|
||||
|
||||
@@ -39,9 +39,9 @@ import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.ParserContext;
|
||||
import org.springframework.binding.expression.support.ParserContextImpl;
|
||||
import org.springframework.binding.mapping.AttributeMapper;
|
||||
import org.springframework.binding.mapping.DefaultAttributeMapper;
|
||||
import org.springframework.binding.mapping.Mapping;
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.binding.mapping.impl.DefaultMapper;
|
||||
import org.springframework.binding.mapping.impl.DefaultMapping;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
@@ -194,7 +194,7 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
}
|
||||
|
||||
public void buildInputMapper() throws FlowBuilderException {
|
||||
AttributeMapper inputMapper = parseFlowInputMapper(getDocumentElement());
|
||||
Mapper inputMapper = parseFlowInputMapper(getDocumentElement());
|
||||
if (inputMapper != null) {
|
||||
getFlow().setInputMapper(inputMapper);
|
||||
}
|
||||
@@ -217,7 +217,7 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
}
|
||||
|
||||
public void buildOutputMapper() throws FlowBuilderException {
|
||||
AttributeMapper outputMapper = parseFlowOutputMapper(getDocumentElement());
|
||||
Mapper outputMapper = parseFlowOutputMapper(getDocumentElement());
|
||||
if (outputMapper != null) {
|
||||
getFlow().setOutputMapper(outputMapper);
|
||||
}
|
||||
@@ -376,19 +376,19 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
}
|
||||
}
|
||||
|
||||
private AttributeMapper parseFlowInputMapper(Element element) {
|
||||
private Mapper parseFlowInputMapper(Element element) {
|
||||
Collection inputs = DomUtils.getChildElementsByTagName(element, "input");
|
||||
if (inputs.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
DefaultAttributeMapper inputMapper = new DefaultAttributeMapper();
|
||||
DefaultMapper inputMapper = new DefaultMapper();
|
||||
for (Iterator it = inputs.iterator(); it.hasNext();) {
|
||||
inputMapper.addMapping(parseFlowInputMapping((Element) it.next()));
|
||||
}
|
||||
return inputMapper;
|
||||
}
|
||||
|
||||
private Mapping parseFlowInputMapping(Element element) {
|
||||
private DefaultMapping parseFlowInputMapping(Element element) {
|
||||
ExpressionParser parser = getLocalContext().getExpressionParser();
|
||||
String name = element.getAttribute("name");
|
||||
String value = null;
|
||||
@@ -399,22 +399,25 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
}
|
||||
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));
|
||||
DefaultMapping mapping = new DefaultMapping(source, target);
|
||||
parseAndSetMappingTypeConverter(element, mapping);
|
||||
parseAndSetMappingRequired(element, mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private AttributeMapper parseFlowOutputMapper(Element element) {
|
||||
private Mapper parseFlowOutputMapper(Element element) {
|
||||
Collection inputs = DomUtils.getChildElementsByTagName(element, "output");
|
||||
if (inputs.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
DefaultAttributeMapper outputMapper = new DefaultAttributeMapper();
|
||||
DefaultMapper outputMapper = new DefaultMapper();
|
||||
for (Iterator it = inputs.iterator(); it.hasNext();) {
|
||||
outputMapper.addMapping(parseFlowOutputMapping((Element) it.next()));
|
||||
}
|
||||
return outputMapper;
|
||||
}
|
||||
|
||||
private Mapping parseFlowOutputMapping(Element element) {
|
||||
private DefaultMapping parseFlowOutputMapping(Element element) {
|
||||
ExpressionParser parser = getLocalContext().getExpressionParser();
|
||||
String name = element.getAttribute("name");
|
||||
String value = null;
|
||||
@@ -425,23 +428,25 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
}
|
||||
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));
|
||||
DefaultMapping mapping = new DefaultMapping(source, target);
|
||||
parseAndSetMappingTypeConverter(element, mapping);
|
||||
parseAndSetMappingRequired(element, mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private ConversionExecutor parseMappingConversionExecutor(Element element) {
|
||||
private void parseAndSetMappingTypeConverter(Element element, DefaultMapping mapping) {
|
||||
if (element.hasAttribute("type")) {
|
||||
Class type = (Class) fromStringTo(Class.class).execute(element.getAttribute("type"));
|
||||
return new RuntimeBindingConversionExecutor(type, getConversionService());
|
||||
} else {
|
||||
return null;
|
||||
ConversionExecutor typeConverter = new RuntimeBindingConversionExecutor(type, getConversionService());
|
||||
mapping.setTypeConverter(typeConverter);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean parseMappingRequired(Element element) {
|
||||
private void parseAndSetMappingRequired(Element element, DefaultMapping mapping) {
|
||||
if (element.hasAttribute("required")) {
|
||||
return ((Boolean) fromStringTo(Boolean.class).execute(element.getAttribute("required"))).booleanValue();
|
||||
} else {
|
||||
return false;
|
||||
boolean required = ((Boolean) fromStringTo(Boolean.class).execute(element.getAttribute("required")))
|
||||
.booleanValue();
|
||||
mapping.setRequired(required);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -810,25 +815,25 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
return (SubflowAttributeMapper) getLocalContext().getBeanFactory().getBean(attributeMapperBeanId,
|
||||
SubflowAttributeMapper.class);
|
||||
} else {
|
||||
AttributeMapper inputMapper = parseSubflowInputMapper(element);
|
||||
AttributeMapper outputMapper = parseSubflowOutputMapper(element);
|
||||
Mapper inputMapper = parseSubflowInputMapper(element);
|
||||
Mapper outputMapper = parseSubflowOutputMapper(element);
|
||||
return new GenericSubflowAttributeMapper(inputMapper, outputMapper);
|
||||
}
|
||||
}
|
||||
|
||||
private AttributeMapper parseSubflowInputMapper(Element element) {
|
||||
private Mapper parseSubflowInputMapper(Element element) {
|
||||
Collection inputs = DomUtils.getChildElementsByTagName(element, "input");
|
||||
if (inputs.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
DefaultAttributeMapper inputMapper = new DefaultAttributeMapper();
|
||||
DefaultMapper inputMapper = new DefaultMapper();
|
||||
for (Iterator it = inputs.iterator(); it.hasNext();) {
|
||||
inputMapper.addMapping(parseSubflowInputMapping((Element) it.next()));
|
||||
}
|
||||
return inputMapper;
|
||||
}
|
||||
|
||||
private Mapping parseSubflowInputMapping(Element element) {
|
||||
private DefaultMapping parseSubflowInputMapping(Element element) {
|
||||
ExpressionParser parser = getLocalContext().getExpressionParser();
|
||||
String name = element.getAttribute("name");
|
||||
String value = null;
|
||||
@@ -839,22 +844,25 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
}
|
||||
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));
|
||||
DefaultMapping mapping = new DefaultMapping(source, target);
|
||||
parseAndSetMappingTypeConverter(element, mapping);
|
||||
parseAndSetMappingRequired(element, mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private AttributeMapper parseSubflowOutputMapper(Element element) {
|
||||
private Mapper parseSubflowOutputMapper(Element element) {
|
||||
Collection inputs = DomUtils.getChildElementsByTagName(element, "output");
|
||||
if (inputs.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
DefaultAttributeMapper outputMapper = new DefaultAttributeMapper();
|
||||
DefaultMapper outputMapper = new DefaultMapper();
|
||||
for (Iterator it = inputs.iterator(); it.hasNext();) {
|
||||
outputMapper.addMapping(parseSubflowOutputMapping((Element) it.next()));
|
||||
}
|
||||
return outputMapper;
|
||||
}
|
||||
|
||||
private Mapping parseSubflowOutputMapping(Element element) {
|
||||
private DefaultMapping parseSubflowOutputMapping(Element element) {
|
||||
ExpressionParser parser = getLocalContext().getExpressionParser();
|
||||
String name = element.getAttribute("name");
|
||||
String value = null;
|
||||
@@ -865,7 +873,10 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
}
|
||||
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));
|
||||
DefaultMapping mapping = new DefaultMapping(source, target);
|
||||
parseAndSetMappingTypeConverter(element, mapping);
|
||||
parseAndSetMappingRequired(element, mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private FlowExecutionExceptionHandler[] parseExceptionHandlers(Element element) {
|
||||
|
||||
@@ -17,12 +17,14 @@ package org.springframework.webflow.engine.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.binding.mapping.AttributeMapper;
|
||||
import org.springframework.binding.mapping.MappingContextImpl;
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.engine.FlowInputMappingException;
|
||||
import org.springframework.webflow.engine.FlowOutputMappingException;
|
||||
import org.springframework.webflow.engine.SubflowAttributeMapper;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
@@ -33,33 +35,41 @@ import org.springframework.webflow.execution.RequestContext;
|
||||
*/
|
||||
public final class GenericSubflowAttributeMapper implements SubflowAttributeMapper, Serializable {
|
||||
|
||||
private final AttributeMapper inputMapper;
|
||||
private final Mapper inputMapper;
|
||||
|
||||
private final AttributeMapper outputMapper;
|
||||
private final Mapper outputMapper;
|
||||
|
||||
/**
|
||||
* Create a new flow attribute mapper using given mapping strategies.
|
||||
* @param inputMapper the input mapping strategy
|
||||
* @param outputMapper the output mapping strategy
|
||||
*/
|
||||
public GenericSubflowAttributeMapper(AttributeMapper inputMapper, AttributeMapper outputMapper) {
|
||||
public GenericSubflowAttributeMapper(Mapper inputMapper, Mapper outputMapper) {
|
||||
this.inputMapper = inputMapper;
|
||||
this.outputMapper = outputMapper;
|
||||
}
|
||||
|
||||
public MutableAttributeMap createFlowInput(RequestContext context) {
|
||||
public MutableAttributeMap createSubflowInput(RequestContext context) {
|
||||
if (inputMapper != null) {
|
||||
LocalAttributeMap input = new LocalAttributeMap();
|
||||
inputMapper.map(context, input, new MappingContextImpl(context.getMessageContext()));
|
||||
MappingResults results = inputMapper.map(context, input);
|
||||
if (results != null && results.hasErrorResults()) {
|
||||
throw new FlowInputMappingException(context.getActiveFlow().getId(), context.getCurrentState().getId(),
|
||||
results);
|
||||
}
|
||||
return input;
|
||||
} else {
|
||||
return new LocalAttributeMap();
|
||||
}
|
||||
}
|
||||
|
||||
public void mapFlowOutput(AttributeMap subflowOutput, RequestContext context) {
|
||||
if (outputMapper != null && subflowOutput != null) {
|
||||
outputMapper.map(subflowOutput, context, new MappingContextImpl(context.getMessageContext()));
|
||||
public void mapSubflowOutput(AttributeMap output, RequestContext context) {
|
||||
if (outputMapper != null && output != null) {
|
||||
MappingResults results = outputMapper.map(output, context);
|
||||
if (results != null && results.hasErrorResults()) {
|
||||
throw new FlowOutputMappingException(context.getActiveFlow().getId(),
|
||||
context.getCurrentState().getId(), results);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import javax.el.VariableMapper;
|
||||
import org.springframework.binding.expression.el.DefaultELResolver;
|
||||
import org.springframework.binding.expression.el.ELContextFactory;
|
||||
import org.springframework.binding.expression.el.ELExpressionParser;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
@@ -44,7 +43,6 @@ public class WebFlowELExpressionParser extends ELExpressionParser {
|
||||
public WebFlowELExpressionParser(ExpressionFactory expressionFactory) {
|
||||
super(expressionFactory);
|
||||
putContextFactory(RequestContext.class, new RequestContextELContextFactory());
|
||||
putContextFactory(MutableAttributeMap.class, new AttributeMapELContextFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,17 +63,6 @@ public class WebFlowELExpressionParser extends ELExpressionParser {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures EL context instances for evaluating against an AttributeMap.
|
||||
* @author Keith Donald
|
||||
*/
|
||||
private static class AttributeMapELContextFactory implements ELContextFactory {
|
||||
public ELContext getELContext(Object target) {
|
||||
ELResolver resolver = new DefaultELResolver(target, null);
|
||||
return new WebFlowELContext(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
private static class WebFlowELContext extends ELContext {
|
||||
|
||||
private ELResolver resolver;
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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.action;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.mapping.DefaultAttributeMapper;
|
||||
import org.springframework.binding.mapping.MappingBuilder;
|
||||
import org.springframework.webflow.expression.DefaultExpressionParserFactory;
|
||||
import org.springframework.webflow.test.MockRequestContext;
|
||||
|
||||
/**
|
||||
* Unit test for the {@link AttributeMapperAction}.
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class AttributeMapperActionTests extends TestCase {
|
||||
|
||||
private MappingBuilder mappingBuilder = new MappingBuilder(DefaultExpressionParserFactory.getExpressionParser());
|
||||
|
||||
public void testMapping() throws Exception {
|
||||
DefaultAttributeMapper mapper = new DefaultAttributeMapper();
|
||||
mapper.addMapping(mappingBuilder.source("externalContext.requestParameterMap.foo").target("flowScope.bar")
|
||||
.value());
|
||||
AttributeMapperAction action = new AttributeMapperAction(mapper);
|
||||
|
||||
MockRequestContext context = new MockRequestContext();
|
||||
context.putRequestParameter("foo", "value");
|
||||
|
||||
assertTrue(context.getFlowScope().size() == 0);
|
||||
|
||||
action.execute(context);
|
||||
|
||||
assertEquals(1, context.getFlowScope().size());
|
||||
assertEquals("value", context.getFlowScope().get("bar"));
|
||||
}
|
||||
|
||||
public void testNullIllegalArgument() {
|
||||
try {
|
||||
new AttributeMapperAction(null);
|
||||
fail("Should've thrown illegal argument");
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import org.springframework.binding.convert.support.DefaultConversionService;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.support.ParserContextImpl;
|
||||
import org.springframework.binding.message.Severity;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
@@ -86,11 +85,6 @@ public class BindActionTests extends TestCase {
|
||||
BindBean bean = (BindBean) context.getFlowScope().get("bindTarget");
|
||||
assertEquals("foo", bean.getStringProperty());
|
||||
assertEquals(new Integer(3), bean.getIntegerProperty());
|
||||
assertEquals(1, context.getMessageContext().getMessages().length);
|
||||
assertEquals("integerProperty", context.getMessageContext().getMessages()[0].getSource());
|
||||
assertEquals(Severity.ERROR, context.getMessageContext().getMessages()[0].getSeverity());
|
||||
assertEquals("The 'integerProperty' value is the wrong type", context.getMessageContext().getMessages()[0]
|
||||
.getText());
|
||||
}
|
||||
|
||||
public void testBindWithEmptyAttributes() throws Exception {
|
||||
|
||||
@@ -18,10 +18,12 @@ package org.springframework.webflow.engine;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.support.AbstractGetValueExpression;
|
||||
import org.springframework.binding.mapping.DefaultAttributeMapper;
|
||||
import org.springframework.binding.mapping.Mapping;
|
||||
import org.springframework.binding.mapping.MappingBuilder;
|
||||
import org.springframework.binding.expression.support.ParserContextImpl;
|
||||
import org.springframework.binding.mapping.impl.DefaultMapper;
|
||||
import org.springframework.binding.mapping.impl.DefaultMapping;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.engine.support.DefaultTargetStateResolver;
|
||||
import org.springframework.webflow.engine.support.EventIdTransitionCriteria;
|
||||
@@ -65,10 +67,11 @@ public class EndStateTests extends TestCase {
|
||||
}
|
||||
};
|
||||
EndState state = new EndState(flow, "end");
|
||||
DefaultAttributeMapper mapper = new DefaultAttributeMapper();
|
||||
MappingBuilder builder = new MappingBuilder(DefaultExpressionParserFactory.getExpressionParser());
|
||||
Mapping mapping = builder.source("flowScope.x").target("y").value();
|
||||
mapper.addMapping(mapping);
|
||||
DefaultMapper mapper = new DefaultMapper();
|
||||
ExpressionParser parser = DefaultExpressionParserFactory.getExpressionParser();
|
||||
Expression x = parser.parseExpression("flowScope.x", new ParserContextImpl().eval(RequestContext.class));
|
||||
Expression y = parser.parseExpression("y", new ParserContextImpl().eval(MutableAttributeMap.class));
|
||||
mapper.addMapping(new DefaultMapping(x, y));
|
||||
state.setOutputMapper(mapper);
|
||||
MockRequestControlContext context = new MockRequestControlContext(flow);
|
||||
context.getFlowScope().put("x", "foo");
|
||||
|
||||
@@ -19,11 +19,16 @@ import java.util.ArrayList;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.mapping.DefaultAttributeMapper;
|
||||
import org.springframework.binding.mapping.MappingBuilder;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.support.ParserContextImpl;
|
||||
import org.springframework.binding.mapping.impl.DefaultMapper;
|
||||
import org.springframework.binding.mapping.impl.DefaultMapping;
|
||||
import org.springframework.webflow.TestException;
|
||||
import org.springframework.webflow.action.TestMultiAction;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.engine.support.DefaultTargetStateResolver;
|
||||
import org.springframework.webflow.engine.support.EventIdTransitionCriteria;
|
||||
import org.springframework.webflow.engine.support.TransitionExecutingFlowExecutionExceptionHandler;
|
||||
@@ -194,9 +199,11 @@ public class FlowTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testStartWithMapper() {
|
||||
DefaultAttributeMapper attributeMapper = new DefaultAttributeMapper();
|
||||
MappingBuilder mapping = new MappingBuilder(DefaultExpressionParserFactory.getExpressionParser());
|
||||
attributeMapper.addMapping(mapping.source("attr").target("flowScope.attr").value());
|
||||
DefaultMapper attributeMapper = new DefaultMapper();
|
||||
ExpressionParser parser = DefaultExpressionParserFactory.getExpressionParser();
|
||||
Expression x = parser.parseExpression("attr", new ParserContextImpl().eval(AttributeMap.class));
|
||||
Expression y = parser.parseExpression("flowScope.attr", new ParserContextImpl().eval(RequestContext.class));
|
||||
attributeMapper.addMapping(new DefaultMapping(x, y));
|
||||
flow.setInputMapper(attributeMapper);
|
||||
MockRequestControlContext context = new MockRequestControlContext(flow);
|
||||
LocalAttributeMap sessionInput = new LocalAttributeMap();
|
||||
@@ -206,9 +213,11 @@ public class FlowTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testStartWithMapperButNoInput() {
|
||||
DefaultAttributeMapper attributeMapper = new DefaultAttributeMapper();
|
||||
MappingBuilder mapping = new MappingBuilder(DefaultExpressionParserFactory.getExpressionParser());
|
||||
attributeMapper.addMapping(mapping.source("attr").target("flowScope.attr").value());
|
||||
DefaultMapper attributeMapper = new DefaultMapper();
|
||||
ExpressionParser parser = DefaultExpressionParserFactory.getExpressionParser();
|
||||
Expression x = parser.parseExpression("attr", new ParserContextImpl().eval(AttributeMap.class));
|
||||
Expression y = parser.parseExpression("flowScope.attr", new ParserContextImpl().eval(RequestContext.class));
|
||||
attributeMapper.addMapping(new DefaultMapping(x, y));
|
||||
flow.setInputMapper(attributeMapper);
|
||||
MockRequestControlContext context = new MockRequestControlContext(flow);
|
||||
LocalAttributeMap sessionInput = new LocalAttributeMap();
|
||||
@@ -293,9 +302,11 @@ public class FlowTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testEndWithOutputMapper() {
|
||||
DefaultAttributeMapper attributeMapper = new DefaultAttributeMapper();
|
||||
MappingBuilder mapping = new MappingBuilder(DefaultExpressionParserFactory.getExpressionParser());
|
||||
attributeMapper.addMapping(mapping.source("flowScope.attr").target("attr").value());
|
||||
DefaultMapper attributeMapper = new DefaultMapper();
|
||||
ExpressionParser parser = DefaultExpressionParserFactory.getExpressionParser();
|
||||
Expression x = parser.parseExpression("flowScope.attr", new ParserContextImpl().eval(RequestContext.class));
|
||||
Expression y = parser.parseExpression("attr", new ParserContextImpl().eval(MutableAttributeMap.class));
|
||||
attributeMapper.addMapping(new DefaultMapping(x, y));
|
||||
flow.setOutputMapper(attributeMapper);
|
||||
MockRequestControlContext context = new MockRequestControlContext(flow);
|
||||
context.getFlowScope().put("attr", "foo");
|
||||
|
||||
@@ -15,12 +15,15 @@
|
||||
*/
|
||||
package org.springframework.webflow.engine;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.support.AbstractGetValueExpression;
|
||||
import org.springframework.binding.mapping.AttributeMapper;
|
||||
import org.springframework.binding.mapping.MappingContext;
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.binding.mapping.impl.DefaultMappingResults;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
@@ -65,17 +68,18 @@ public class SubflowStateTests extends TestCase {
|
||||
|
||||
public void testEnterWithInput() {
|
||||
subflowState.setAttributeMapper(new SubflowAttributeMapper() {
|
||||
public MutableAttributeMap createFlowInput(RequestContext context) {
|
||||
public MutableAttributeMap createSubflowInput(RequestContext context) {
|
||||
return new LocalAttributeMap("foo", "bar");
|
||||
}
|
||||
|
||||
public void mapFlowOutput(AttributeMap flowOutput, RequestContext context) {
|
||||
public void mapSubflowOutput(AttributeMap flowOutput, RequestContext context) {
|
||||
}
|
||||
});
|
||||
subflow.setInputMapper(new AttributeMapper() {
|
||||
public void map(Object source, Object target, MappingContext context) {
|
||||
subflow.setInputMapper(new Mapper() {
|
||||
public MappingResults map(Object source, Object target) {
|
||||
MutableAttributeMap map = (MutableAttributeMap) source;
|
||||
assertEquals("bar", map.get("foo"));
|
||||
return new DefaultMappingResults(source, target, Collections.EMPTY_LIST);
|
||||
}
|
||||
});
|
||||
new State(subflow, "whatev") {
|
||||
@@ -88,11 +92,11 @@ public class SubflowStateTests extends TestCase {
|
||||
|
||||
public void testReturnWithOutput() {
|
||||
subflowState.setAttributeMapper(new SubflowAttributeMapper() {
|
||||
public MutableAttributeMap createFlowInput(RequestContext context) {
|
||||
public MutableAttributeMap createSubflowInput(RequestContext context) {
|
||||
return new LocalAttributeMap();
|
||||
}
|
||||
|
||||
public void mapFlowOutput(AttributeMap flowOutput, RequestContext context) {
|
||||
public void mapSubflowOutput(AttributeMap flowOutput, RequestContext context) {
|
||||
assertEquals("bar", flowOutput.get("foo"));
|
||||
}
|
||||
});
|
||||
@@ -101,14 +105,13 @@ public class SubflowStateTests extends TestCase {
|
||||
protected void doEnter(RequestControlContext context) throws FlowExecutionException {
|
||||
}
|
||||
};
|
||||
|
||||
new EndState(subflow, "end");
|
||||
subflow.setOutputMapper(new AttributeMapper() {
|
||||
public void map(Object source, Object target, MappingContext context) {
|
||||
subflow.setOutputMapper(new Mapper() {
|
||||
public MappingResults map(Object source, Object target) {
|
||||
MutableAttributeMap map = (MutableAttributeMap) target;
|
||||
map.put("foo", "bar");
|
||||
return new DefaultMappingResults(source, target, Collections.EMPTY_LIST);
|
||||
}
|
||||
|
||||
});
|
||||
subflowState.enter(context);
|
||||
assertEquals("parent", context.getActiveFlow().getId());
|
||||
|
||||
@@ -21,13 +21,13 @@ import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
class TestSubflowAttributeMapper implements SubflowAttributeMapper {
|
||||
public MutableAttributeMap createFlowInput(RequestContext context) {
|
||||
public MutableAttributeMap createSubflowInput(RequestContext context) {
|
||||
LocalAttributeMap inputMap = new LocalAttributeMap();
|
||||
inputMap.put("childInputAttribute", context.getFlowScope().get("parentInputAttribute"));
|
||||
return inputMap;
|
||||
}
|
||||
|
||||
public void mapFlowOutput(AttributeMap subflowOutput, RequestContext context) {
|
||||
public void mapSubflowOutput(AttributeMap subflowOutput, RequestContext context) {
|
||||
MutableAttributeMap parentAttributes = context.getFlowExecutionContext().getActiveSession().getScope();
|
||||
parentAttributes.put("parentOutputAttribute", subflowOutput.get("childInputAttribute"));
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@ package org.springframework.webflow.engine.builder.xml;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.binding.mapping.AttributeMappingException;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.webflow.action.ExternalRedirectAction;
|
||||
import org.springframework.webflow.action.FlowDefinitionRedirectAction;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
import org.springframework.webflow.engine.FlowInputMappingException;
|
||||
import org.springframework.webflow.engine.FlowOutputMappingException;
|
||||
import org.springframework.webflow.engine.ViewState;
|
||||
import org.springframework.webflow.engine.builder.FlowAssembler;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderException;
|
||||
@@ -17,7 +18,6 @@ import org.springframework.webflow.engine.builder.support.ActionExecutingViewFac
|
||||
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.ViewFactory;
|
||||
import org.springframework.webflow.security.SecurityRule;
|
||||
import org.springframework.webflow.test.MockExternalContext;
|
||||
@@ -122,8 +122,7 @@ public class XmlFlowBuilderTests extends TestCase {
|
||||
try {
|
||||
execution.start(input, context);
|
||||
fail("Should have failed");
|
||||
} catch (FlowExecutionException e) {
|
||||
AttributeMappingException me = (AttributeMappingException) e.getCause();
|
||||
} catch (FlowInputMappingException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,8 +139,7 @@ public class XmlFlowBuilderTests extends TestCase {
|
||||
try {
|
||||
execution.start(input, context);
|
||||
fail("Should have failed");
|
||||
} catch (FlowExecutionException e) {
|
||||
AttributeMappingException me = (AttributeMappingException) e.getCause();
|
||||
} catch (FlowOutputMappingException e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ package org.springframework.webflow.test;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.binding.mapping.AttributeMapper;
|
||||
import org.springframework.binding.mapping.MappingContext;
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.webflow.config.FlowDefinitionResource;
|
||||
import org.springframework.webflow.config.FlowDefinitionResourceFactory;
|
||||
import org.springframework.webflow.context.ExternalContext;
|
||||
@@ -87,10 +87,11 @@ public class SearchFlowExecutionTests extends AbstractXmlFlowExecutionTests {
|
||||
|
||||
protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext) {
|
||||
Flow mockDetailFlow = new Flow("detail-flow");
|
||||
mockDetailFlow.setInputMapper(new AttributeMapper() {
|
||||
public void map(Object source, Object target, MappingContext context) {
|
||||
mockDetailFlow.setInputMapper(new Mapper() {
|
||||
public MappingResults map(Object source, Object target) {
|
||||
assertEquals("id of value 1 not provided as input by calling search flow", new Long(1),
|
||||
((AttributeMap) source).get("id"));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
// test responding to finish result
|
||||
|
||||
Reference in New Issue
Block a user