/* * 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.impl; 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.mapping.Mapping; 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 * @author Scott Andrews */ public class DefaultMapping implements Mapping { /** * 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 /** * Returns the type conversion executor to use during mapping execution. May be null. */ public ConversionExecutor getTypeConverter() { return typeConverter; } /** * Sets a specific type conversion executor to use during mapping execution. * @param typeConverter the type converter */ public void setTypeConverter(ConversionExecutor typeConverter) { this.typeConverter = typeConverter; } /** * Indicates if this mapping is a required mapping. Default is false. * @param required required status */ public void setRequired(boolean required) { this.required = required; } /** * Execute this mapping. * @param context the mapping context */ public void map(DefaultMappingContext 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(sourceValue); } catch (ConversionExecutionException e) { context.setTypeConversionErrorResult(sourceValue, e); return; } } } 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 sourceExpression + " -> " + targetExpression; } }