streamlined mapping system in prepartion for binding fix

This commit is contained in:
Keith Donald
2008-11-11 16:52:24 +00:00
parent 467c2f65b2
commit 708017a73a
17 changed files with 202 additions and 270 deletions

View File

@@ -1,56 +0,0 @@
/*
* Copyright 2004-2008 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.core.style.ToStringCreator;
/**
* A single mapping result within a {@link MappingResults} transaction.
*/
public class MappingResult {
private Mapping mapping;
private Result result;
/**
* Creates a new mapping result.
* @param mapping the mapping that executed
* @param result the result of executing the mapping
*/
public MappingResult(Mapping mapping, Result result) {
this.mapping = mapping;
this.result = result;
}
/**
* Returns the mapping that executed.
*/
public Mapping getMapping() {
return mapping;
}
/**
* Returns the result of executing the mapping.
*/
public Result getResult() {
return result;
}
public String toString() {
return new ToStringCreator(this).append("mapping", mapping).append("result", result).toString();
}
}

View File

@@ -1,45 +0,0 @@
/*
* Copyright 2004-2008 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;
/**
* Exposes information about the result of a single mapping operation.
* @author Keith Donald
*/
public abstract class Result {
/**
* The original value of the source object that was to be mapped. Null if this result is an error on the source
* object.
*/
public abstract Object getOriginalValue();
/**
* The actual value that was mapped to the target object. Null if this result is an error.
*/
public abstract Object getMappedValue();
/**
* Indicates if this result was an error.
*/
public abstract boolean isError();
/**
* If this result was an error, the logical mapping error code; for example "propertyNotFound". Null if this result
* is not an error result.
*/
public abstract String getErrorCode();
}

View File

