enhanced mapper subsystem

This commit is contained in:
Keith Donald
2008-03-16 20:53:19 +00:00
parent 3cc4c93eba
commit 4cbb5ac1cf
43 changed files with 968 additions and 631 deletions

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -1,5 +0,0 @@
package org.springframework.binding.mapping;
public class AttributeMappingException extends RuntimeException {
}

View File

@@ -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);
}

View File

@@ -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(&quot;foo&quot;).target(&quot;bar&quot;).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;
}
}

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -0,0 +1,5 @@
package org.springframework.binding.mapping;
public interface MappingResultsCriteria {
public boolean test(MappingResult result);
}

View File

@@ -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();
}

View File

@@ -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() {

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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";
}
}

View File

@@ -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";
}
}

View File

@@ -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;
}
}

View File

@@ -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";
}
}
}

View File

@@ -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";
}
}