@@ -19,7 +19,6 @@ import org.springframework.binding.convert.ConversionExecutionException;
import org.springframework.binding.convert.ConversionExecutor;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ValueCoercionException;
import org.springframework.binding.mapping.Mapping;
import org.springframework.util.Assert;
@@ -126,7 +125,7 @@ public class DefaultMapping implements Mapping {
try {
targetValue = typeConverter.execute(sourceValue);
} catch (ConversionExecutionException e) {
context.setTypeConversionErrorResult(e);
context.setTypeConversionErrorResult(sourceValue, e);
return;
}
}
@@ -134,8 +133,6 @@ public class DefaultMapping implements Mapping {
try {
targetExpression.setValue(context.getTarget(), targetValue);
context.setSuccessResult(sourceValue, targetValue);
} catch (ValueCoercionException e) {
context.setTypeConversionErrorResult(e);
} catch (EvaluationException e) {
context.setTargetAccessError(sourceValue, e);
}

View File

@@ -20,9 +20,7 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.binding.convert.ConversionExecutionException;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.ValueCoercionException;
import org.springframework.binding.mapping.Mapping;
import org.springframework.binding.mapping.MappingResult;
import org.springframework.binding.mapping.MappingResults;
@@ -96,7 +94,7 @@ public class DefaultMappingContext {
* was performed
*/
public void setSuccessResult(Object originalValue, Object mappedValue) {
add(new MappingResult(currentMapping, new Success(mappedValue, originalValue)));
add(new Success(currentMapping, mappedValue, originalValue));
}
/**
@@ -105,29 +103,17 @@ public class DefaultMappingContext {
* @param originalValue the original source value that is empty (null or an empty string, typically)
*/
public void setRequiredErrorResult(Object originalValue) {
add(new MappingResult(currentMapping, new RequiredError(originalValue)));
add(new RequiredError(currentMapping, 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 exception the conversion exception that occurred, containing the original source value that could not be
* converted during the mapping attempt, as well as the desired target type to which conversion could not be
* performed
* @param originalValue the original source value that is empty (null or an empty string, typically)
* @param cause the actual type conversion exception that occurred
*/
public void setTypeConversionErrorResult(ConversionExecutionException exception) {
add(new MappingResult(currentMapping, new TypeConversionError(exception)));
}
/**
* 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 exception the coercion exception that occurred, containing the original source value that could not be
* converted during the mapping attempt, as well as the desired target type to which conversion could not be
* performed
*/
public void setTypeConversionErrorResult(ValueCoercionException exception) {
add(new MappingResult(currentMapping, new TypeConversionError(exception)));
public void setTypeConversionErrorResult(Object originalValue, Exception cause) {
add(new TypeConversionError(currentMapping, originalValue, cause));
}
/**
@@ -135,7 +121,7 @@ public class DefaultMappingContext {
* @param error the error that occurred
*/
public void setSourceAccessError(EvaluationException error) {
add(new MappingResult(currentMapping, new SourceAccessError(error)));
add(new SourceAccessError(currentMapping, error));
}
/**
@@ -143,7 +129,7 @@ public class DefaultMappingContext {
* @param error the error that occurred
*/
public void setTargetAccessError(Object originalValue, EvaluationException error) {
add(new MappingResult(currentMapping, new TargetAccessError(originalValue, error)));
add(new TargetAccessError(currentMapping, originalValue, error));
}
/**

View File

@@ -64,7 +64,7 @@ public class DefaultMappingResults implements MappingResults {
Iterator it = mappingResults.iterator();
while (it.hasNext()) {
MappingResult result = (MappingResult) it.next();
if (result.getResult().isError()) {
if (result.isError()) {
return true;
}
}
@@ -76,7 +76,7 @@ public class DefaultMappingResults implements MappingResults {
Iterator it = mappingResults.iterator();
while (it.hasNext()) {
MappingResult result = (MappingResult) it.next();
if (result.getResult().isError()) {
if (result.isError()) {
errorResults.add(result);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2004-2008 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.results;
import org.springframework.binding.mapping.Mapping;
import org.springframework.binding.mapping.MappingResult;
import org.springframework.core.style.ToStringCreator;
/**
* Convenient base class for {@link MappingResult} implementations.
*
* @author Keith Donald
*/
public abstract class AbstractMappingResult implements MappingResult {
private Mapping mapping;
/**
* Creates a new mapping result.
* @param mapping the mapping this result is for.
*/
public AbstractMappingResult(Mapping mapping) {
this.mapping = mapping;
}
public Mapping getMapping() {
return mapping;
}
public abstract String getCode();
public abstract boolean isError();
public abstract Throwable getErrorCause();
public abstract Object getOriginalValue();
public abstract Object getMappedValue();
public String toString() {
ToStringCreator creator = new ToStringCreator(this).append("code", getCode()).append("error", isError());
if (isError()) {
creator.append("errorCause", getErrorCause());
}
creator.append("originalValue", getOriginalValue());
creator.append("mappedValue", getMappedValue());
return creator.toString();
}
}

View File

@@ -15,15 +15,14 @@
*/
package org.springframework.binding.mapping.results;
import org.springframework.binding.mapping.Result;
import org.springframework.core.style.ToStringCreator;
import org.springframework.binding.mapping.Mapping;
/**
* The "required" error result--indicates a required mapping could not be performed because the source value to map was
* empty.
* @author Keith Donald
*/
public class RequiredError extends Result {
public class RequiredError extends AbstractMappingResult {
private Object originalValue;
@@ -31,10 +30,23 @@ public class RequiredError extends Result {
* Creates a new required error result
* @param originalValue the original source value (empty)
*/
public RequiredError(Object originalValue) {
public RequiredError(Mapping mapping, Object originalValue) {
super(mapping);
this.originalValue = originalValue;
}
public String getCode() {
return "required";
}
public boolean isError() {
return true;
}
public Throwable getErrorCause() {
return null;
}
public Object getOriginalValue() {
return originalValue;
}
@@ -43,15 +55,4 @@ public class RequiredError extends Result {
return null;
}
public boolean isError() {
return true;
}
public String getErrorCode() {
return "required";
}
public String toString() {
return new ToStringCreator(this).append("originalValue", originalValue).toString();
}
}

View File

@@ -17,31 +17,40 @@ package org.springframework.binding.mapping.results;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.PropertyNotFoundException;
import org.springframework.binding.mapping.Result;
import org.springframework.core.style.ToStringCreator;
import org.springframework.binding.mapping.Mapping;
/**
* Indicates an exception occurred accessing the source object to be mapped. Used to report source
* {@link PropertyNotFoundException} errors and general {@link EvaluationException} errors.
* @author Keith Donald
*/
public class SourceAccessError extends Result {
public class SourceAccessError extends AbstractMappingResult {
private EvaluationException error;
private EvaluationException cause;
/**
* Creates a new source access error.
* @param error the underlying evaluation exception that occurred
*/
public SourceAccessError(EvaluationException error) {
this.error = error;
public SourceAccessError(Mapping mapping, EvaluationException error) {
super(mapping);
this.cause = error;
}
/**
* Returns the backing source evaluation exception that occurred.
*/
public EvaluationException getException() {
return error;
public String getCode() {
if (cause instanceof PropertyNotFoundException) {
return "propertyNotFound";
} else {
return "evaluationException";
}
}
public boolean isError() {
return true;
}
public Throwable getErrorCause() {
return cause;
}
public Object getOriginalValue() {
@@ -52,20 +61,4 @@ public class SourceAccessError extends Result {
return null;
}
public boolean isError() {
return true;
}
public String getErrorCode() {
if (error instanceof PropertyNotFoundException) {
return "propertyNotFound";
} else {
return "evaluationException";
}
}
public String toString() {
return new ToStringCreator(this).append("errorCode", getErrorCode()).append("message", error.getMessage())
.toString();
}
}

View File

@@ -15,14 +15,13 @@
*/
package org.springframework.binding.mapping.results;
import org.springframework.binding.mapping.Result;
import org.springframework.core.style.ToStringCreator;
import org.springframework.binding.mapping.Mapping;
/**
* Indicates a successful mapping operation.
* @author Keith Donald
*/
public class Success extends Result {
public class Success extends AbstractMappingResult {
private Object mappedValue;
@@ -33,11 +32,24 @@ public class Success extends Result {
* @param mappedValue the successfully mapped value
* @param originalValue the original value
*/
public Success(Object mappedValue, Object originalValue) {
public Success(Mapping mapping, Object mappedValue, Object originalValue) {
super(mapping);
this.mappedValue = mappedValue;
this.originalValue = originalValue;
}
public String getCode() {
return "success";
}
public boolean isError() {
return false;
}
public Throwable getErrorCause() {
return null;
}
public Object getOriginalValue() {
return originalValue;
}
@@ -46,16 +58,4 @@ public class Success extends Result {
return mappedValue;
}
public boolean isError() {
return false;
}
public String getErrorCode() {
return null;
}
public String toString() {
return new ToStringCreator(this).append("originalValue", originalValue).append("mappedValue", mappedValue)
.toString();
}
}

View File

@@ -17,35 +17,47 @@ package org.springframework.binding.mapping.results;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.PropertyNotFoundException;
import org.springframework.binding.mapping.Result;
import org.springframework.core.style.ToStringCreator;
import org.springframework.binding.expression.ValueCoercionException;
import org.springframework.binding.mapping.Mapping;
/**
* Indicates an exception occurred accessing the target object to be mapped to. Used to report source
* {@link PropertyNotFoundException} errors and general {@link EvaluationException} errors.
* @author Keith Donald
*/
public class TargetAccessError extends Result {
public class TargetAccessError extends AbstractMappingResult {
private Object originalValue;
private EvaluationException error;
private EvaluationException cause;
/**
* Creates a new target access error.
* @param originalValue the value that was attempted to be mapped
* @param error the underlying evaluation exception that occurred
* @param cause the underlying evaluation exception that occurred
*/
public TargetAccessError(Object originalValue, EvaluationException error) {
public TargetAccessError(Mapping mapping, Object originalValue, EvaluationException cause) {
super(mapping);
this.originalValue = originalValue;
this.error = error;
this.cause = cause;
}
/**
* Returns the backing target evaluation exception that occurred.
*/
public EvaluationException getException() {
return error;
public String getCode() {
if (cause instanceof PropertyNotFoundException) {
return "propertyNotFound";
} else if (cause instanceof ValueCoercionException) {
return "typeMismatch";
} else {
return "evaluationException";
}
}
public boolean isError() {
return true;
}
public Throwable getErrorCause() {
return cause;
}
public Object getOriginalValue() {
@@ -56,20 +68,4 @@ public class TargetAccessError extends Result {
return null;
}
public boolean isError() {
return true;
}
public String getErrorCode() {
if (error instanceof PropertyNotFoundException) {
return "propertyNotFound";
} else {
return "evaluationException";
}
}
public String toString() {
return new ToStringCreator(this).append("errorCode", getErrorCode()).append("message", error.getMessage())
.toString();
}
}
}

View File

@@ -15,10 +15,7 @@
*/
package org.springframework.binding.mapping.results;
import org.springframework.binding.convert.ConversionExecutionException;
import org.springframework.binding.expression.ValueCoercionException;
import org.springframework.binding.mapping.Result;
import org.springframework.core.style.ToStringCreator;
import org.springframework.binding.mapping.Mapping;
/**
* Indicates a type conversion occurred during a mapping operation.
@@ -26,28 +23,32 @@ import org.springframework.core.style.ToStringCreator;
* @author Keith Donald
* @author Scott Andrews
*/
public class TypeConversionError extends Result {
public class TypeConversionError extends AbstractMappingResult {
private Object originalValue;
private Class targetType;
private Exception exception;
private Exception cause;
/**
* Creates a new type conversion error.
* @param exception the underlying type conversion exception
* @param cause the underlying type conversion exception
*/
public TypeConversionError(ConversionExecutionException exception) {
this.exception = exception;
this.originalValue = exception.getValue();
this.targetType = exception.getTargetClass();
public TypeConversionError(Mapping mapping, Object originalValue, Exception cause) {
super(mapping);
this.originalValue = originalValue;
this.cause = cause;
}
public TypeConversionError(ValueCoercionException exception) {
this.exception = exception;
this.originalValue = exception.getValue();
this.targetType = exception.getTargetClass();
public String getCode() {
return "typeMismatch";
}
public boolean isError() {
return true;
}
public Throwable getErrorCause() {
return cause;
}
public Object getOriginalValue() {
@@ -58,32 +59,4 @@ public class TypeConversionError extends Result {
return null;
}
public boolean isError() {
return true;
}
public String getErrorCode() {
return "typeMismatch";
}
// impl
/**
* Returns the target type of the conversion attempt.
*/
public Class getTargetClass() {
return targetType;
}
/**
* Returns the backing type conversion exception that occurred.
*/
public Exception getException() {
return exception;
}
public String toString() {
return new ToStringCreator(this).append("originalValue", originalValue).append("targetType", targetType)
.append("message", exception.getMessage()).toString();
}
}

View File

@@ -125,7 +125,7 @@ public class MessageContextErrors extends AbstractErrors {
List results = mappingResults.getResults(new FieldErrorResult(field));
if (!results.isEmpty()) {
MappingResult fieldError = (MappingResult) results.get(0);
return fieldError.getResult().getOriginalValue();
return fieldError.getOriginalValue();
}
}
return parseFieldExpression(field).getValue(boundObject);

View File

@@ -24,7 +24,6 @@ import org.springframework.binding.message.MessageContext;
* A context for validation events.
*
* @author Scott Andrews
* @since 2.0.4
*/
public interface ValidationContext {